Compare commits

..

2 Commits

Author SHA1 Message Date
4945e73588 docs(changelog): update change log to beta.2 2016-01-28 11:34:11 -08:00
8a00a863ac chore(release): bump version to beta.2 2016-01-28 11:27:47 -08:00
189 changed files with 1769 additions and 4264 deletions

View File

@ -36,13 +36,12 @@ env:
matrix:
# 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
# Disable dart dev build, which is timing out after 2h. #6823
# - MODE=dart DART_CHANNEL=dev DART_VERSION=$DART_DEV_VERSION
- MODE=dart 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_ddc 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
- MODE=build_only DART_CHANNEL=stable DART_VERSION=$DART_STABLE_VERSION
@ -53,6 +52,7 @@ matrix:
allow_failures:
- 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"

View File

@ -1,33 +1,3 @@
<a name="2.0.0-beta.3"></a>
# 2.0.0-beta.3 (2016-02-03)
### Bug Fixes
* **bundle:** add angular2/platform/testing/browser to SystemJS testing bundle ([ae7d2ab](https://github.com/angular/angular/commit/ae7d2ab))
* **circle:** pre-dependencies `npm install npm` ([36a0e04](https://github.com/angular/angular/commit/36a0e04)), closes [#6777](https://github.com/angular/angular/issues/6777)
* **dart/transform:** Handle edge cases in ReflectionRemover ([3e9b532](https://github.com/angular/angular/commit/3e9b532)), closes [#6749](https://github.com/angular/angular/issues/6749)
* **docs:** `rxjs/add/operators/map` -> `rxjs/add/operator/map` (no 's'). ([2a302aa](https://github.com/angular/angular/commit/2a302aa))
* **karma:** fix running karma via gulp ([27daeaf](https://github.com/angular/angular/commit/27daeaf))
* **query:** dont cross component boundaries ([c6adbf6](https://github.com/angular/angular/commit/c6adbf6)), closes [#6759](https://github.com/angular/angular/issues/6759)
* **query:** update view queries that query directives in embedded views ([1f7a41c](https://github.com/angular/angular/commit/1f7a41c)), closes [#6747](https://github.com/angular/angular/issues/6747)
* **WebWorkers:** Add support for transitionend events. ([c2a38c0](https://github.com/angular/angular/commit/c2a38c0)), closes [#6649](https://github.com/angular/angular/issues/6649)
* **zone:** correct incorrect calls to zone ([3211938](https://github.com/angular/angular/commit/3211938))
### Features
* **change_detection:** allow all legal programs in the dev mode ([42231f5](https://github.com/angular/angular/commit/42231f5))
* **dart/transform:** Generate all code into <file>.template.dart ([8c36aa8](https://github.com/angular/angular/commit/8c36aa8))
* **debug:** replace DebugElement with new Debug DOM ([e1bf3d3](https://github.com/angular/angular/commit/e1bf3d3))
* **ngFor:** add custom trackBy function support ([cee2318](https://github.com/angular/angular/commit/cee2318)), closes [#6779](https://github.com/angular/angular/issues/6779)
* **upgrade:** support bindToController with binding definitions ([99e6500](https://github.com/angular/angular/commit/99e6500)), closes [#4784](https://github.com/angular/angular/issues/4784)
* **WebWorker:** Add Router Support for WebWorker Apps ([8bea667](https://github.com/angular/angular/commit/8bea667)), closes [#3563](https://github.com/angular/angular/issues/3563)
### Performance Improvements
* **dart/transform:** Only process deferred libs when necessary ([f56df65](https://github.com/angular/angular/commit/f56df65)), closes [#6745](https://github.com/angular/angular/issues/6745)
<a name="2.0.0-beta.2"></a>
# 2.0.0-beta.2 (2016-01-28)
@ -60,10 +30,13 @@
### BREAKING CHANGES
* there's a chance of breakage as router's Instruction constructor
signature changed.
* `Renderer.listen` now has to return a function that
removes the event listener.
* TemplateRef.elementRef is now read-only.
* remove TemplateRef.elementRef setter
* Tests are now required to use `setBaseTestProviders`
to set up. Assuming your tests are run on a browser, setup would change
@ -86,6 +59,7 @@ setBaseTestProviders(TEST_BROWSER_PLATFORM_PROVIDERS,
TEST_BROWSER_APPLICATION_PROVIDERS);
```
* This is very unlikely to be breaking, but I'm still marking just in case. The only change to the user should be that dev mode is driven by Dart's checked mode, like it was in the past.
<a name="2.0.0-beta.1"></a>
# 2.0.0-beta.1 catamorphic-involution (2016-01-08)
@ -132,7 +106,6 @@ setBaseTestProviders(TEST_BROWSER_PLATFORM_PROVIDERS,
take a native element instead of an ElementRef
* `Renderer` interface now operates on plain native nodes,
instead of `RenderElementRef`s or `RenderViewRef`s
<a name="2.0.0-beta.0"></a>
# 2.0.0-beta.0 somnambulant-inauguration (2015-12-15)
@ -154,7 +127,10 @@ setBaseTestProviders(TEST_BROWSER_PLATFORM_PROVIDERS,
### BREAKING CHANGES
* Previously, Angular would run in dev prod mode by default, and you could enable the dev mode by calling enableDevMode. Now, Angular runs in the dev mode by default, and you can enable the prod mode by calling enableProdMode.
* Before
Previously Angular would run in dev prod mode by default, and you could enable the dev mode by calling enableDevMode.
After
Now, Angular runs in the dev mode by default, and you can enable the prod mode by calling enableProdMode.
@ -231,11 +207,11 @@ bundle. `ngUpgrade` has a dedicated `upgrade.js` bundle now.
* `Observable` are no more re-exported from `angular2/core`
Before
Before
```
import {Observable} from 'angular2/core'
```
After
After
```
import {Observable} from 'rxjs/Observable';
```
@ -456,7 +432,7 @@ import * as core from 'angular2/core';
* Operators and Observables from RxJS (e.g. .map(), .toArray(), .toPromise(), etc ) now need to be explicitly imported (once per operator in your app)
```
import {Observable} from 'rxjs/Observable';
import 'rxjs/add/operator/map';
import 'rxjs/add/operators/map';
import 'rxjs/add/observable/interval';
Observable.interval(1000).subscribe(...);

View File

@ -9,7 +9,7 @@ JS and Dart versions. It also explains the basic mechanics of using `git`, `node
* [Installing NPM Modules and Dart Packages](#installing-npm-modules-and-dart-packages)
* [Build commands](#build-commands)
* [Running Tests Locally](#running-tests-locally)
* [Code Style](#code-style)
* [Formatting](#clang-format)
* [Project Information](#project-information)
* [CI using Travis](#ci-using-travis)
* [Transforming Dart code](#transforming-dart-code)
@ -227,9 +227,7 @@ Angular specific command line options when running protractor:
Angular specific command line options when running protractor (e.g. force gc, ...):
`$(npm bin)/protractor protractor-{js|dart2js}-conf.js --ng-help`
## Code Style
### Formatting with <a name="clang-format">clang-format</a>
## Formatting with <a name="clang-format">clang-format</a>
We use [clang-format](http://clang.llvm.org/docs/ClangFormat.html) to automatically enforce code
style for our TypeScript code. This allows us to focus our code reviews more on the content, and
@ -275,14 +273,6 @@ to some whitespace difference.
* `clang-format` integrations are also available for many popular editors (`vim`, `emacs`,
`Sublime Text`, etc.).
### Linting
We use [tslint](https://github.com/palantir/tslint) for linting. See linting rules in [gulpfile](gulpfile.js). To lint, run
```shell
$ gulp lint
```
## Generating the API documentation
The following gulp task will generate the API docs in the `dist/angular.io/partials/api/angular2`:

View File

@ -1,21 +1,6 @@
machine:
node:
version: 5.4.1
dependencies:
pre:
- npm install -g npm
override:
- npm install:
environment:
# Token for tsd to increase github rate limit
# See https://github.com/DefinitelyTyped/tsd#tsdrc
# This is not hidden using https://circleci.com/docs/fork-pr-builds#details
# because those are not visible for pull requests, and those should also be reliable.
# This SSO token belongs to github account angular-github-ratelimit-token which has no access
# (password is in Valentine)
TSD_GITHUB_TOKEN: ef474500309daea53d5991b3079159a29520a40b
test:
override:
- npm run build

View File

@ -155,7 +155,7 @@ var HTTP_BUNDLE_CONTENT = 'angular2/http - rxjs/* - ' + ANGULAR2_BUNDLE_CONFIG.j
var ROUTER_BUNDLE_CONTENT = 'angular2/router + angular2/router/router_link_dsl - rxjs/* - ' +
ANGULAR2_BUNDLE_CONFIG.join(' - ');
var TESTING_BUNDLE_CONTENT =
'angular2/testing + angular2/http/testing + angular2/router/testing + angular2/platform/testing/browser - rxjs/* - ' +
'angular2/testing + angular2/http/testing + angular2/router/testing - rxjs/* - ' +
ANGULAR2_BUNDLE_CONFIG.join(' - ');
var UPGRADE_BUNDLE_CONTENT = 'angular2/upgrade - rxjs/* - ' + ANGULAR2_BUNDLE_CONFIG.join(' - ');
@ -463,7 +463,7 @@ function runKarma(configFile, done) {
gulp.task('test.js', function(done) {
runSequence('test.unit.tools/ci', 'test.transpiler.unittest', 'test.unit.js/ci',
'test.unit.cjs/ci', 'test.typings', 'check-public-api', sequenceComplete(done));
'test.unit.cjs/ci', 'test.typings', sequenceComplete(done));
});
gulp.task('test.dart', function(done) {
@ -627,11 +627,7 @@ gulp.task('!test.unit.router/karma-run', function(done) {
});
});
gulp.task('buildRouter.dev', function() {
var modulesSrcDir = __dirname + '/modules';
var distDir = __dirname + '/dist';
buildRouter(modulesSrcDir, distDir);
});
gulp.task('buildRouter.dev', function() { buildRouter(); });
gulp.task('test.unit.dart', function(done) {
printModulesWarning();
@ -830,7 +826,7 @@ gulp.task('test.unit.js/ci', function(done) {
reporters: ['dots'],
browsers: browserConf.browsersToRun
},
function(err) { done(); })
done)
.start();
});
@ -870,8 +866,6 @@ gulp.task('test.unit.cjs/ci', function(done) {
runJasmineTests(['dist/js/cjs/{angular2,benchpress}/test/**/*_spec.js'], done);
});
gulp.task('check-public-api',
function(done) { runJasmineTests(['dist/tools/public_api_guard/**/*_spec.js'], done); });
gulp.task('test.unit.cjs', ['build/clean.js', 'build.tools'], function(neverDone) {
var watch = require('./tools/build/watch');

View File

@ -21,25 +21,18 @@ var files = [
var PRELUDE = '(function(){\n';
var POSTLUDE = '\n}());\n';
var FACADES = fs.readFileSync(__dirname + '/lib/facades.es5', 'utf8');
var DIRECTIVES = fs.readFileSync(__dirname + '/src/ng_outlet.ts', 'utf8');
var moduleTemplate = fs.readFileSync(__dirname + '/src/module_template.js', 'utf8');
function main(modulesDirectory) {
var angular1RouterModuleDirectory = modulesDirectory + '/angular1_router';
var facades = fs.readFileSync(
angular1RouterModuleDirectory + '/lib/facades.es5', 'utf8');
var directives = fs.readFileSync(
angular1RouterModuleDirectory + '/src/ng_outlet.ts', 'utf8');
var moduleTemplate = fs.readFileSync(
angular1RouterModuleDirectory + '/src/module_template.js', 'utf8');
var dir = modulesDirectory + '/angular2/src/router/';
function main() {
var dir = __dirname + '/../angular2/src/router/';
var sharedCode = files.reduce(function (prev, file) {
return prev + transform(fs.readFileSync(dir + file, 'utf8'));
}, '');
var out = moduleTemplate.replace('//{{FACADES}}', facades)
.replace('//{{SHARED_CODE}}', sharedCode);
return PRELUDE + transform(directives) + out + POSTLUDE;
var out = moduleTemplate.replace('//{{FACADES}}', FACADES).replace('//{{SHARED_CODE}}', sharedCode);
return PRELUDE + transform(DIRECTIVES) + out + POSTLUDE;
}
/*
@ -69,29 +62,10 @@ function isFacadeModule(modulePath) {
modulePath === 'angular2/src/core/reflection/reflection';
}
module.exports = function(modulesDirectory, outputDirectory) {
if (!fs.existsSync(outputDirectory)) {
fs.mkdirSync(outputDirectory);
module.exports = function () {
var dist = __dirname + '/../../dist';
if (!fs.existsSync(dist)) {
fs.mkdirSync(dist);
}
fs.writeFileSync(
outputDirectory + '/angular_1_router.js', main(modulesDirectory));
fs.writeFileSync(dist + '/angular_1_router.js', main());
};
// CLI entry point
if (require.main === module) {
try {
var args = process.argv;
args.shift(); // node
args.shift(); // scriptfile.js
if (args.length < 2) {
console.log("usage: $0 outFile path/to/modules");
process.exit(1);
}
var outfile = args.shift();
var directory = args.shift();
fs.writeFileSync(outfile, main(directory));
} catch (e) {
console.log(e.message);
process.exit(1);
}
}

View File

@ -15,8 +15,9 @@ export './src/core/application_tokens.dart' show APP_ID,
export './src/core/zone.dart';
export './src/core/render.dart';
export './src/core/linker.dart';
export './src/core/debug/debug_node.dart' show DebugElement,
DebugNode,
export './src/core/debug/debug_element.dart' show DebugElement,
Scope,
inspectElement,
asNativeElements;
export './src/core/testability/testability.dart';
export './src/core/change_detection.dart';

View File

@ -20,7 +20,12 @@ export {
export * from './src/core/zone';
export * from './src/core/render';
export * from './src/core/linker';
export {DebugElement, DebugNode, asNativeElements} from './src/core/debug/debug_node';
export {
DebugElement,
Scope,
inspectElement,
asNativeElements
} from './src/core/debug/debug_element';
export * from './src/core/testability/testability';
export * from './src/core/change_detection';
export * from './src/core/platform_directives_and_pipes';

View File

@ -32,7 +32,7 @@ filename | list of barrels | dev/prod | minified?
`angular2-all.umd.js` | `angular2/core`, `angular2/common`, `angular2/compiler`, `angular2/platform/browser`, `angular2/platform/common_dom`, `angular2/http`, `angular2/router`, `angular2/instrumentation`, `angular2/upgrade`| prod | no
`angular2-all.umd.min.js` | `angular2/core`, `angular2/common`, `angular2/compiler`, `angular2/platform/browser`, `angular2/platform/common_dom`, `angular2/http`, `angular2/router`, `angular2/instrumentation`, `angular2/upgrade` | prod | yes
`angular2-all.umd.dev.js` | `angular2/core`, `angular2/common`, `angular2/compiler`, `angular2/platform/browser`, `angular2/platform/common_dom`, `angular2/http`, `angular2/router`, `angular2/instrumentation`, `angular2/upgrade` | dev | no
`angular2-all-testing.umd.dev.js` | `angular2/core`, `angular2/common`, `angular2/compiler`, `angular2/platform/browser`, `angular2/platform/common_dom`, `angular2/http`, `angular2/router`, `angular2/instrumentation`, `angular2/upgrade`, `angular2/testing`, `angular2/http/testing`, `angular2/router/testing`, `angular2/platform/testing/browser` | dev | no
`angular2-all-testing.umd.dev.js` | `angular2/core`, `angular2/common`, `angular2/compiler`, `angular2/platform/browser`, `angular2/platform/common_dom`, `angular2/http`, `angular2/router`, `angular2/instrumentation`, `angular2/upgrade`, `angular2/testing`, `angular2/http/testing`, `angular2/router/testing` | dev | no
**Warning**: bundles in the `UMD` format are _not_ "additive". A single application should use only one bundle from the above list.
@ -55,7 +55,7 @@ filename | list of barrels | dev/prod | minified?
`upgrade.js` | `angular2/upgrade` | prod | no
`upgrade.min.js` | `angular2/upgrade` | prod | yes
`upgrade.dev.js` | `angular2/upgrade` | dev | no
`testing.dev.js` | `angular2/testing`, `angular2/http/testing`, `angular2/router/testing`, `angular2/platform/testing/browser` | dev | no
`testing.dev.js` | `angular2/testing`, `angular2/http/testing`, `angular2/router/testing` | dev | no
**Note**: bundles in the `System.register` format are "additive" - it is quite common to include several bundles in one application.
For example people using Angular 2 with `http` and `router` would include: `angular2.js`, `http.js` and `router.js`.

View File

@ -10,16 +10,16 @@ Routing and navigation
@cheatsheetItem
syntax(ts):
`@RouteConfig([
{ path: '/:myParam', component: MyComponent, name: 'MyCmp' },
{ path: '/staticPath', component: ..., name: ...},
{ path: '/*wildCardParam', component: ..., name: ...}
{ path: '/:myParam', component: MyComponent, as: 'MyCmp' },
{ path: '/staticPath', component: ..., as: ...},
{ path: '/*wildCardParam', component: ..., as: ...}
])
class MyComponent() {}`|`@RouteConfig`
syntax(js):
`var MyComponent = ng.router.RouteConfig([
{ path: '/:myParam', component: MyComponent, name: 'MyCmp' },
{ path: '/staticPath', component: ..., name: ...},
{ path: '/*wildCardParam', component: ..., name: ...}
{ path: '/:myParam', component: MyComponent, as: 'MyCmp' },
{ path: '/staticPath', component: ..., as: ...},
{ path: '/*wildCardParam', component: ..., as: ...}
]).Class({
constructor: function() {}
});`|`ng.router.RouteConfig`

View File

@ -1,8 +1,16 @@
import {DebugElement} from 'angular2/core';
import {DebugElement, Scope} from 'angular2/core';
var debugElement: DebugElement;
var predicate;
// #docregion scope_all
debugElement.query(predicate);
debugElement.query(predicate, Scope.all);
// #enddocregion
// #docregion scope_light
debugElement.query(predicate, Scope.light);
// #enddocregion
// #docregion scope_view
debugElement.query(predicate, Scope.view);
// #enddocregion

View File

@ -1,17 +1,17 @@
import {By} from 'angular2/platform/browser';
import {DebugElement} from 'angular2/core';
import {DebugElement, Scope} from 'angular2/core';
var debugElement: DebugElement;
class MyDirective {}
// #docregion by_all
debugElement.query(By.all());
debugElement.query(By.all(), Scope.all);
// #enddocregion
// #docregion by_css
debugElement.query(By.css('[attribute]'));
debugElement.query(By.css('[attribute]'), Scope.all);
// #enddocregion
// #docregion by_directive
debugElement.query(By.directive(MyDirective));
debugElement.query(By.directive(MyDirective), Scope.all);
// #enddocregion

View File

@ -1,8 +1,8 @@
export {AngularEntrypoint} from 'angular2/src/core/angular_entrypoint';
export {
BROWSER_PROVIDERS,
ELEMENT_PROBE_BINDINGS,
ELEMENT_PROBE_PROVIDERS,
ELEMENT_PROBE_PROVIDERS_PROD_MODE,
inspectNativeElement,
BrowserDomAdapter,
By,

View File

@ -1,8 +1,8 @@
export {AngularEntrypoint} from 'angular2/src/core/angular_entrypoint';
export {
BROWSER_PROVIDERS,
ELEMENT_PROBE_BINDINGS,
ELEMENT_PROBE_PROVIDERS,
ELEMENT_PROBE_PROVIDERS_PROD_MODE,
inspectNativeElement,
BrowserDomAdapter,
By,

View File

@ -12,4 +12,4 @@ export {
EventManagerPlugin
} from 'angular2/src/platform/dom/events/event_manager';
export * from 'angular2/src/platform/dom/debug/by';
export * from 'angular2/src/platform/dom/debug/ng_probe';
export * from 'angular2/src/platform/dom/debug/debug_element_view_listener';

View File

@ -12,5 +12,3 @@ export 'package:angular2/src/web_workers/shared/service_message_broker.dart'
show ReceivedMessage, ServiceMessageBroker, ServiceMessageBrokerFactory;
export 'package:angular2/src/web_workers/shared/serializer.dart' show PRIMITIVE;
export 'package:angular2/src/web_workers/shared/message_bus.dart';
export 'package:angular2/src/web_workers/worker/router_providers.dart'
show WORKER_APP_ROUTER;

View File

@ -8,13 +8,12 @@ export {
ClientMessageBrokerFactory,
FnArg,
UiArguments
} from 'angular2/src/web_workers/shared/client_message_broker';
} from '../src/web_workers/shared/client_message_broker';
export {
ReceivedMessage,
ServiceMessageBroker,
ServiceMessageBrokerFactory
} from 'angular2/src/web_workers/shared/service_message_broker';
export {PRIMITIVE} from 'angular2/src/web_workers/shared/serializer';
export * from 'angular2/src/web_workers/shared/message_bus';
} from '../src/web_workers/shared/service_message_broker';
export {PRIMITIVE} from '../src/web_workers/shared/serializer';
export * from '../src/web_workers/shared/message_bus';
export {AngularEntrypoint} from 'angular2/src/core/angular_entrypoint';
export {WORKER_APP_ROUTER} from 'angular2/src/web_workers/worker/router_providers';

View File

@ -18,9 +18,7 @@ export '../src/web_workers/shared/service_message_broker.dart'
export '../src/web_workers/shared/serializer.dart' show PRIMITIVE;
export '../src/web_workers/shared/message_bus.dart';
export '../src/web_workers/ui/router_providers.dart' show WORKER_RENDER_ROUTER;
import 'package:angular2/src/platform/worker_render_common.dart';
const WORKER_RENDER_APP = WORKER_RENDER_APPLICATION_COMMON;

View File

@ -24,4 +24,3 @@ import {WORKER_RENDER_APPLICATION} from 'angular2/src/platform/worker_render';
* @deprecated Use WORKER_RENDER_APPLICATION
*/
export const WORKER_RENDER_APP = WORKER_RENDER_APPLICATION;
export {WORKER_RENDER_ROUTER} from 'angular2/src/web_workers/ui/router_providers';

View File

@ -20,12 +20,18 @@ export {OnActivate, OnDeactivate, OnReuse, CanDeactivate, CanReuse} from './src/
export {CanActivate} from './src/router/lifecycle_annotations';
export {Instruction, ComponentInstruction} from './src/router/instruction';
export {OpaqueToken} from 'angular2/core';
export {ROUTER_PROVIDERS_COMMON} from 'angular2/src/router/router_providers_common';
export {ROUTER_PROVIDERS, ROUTER_BINDINGS} from 'angular2/src/router/router_providers';
import {PlatformLocation} from './src/router/platform_location';
import {LocationStrategy} from './src/router/location_strategy';
import {PathLocationStrategy} from './src/router/path_location_strategy';
import {Router, RootRouter} from './src/router/router';
import {RouterOutlet} from './src/router/router_outlet';
import {RouterLink} from './src/router/router_link';
import {RouteRegistry, ROUTER_PRIMARY_COMPONENT} from './src/router/route_registry';
import {Location} from './src/router/location';
import {ApplicationRef, provide, OpaqueToken, Provider} from 'angular2/core';
import {CONST_EXPR} from './src/facade/lang';
import {BaseException} from 'angular2/src/facade/exceptions';
/**
* A list of directives. To use the router directives like {@link RouterOutlet} and
@ -50,3 +56,63 @@ import {CONST_EXPR} from './src/facade/lang';
* ```
*/
export const ROUTER_DIRECTIVES: any[] = CONST_EXPR([RouterOutlet, RouterLink]);
/**
* A list of {@link Provider}s. To use the router, you must add this to your application.
*
* ### Example ([live demo](http://plnkr.co/edit/iRUP8B5OUbxCWQ3AcIDm))
*
* ```
* import {Component} from 'angular2/core';
* import {
* ROUTER_DIRECTIVES,
* ROUTER_PROVIDERS,
* RouteConfig
* } from 'angular2/router';
*
* @Component({directives: [ROUTER_DIRECTIVES]})
* @RouteConfig([
* {...},
* ])
* class AppCmp {
* // ...
* }
*
* bootstrap(AppCmp, [ROUTER_PROVIDERS]);
* ```
*/
export const ROUTER_PROVIDERS: any[] = CONST_EXPR([
RouteRegistry,
CONST_EXPR(new Provider(LocationStrategy, {useClass: PathLocationStrategy})),
PlatformLocation,
Location,
CONST_EXPR(new Provider(
Router,
{
useFactory: routerFactory,
deps: CONST_EXPR([RouteRegistry, Location, ROUTER_PRIMARY_COMPONENT, ApplicationRef])
})),
CONST_EXPR(new Provider(
ROUTER_PRIMARY_COMPONENT,
{useFactory: routerPrimaryComponentFactory, deps: CONST_EXPR([ApplicationRef])}))
]);
/**
* Use {@link ROUTER_PROVIDERS} instead.
*
* @deprecated
*/
export const ROUTER_BINDINGS = ROUTER_PROVIDERS;
function routerFactory(registry, location, primaryComponent, appRef) {
var rootRouter = new RootRouter(registry, location, primaryComponent);
appRef.registerDisposeListener(() => rootRouter.dispose());
return rootRouter;
}
function routerPrimaryComponentFactory(app) {
if (app.componentTypes.length == 0) {
throw new BaseException("Bootstrap at least one component before injecting Router.");
}
return app.componentTypes[0];
}

View File

@ -6,8 +6,7 @@ import {
IterableDiffers,
ViewContainerRef,
TemplateRef,
EmbeddedViewRef,
TrackByFn
EmbeddedViewRef
} from 'angular2/core';
import {isPresent, isBlank} from 'angular2/src/facade/lang';
@ -60,11 +59,10 @@ import {isPresent, isBlank} from 'angular2/src/facade/lang';
* See a [live demo](http://plnkr.co/edit/KVuXxDp0qinGDyo307QW?p=preview) for a more detailed
* example.
*/
@Directive({selector: '[ngFor][ngForOf]', inputs: ['ngForTrackBy', 'ngForOf', 'ngForTemplate']})
@Directive({selector: '[ngFor][ngForOf]', inputs: ['ngForOf', 'ngForTemplate']})
export class NgFor implements DoCheck {
/** @internal */
_ngForOf: any;
_ngForTrackBy: TrackByFn;
private _differ: IterableDiffer;
constructor(private _viewContainer: ViewContainerRef, private _templateRef: TemplateRef,
@ -73,7 +71,7 @@ export class NgFor implements DoCheck {
set ngForOf(value: any) {
this._ngForOf = value;
if (isBlank(this._differ) && isPresent(value)) {
this._differ = this._iterableDiffers.find(value).create(this._cdr, this._ngForTrackBy);
this._differ = this._iterableDiffers.find(value).create(this._cdr);
}
}
@ -83,8 +81,6 @@ export class NgFor implements DoCheck {
}
}
set ngForTrackBy(value: TrackByFn) { this._ngForTrackBy = value; }
ngDoCheck() {
if (isPresent(this._differ)) {
var changes = this._differ.diff(this._ngForOf);

View File

@ -57,7 +57,7 @@ class ObservableListDiff extends DefaultIterableDiffer {
class ObservableListDiffFactory implements IterableDifferFactory {
const ObservableListDiffFactory();
bool supports(obj) => obj is ObservableList;
IterableDiffer create(ChangeDetectorRef cdRef, [Function trackByFn]) {
IterableDiffer create(ChangeDetectorRef cdRef) {
return new ObservableListDiff(cdRef);
}
}

View File

@ -15,6 +15,7 @@ import {ResolvedMetadataCache} from 'angular2/src/core/linker/resolved_metadata_
import {AppViewManager} from './linker/view_manager';
import {AppViewManager_} from "./linker/view_manager";
import {ViewResolver} from './linker/view_resolver';
import {AppViewListener} from './linker/view_listener';
import {DirectiveResolver} from './linker/directive_resolver';
import {PipeResolver} from './linker/pipe_resolver';
import {Compiler} from './linker/compiler';
@ -31,6 +32,7 @@ export const APPLICATION_COMMON_PROVIDERS: Array<Type | Provider | any[]> = CONS
APP_ID_RANDOM_PROVIDER,
ResolvedMetadataCache,
new Provider(AppViewManager, {useClass: AppViewManager_}),
AppViewListener,
ViewResolver,
new Provider(IterableDiffers, {useValue: defaultIterableDiffers}),
new Provider(KeyValueDiffers, {useValue: defaultKeyValueDiffers}),

View File

@ -20,6 +20,5 @@ export {
IterableDifferFactory,
KeyValueDiffers,
KeyValueDiffer,
KeyValueDifferFactory,
TrackByFn
KeyValueDifferFactory
} from './change_detection/change_detection';

View File

@ -1,4 +1,4 @@
import {IterableDiffers, IterableDifferFactory, TrackByFn} from './differs/iterable_differs';
import {IterableDiffers, IterableDifferFactory} from './differs/iterable_differs';
import {DefaultIterableDifferFactory} from './differs/default_iterable_differ';
import {KeyValueDiffers, KeyValueDifferFactory} from './differs/keyvalue_differs';
import {DefaultKeyValueDifferFactory} from './differs/default_keyvalue_differ';
@ -37,12 +37,7 @@ export {BindingRecord, BindingTarget} from './binding_record';
export {DirectiveIndex, DirectiveRecord} from './directive_record';
export {DynamicChangeDetector} from './dynamic_change_detector';
export {ChangeDetectorRef} from './change_detector_ref';
export {
IterableDiffers,
IterableDiffer,
IterableDifferFactory,
TrackByFn
} from './differs/iterable_differs';
export {IterableDiffers, IterableDiffer, IterableDifferFactory} from './differs/iterable_differs';
export {KeyValueDiffers, KeyValueDiffer, KeyValueDifferFactory} from './differs/keyvalue_differs';
export {PipeTransform} from './pipe_transform';
export {WrappedValue, SimpleChange} from './change_detection_util';

View File

@ -350,7 +350,6 @@ export class ChangeDetectorJITGenerator {
var condition = `!${pipe}.pure || (${contexOrArgCheck.join(" || ")})`;
var check = `
${this._genThrowOnChangeCheck(oldValue, newValue)}
if (${this.changeDetectionUtilVarName}.looseNotIdentical(${oldValue}, ${newValue})) {
${newValue} = ${this.changeDetectionUtilVarName}.unwrapValue(${newValue})
${this._genChangeMarker(r)}
@ -378,7 +377,6 @@ export class ChangeDetectorJITGenerator {
`;
var check = `
${this._genThrowOnChangeCheck(oldValue, newValue)}
if (${this.changeDetectionUtilVarName}.looseNotIdentical(${oldValue}, ${newValue})) {
${this._genChangeMarker(r)}
${this._genUpdateDirectiveOrElement(r)}
@ -411,6 +409,7 @@ export class ChangeDetectorJITGenerator {
if (!r.lastInBinding) return "";
var newValue = this._names.getLocalName(r.selfIndex);
var oldValue = this._names.getFieldName(r.selfIndex);
var notifyDebug = this.genConfig.logBindingUpdate ? `this.logBindingUpdate(${newValue});` : "";
var br = r.bindingRecord;
@ -418,12 +417,14 @@ export class ChangeDetectorJITGenerator {
var directiveProperty =
`${this._names.getDirectiveName(br.directiveRecord.directiveIndex)}.${br.target.name}`;
return `
${this._genThrowOnChangeCheck(oldValue, newValue)}
${directiveProperty} = ${newValue};
${notifyDebug}
${IS_CHANGED_LOCAL} = true;
`;
} else {
return `
${this._genThrowOnChangeCheck(oldValue, newValue)}
this.notifyDispatcher(${newValue});
${notifyDebug}
`;
@ -434,7 +435,7 @@ export class ChangeDetectorJITGenerator {
_genThrowOnChangeCheck(oldValue: string, newValue: string): string {
if (assertionsEnabled()) {
return `
if (throwOnChange && !${this.changeDetectionUtilVarName}.devModeEqual(${oldValue}, ${newValue})) {
if(throwOnChange) {
this.throwOnChangeError(${oldValue}, ${newValue});
}
`;

View File

@ -4,17 +4,10 @@ import {
isBlank,
Type,
StringWrapper,
looseIdentical,
isPrimitive
looseIdentical
} from 'angular2/src/facade/lang';
import {BaseException} from 'angular2/src/facade/exceptions';
import {
ListWrapper,
MapWrapper,
StringMapWrapper,
isListLikeIterable,
areIterablesEqual
} from 'angular2/src/facade/collection';
import {ListWrapper, MapWrapper, StringMapWrapper} from 'angular2/src/facade/collection';
import {ProtoRecord} from './proto_record';
import {ChangeDetectionStrategy, isDefaultChangeDetectionStrategy} from './constants';
import {implementsOnDestroy} from './pipe_lifecycle_reflector';
@ -221,17 +214,4 @@ export class ChangeDetectionUtil {
}
static looseNotIdentical(a: any, b: any): boolean { return !looseIdentical(a, b); }
static devModeEqual(a: any, b: any): boolean {
if (isListLikeIterable(a) && isListLikeIterable(b)) {
return areIterablesEqual(a, b, ChangeDetectionUtil.devModeEqual);
} else if (!isListLikeIterable(a) && !isPrimitive(a) && !isListLikeIterable(b) &&
!isPrimitive(b)) {
return true;
} else {
return looseIdentical(a, b);
}
}
}

View File

@ -1,6 +1,11 @@
import {CONST} from 'angular2/src/facade/lang';
import {BaseException} from 'angular2/src/facade/exceptions';
import {isListLikeIterable, iterateListLike, ListWrapper} from 'angular2/src/facade/collection';
import {
isListLikeIterable,
iterateListLike,
ListWrapper,
MapWrapper
} from 'angular2/src/facade/collection';
import {
isBlank,
@ -12,21 +17,17 @@ import {
} from 'angular2/src/facade/lang';
import {ChangeDetectorRef} from '../change_detector_ref';
import {IterableDiffer, IterableDifferFactory, TrackByFn} from '../differs/iterable_differs';
import {IterableDiffer, IterableDifferFactory} from '../differs/iterable_differs';
@CONST()
export class DefaultIterableDifferFactory implements IterableDifferFactory {
supports(obj: Object): boolean { return isListLikeIterable(obj); }
create(cdRef: ChangeDetectorRef, trackByFn?: TrackByFn): DefaultIterableDiffer {
return new DefaultIterableDiffer(trackByFn);
}
create(cdRef: ChangeDetectorRef): DefaultIterableDiffer { return new DefaultIterableDiffer(); }
}
var trackByIdentity = (index: number, item: any) => item;
export class DefaultIterableDiffer implements IterableDiffer {
private _length: number = null;
private _collection = null;
private _length: number = null;
// Keeps track of the used records at any point in time (during & across `_check()` calls)
private _linkedRecords: _DuplicateMap = null;
// Keeps track of the removed records at any point in time during `_check()` calls.
@ -41,10 +42,6 @@ export class DefaultIterableDiffer implements IterableDiffer {
private _removalsHead: CollectionChangeRecord = null;
private _removalsTail: CollectionChangeRecord = null;
constructor(private _trackByFn?: TrackByFn) {
this._trackByFn = isPresent(this._trackByFn) ? this._trackByFn : trackByIdentity;
}
get collection() { return this._collection; }
get length(): number { return this._length; }
@ -107,37 +104,31 @@ export class DefaultIterableDiffer implements IterableDiffer {
var mayBeDirty: boolean = false;
var index: number;
var item;
var itemTrackBy;
if (isArray(collection)) {
var list = collection;
this._length = collection.length;
for (index = 0; index < this._length; index++) {
item = list[index];
itemTrackBy = this._trackByFn(index, item);
if (record === null || !looseIdentical(record.trackById, itemTrackBy)) {
record = this._mismatch(record, item, itemTrackBy, index);
if (record === null || !looseIdentical(record.item, item)) {
record = this._mismatch(record, item, index);
mayBeDirty = true;
} else {
if (mayBeDirty) {
// TODO(misko): can we limit this to duplicates only?
record = this._verifyReinsertion(record, item, itemTrackBy, index);
}
record.item = item;
} else if (mayBeDirty) {
// TODO(misko): can we limit this to duplicates only?
record = this._verifyReinsertion(record, item, index);
}
record = record._next;
}
} else {
index = 0;
iterateListLike(collection, (item) => {
itemTrackBy = this._trackByFn(index, item);
if (record === null || !looseIdentical(record.trackById, itemTrackBy)) {
record = this._mismatch(record, item, itemTrackBy, index);
if (record === null || !looseIdentical(record.item, item)) {
record = this._mismatch(record, item, index);
mayBeDirty = true;
} else if (mayBeDirty) {
// TODO(misko): can we limit this to duplicates only?
record = this._verifyReinsertion(record, item, itemTrackBy, index);
record = this._verifyReinsertion(record, item, index);
}
record = record._next;
index++;
@ -199,8 +190,7 @@ export class DefaultIterableDiffer implements IterableDiffer {
*
* @internal
*/
_mismatch(record: CollectionChangeRecord, item: any, itemTrackBy: any,
index: number): CollectionChangeRecord {
_mismatch(record: CollectionChangeRecord, item, index: number): CollectionChangeRecord {
// The previous record after which we will append the current one.
var previousRecord: CollectionChangeRecord;
@ -213,20 +203,19 @@ export class DefaultIterableDiffer implements IterableDiffer {
}
// Attempt to see if we have seen the item before.
record = this._linkedRecords === null ? null : this._linkedRecords.get(itemTrackBy, index);
record = this._linkedRecords === null ? null : this._linkedRecords.get(item, index);
if (record !== null) {
// We have seen this before, we need to move it forward in the collection.
this._moveAfter(record, previousRecord, index);
} else {
// Never seen it, check evicted list.
record = this._unlinkedRecords === null ? null : this._unlinkedRecords.get(itemTrackBy);
record = this._unlinkedRecords === null ? null : this._unlinkedRecords.get(item);
if (record !== null) {
// It is an item which we have evicted earlier: reinsert it back into the list.
this._reinsertAfter(record, previousRecord, index);
} else {
// It is a new item: add it.
record =
this._addAfter(new CollectionChangeRecord(item, itemTrackBy), previousRecord, index);
record = this._addAfter(new CollectionChangeRecord(item), previousRecord, index);
}
}
return record;
@ -259,17 +248,15 @@ export class DefaultIterableDiffer implements IterableDiffer {
*
* @internal
*/
_verifyReinsertion(record: CollectionChangeRecord, item: any, itemTrackBy: any,
index: number): CollectionChangeRecord {
_verifyReinsertion(record: CollectionChangeRecord, item, index: number): CollectionChangeRecord {
var reinsertRecord: CollectionChangeRecord =
this._unlinkedRecords === null ? null : this._unlinkedRecords.get(itemTrackBy);
this._unlinkedRecords === null ? null : this._unlinkedRecords.get(item);
if (reinsertRecord !== null) {
record = this._reinsertAfter(reinsertRecord, record._prev, index);
} else if (record.currentIndex != index) {
record.currentIndex = index;
this._addToMoves(record, index);
}
record.item = item;
return record;
}
@ -470,20 +457,31 @@ export class DefaultIterableDiffer implements IterableDiffer {
}
toString(): string {
var record: CollectionChangeRecord;
var list = [];
this.forEachItem((record) => list.push(record));
for (record = this._itHead; record !== null; record = record._next) {
list.push(record);
}
var previous = [];
this.forEachPreviousItem((record) => previous.push(record));
for (record = this._previousItHead; record !== null; record = record._nextPrevious) {
previous.push(record);
}
var additions = [];
this.forEachAddedItem((record) => additions.push(record));
for (record = this._additionsHead; record !== null; record = record._nextAdded) {
additions.push(record);
}
var moves = [];
this.forEachMovedItem((record) => moves.push(record));
for (record = this._movesHead; record !== null; record = record._nextMoved) {
moves.push(record);
}
var removals = [];
this.forEachRemovedItem((record) => removals.push(record));
for (record = this._removalsHead; record !== null; record = record._nextRemoved) {
removals.push(record);
}
return "collection: " + list.join(', ') + "\n" + "previous: " + previous.join(', ') + "\n" +
"additions: " + additions.join(', ') + "\n" + "moves: " + moves.join(', ') + "\n" +
@ -514,7 +512,7 @@ export class CollectionChangeRecord {
/** @internal */
_nextMoved: CollectionChangeRecord = null;
constructor(public item: any, public trackById: any) {}
constructor(public item: any) {}
toString(): string {
return this.previousIndex === this.currentIndex ?
@ -552,13 +550,13 @@ class _DuplicateItemRecordList {
}
}
// Returns a CollectionChangeRecord having CollectionChangeRecord.trackById == trackById and
// Returns a CollectionChangeRecord having CollectionChangeRecord.item == item and
// CollectionChangeRecord.currentIndex >= afterIndex
get(trackById: any, afterIndex: number): CollectionChangeRecord {
get(item: any, afterIndex: number): CollectionChangeRecord {
var record: CollectionChangeRecord;
for (record = this._head; record !== null; record = record._nextDup) {
if ((afterIndex === null || afterIndex < record.currentIndex) &&
looseIdentical(record.trackById, trackById)) {
looseIdentical(record.item, item)) {
return record;
}
}
@ -601,7 +599,7 @@ class _DuplicateMap {
put(record: CollectionChangeRecord) {
// todo(vicb) handle corner cases
var key = getMapKey(record.trackById);
var key = getMapKey(record.item);
var duplicates = this.map.get(key);
if (!isPresent(duplicates)) {
@ -612,17 +610,17 @@ class _DuplicateMap {
}
/**
* Retrieve the `value` using key. Because the CollectionChangeRecord value may be one which we
* Retrieve the `value` using key. Because the CollectionChangeRecord value maybe one which we
* have already iterated over, we use the afterIndex to pretend it is not there.
*
* Use case: `[a, b, c, a, a]` if we are at index `3` which is the second `a` then asking if we
* have any more `a`s needs to return the last `a` not the first or second.
*/
get(trackById: any, afterIndex: number = null): CollectionChangeRecord {
var key = getMapKey(trackById);
get(value: any, afterIndex: number = null): CollectionChangeRecord {
var key = getMapKey(value);
var recordList = this.map.get(key);
return isBlank(recordList) ? null : recordList.get(trackById, afterIndex);
return isBlank(recordList) ? null : recordList.get(value, afterIndex);
}
/**
@ -631,7 +629,7 @@ class _DuplicateMap {
* The list of duplicates also is removed from the map if it gets empty.
*/
remove(record: CollectionChangeRecord): CollectionChangeRecord {
var key = getMapKey(record.trackById);
var key = getMapKey(record.item);
// todo(vicb)
// assert(this.map.containsKey(key));
var recordList: _DuplicateItemRecordList = this.map.get(key);

View File

@ -13,19 +13,12 @@ export interface IterableDiffer {
onDestroy();
}
/**
* An optional function passed into {@link NgFor} that defines how to track
* items in an iterable (e.g. by index or id)
*/
export interface TrackByFn { (index: number, item: any): any; }
/**
* Provides a factory for {@link IterableDiffer}.
*/
export interface IterableDifferFactory {
supports(objects: any): boolean;
create(cdRef: ChangeDetectorRef, trackByFn?: TrackByFn): IterableDiffer;
create(cdRef: ChangeDetectorRef): IterableDiffer;
}
/**

View File

@ -304,10 +304,7 @@ export class DynamicChangeDetector extends AbstractChangeDetector<any> {
if (proto.shouldBeChecked()) {
var prevValue = this._readSelf(proto, values);
var detectedChange = throwOnChange ?
!ChangeDetectionUtil.devModeEqual(prevValue, currValue) :
ChangeDetectionUtil.looseNotIdentical(prevValue, currValue);
if (detectedChange) {
if (ChangeDetectionUtil.looseNotIdentical(prevValue, currValue)) {
if (proto.lastInBinding) {
var change = ChangeDetectionUtil.simpleChange(prevValue, currValue);
if (throwOnChange) this.throwOnChangeError(prevValue, currValue);
@ -408,10 +405,7 @@ export class DynamicChangeDetector extends AbstractChangeDetector<any> {
if (proto.shouldBeChecked()) {
var prevValue = this._readSelf(proto, values);
var detectedChange = throwOnChange ?
!ChangeDetectionUtil.devModeEqual(prevValue, currValue) :
ChangeDetectionUtil.looseNotIdentical(prevValue, currValue);
if (detectedChange) {
if (ChangeDetectionUtil.looseNotIdentical(prevValue, currValue)) {
currValue = ChangeDetectionUtil.unwrapValue(currValue);
if (proto.lastInBinding) {

View File

@ -0,0 +1,248 @@
import {Type, isPresent, isBlank} from 'angular2/src/facade/lang';
import {ListWrapper, MapWrapper, Predicate} from 'angular2/src/facade/collection';
import {unimplemented} from 'angular2/src/facade/exceptions';
import {AppElement} from 'angular2/src/core/linker/element';
import {AppView} from 'angular2/src/core/linker/view';
import {ElementRef, ElementRef_} from 'angular2/src/core/linker/element_ref';
/**
* A DebugElement contains information from the Angular compiler about an
* element and provides access to the corresponding ElementInjector and
* underlying DOM Element, as well as a way to query for children.
*
* A DebugElement can be obtained from a {@link ComponentFixture} or from an
* {@link ElementRef} via {@link inspectElement}.
*/
export abstract class DebugElement {
/**
* Return the instance of the component associated with this element, if any.
*/
get componentInstance(): any { return unimplemented(); };
/**
* Return the native HTML element for this DebugElement.
*/
get nativeElement(): any { return unimplemented(); };
/**
* Return an Angular {@link ElementRef} for this element.
*/
get elementRef(): ElementRef { return unimplemented(); };
/**
* Get the directive active for this element with the given index, if any.
*/
abstract getDirectiveInstance(directiveIndex: number): any;
/**
* Get child DebugElements from within the Light DOM.
*
* @return {DebugElement[]}
*/
get children(): DebugElement[] { return unimplemented(); };
/**
* Get the root DebugElement children of a component. Returns an empty
* list if the current DebugElement is not a component root.
*
* @return {DebugElement[]}
*/
get componentViewChildren(): DebugElement[] { return unimplemented(); };
/**
* Simulate an event from this element as if the user had caused
* this event to fire from the page.
*/
abstract triggerEventHandler(eventName: string, eventObj: Event): void;
/**
* Check whether the element has a directive with the given type.
*/
abstract hasDirective(type: Type): boolean;
/**
* Inject the given type from the element injector.
*/
abstract inject(type: Type): any;
/**
* Read a local variable from the element (e.g. one defined with `#variable`).
*/
abstract getLocal(name: string): any;
/**
* Return the first descendant TestElement matching the given predicate
* and scope.
*
* @param {Function: boolean} predicate
* @param {Scope} scope
*
* @return {DebugElement}
*/
query(predicate: Predicate<DebugElement>, scope: Function = Scope.all): DebugElement {
var results = this.queryAll(predicate, scope);
return results.length > 0 ? results[0] : null;
}
/**
* Return descendant TestElememts matching the given predicate
* and scope.
*
* @param {Function: boolean} predicate
* @param {Scope} scope
*
* @return {DebugElement[]}
*/
queryAll(predicate: Predicate<DebugElement>, scope: Function = Scope.all): DebugElement[] {
var elementsInScope: any[] = scope(this);
return elementsInScope.filter(predicate);
}
}
export class DebugElement_ extends DebugElement {
constructor(private _appElement: AppElement) { super(); }
get componentInstance(): any {
if (!isPresent(this._appElement)) {
return null;
}
return this._appElement.getComponent();
}
get nativeElement(): any { return this.elementRef.nativeElement; }
get elementRef(): ElementRef { return this._appElement.ref; }
getDirectiveInstance(directiveIndex: number): any {
return this._appElement.getDirectiveAtIndex(directiveIndex);
}
get children(): DebugElement[] {
return this._getChildElements(this._appElement.parentView, this._appElement);
}
get componentViewChildren(): DebugElement[] {
if (!isPresent(this._appElement.componentView)) {
// The current element is not a component.
return [];
}
return this._getChildElements(this._appElement.componentView, null);
}
triggerEventHandler(eventName: string, eventObj: Event): void {
this._appElement.parentView.triggerEventHandlers(eventName, eventObj,
this._appElement.proto.index);
}
hasDirective(type: Type): boolean {
if (!isPresent(this._appElement)) {
return false;
}
return this._appElement.hasDirective(type);
}
inject(type: Type): any {
if (!isPresent(this._appElement)) {
return null;
}
return this._appElement.get(type);
}
getLocal(name: string): any { return this._appElement.parentView.locals.get(name); }
/** @internal */
_getChildElements(view: AppView, parentAppElement: AppElement): DebugElement[] {
var els = [];
for (var i = 0; i < view.appElements.length; ++i) {
var appEl = view.appElements[i];
if (appEl.parent == parentAppElement) {
els.push(new DebugElement_(appEl));
var views = appEl.nestedViews;
if (isPresent(views)) {
views.forEach(
(nextView) => { els = els.concat(this._getChildElements(nextView, null)); });
}
}
}
return els;
}
}
/**
* Returns a {@link DebugElement} for an {@link ElementRef}.
*
* @param {ElementRef}: elementRef
* @return {DebugElement}
*/
export function inspectElement(elementRef: ElementRef): DebugElement {
return new DebugElement_((<ElementRef_>elementRef).internalElement);
}
/**
* Maps an array of {@link DebugElement}s to an array of native DOM elements.
*/
export function asNativeElements(arr: DebugElement[]): any[] {
return arr.map((debugEl) => debugEl.nativeElement);
}
/**
* Set of scope functions used with {@link DebugElement}'s query functionality.
*/
export class Scope {
/**
* Scope queries to both the light dom and view of an element and its
* children.
*
* ## Example
*
* {@example core/debug/ts/debug_element/debug_element.ts region='scope_all'}
*/
static all(debugElement: DebugElement): DebugElement[] {
var scope = [];
scope.push(debugElement);
debugElement.children.forEach(child => scope = scope.concat(Scope.all(child)));
debugElement.componentViewChildren.forEach(child => scope = scope.concat(Scope.all(child)));
return scope;
}
/**
* Scope queries to the light dom of an element and its children.
*
* ## Example
*
* {@example core/debug/ts/debug_element/debug_element.ts region='scope_light'}
*/
static light(debugElement: DebugElement): DebugElement[] {
var scope = [];
debugElement.children.forEach(child => {
scope.push(child);
scope = scope.concat(Scope.light(child));
});
return scope;
}
/**
* Scope queries to the view of an element of its children.
*
* ## Example
*
* {@example core/debug/ts/debug_element/debug_element.ts region='scope_view'}
*/
static view(debugElement: DebugElement): DebugElement[] {
var scope = [];
debugElement.componentViewChildren.forEach(child => {
scope.push(child);
scope = scope.concat(Scope.light(child));
});
return scope;
}
}

View File

@ -1,171 +0,0 @@
import {isPresent} from 'angular2/src/facade/lang';
import {Predicate} from 'angular2/src/facade/collection';
import {Injector} from 'angular2/src/core/di';
import {ListWrapper, MapWrapper} from 'angular2/src/facade/collection';
import {RenderDebugInfo} from 'angular2/src/core/render/api';
export class EventListener { constructor(public name: string, public callback: Function){}; }
export class DebugNode {
nativeNode: any;
listeners: EventListener[];
parent: DebugElement;
providerTokens: any[];
locals: Map<string, any>;
injector: Injector;
componentInstance: any;
constructor(nativeNode: any, parent: DebugNode) {
this.nativeNode = nativeNode;
if (isPresent(parent) && parent instanceof DebugElement) {
parent.addChild(this);
} else {
this.parent = null;
}
this.listeners = [];
this.providerTokens = [];
}
setDebugInfo(info: RenderDebugInfo) {
this.injector = info.injector;
this.providerTokens = info.providerTokens;
this.locals = info.locals;
this.componentInstance = info.component;
}
inject(token: any): any { return this.injector.get(token); }
getLocal(name: string): any { return this.locals.get(name); }
}
export class DebugElement extends DebugNode {
name: string;
properties: Map<string, any>;
attributes: Map<string, any>;
childNodes: DebugNode[];
nativeElement: any;
constructor(nativeNode: any, parent: any) {
super(nativeNode, parent);
this.properties = new Map<string, any>();
this.attributes = new Map<string, any>();
this.childNodes = [];
this.nativeElement = nativeNode;
}
addChild(child: DebugNode) {
if (isPresent(child)) {
this.childNodes.push(child);
child.parent = this;
}
}
removeChild(child: DebugNode) {
var childIndex = this.childNodes.indexOf(child);
if (childIndex !== -1) {
child.parent = null;
this.childNodes.splice(childIndex, 1);
}
}
insertChildrenAfter(child: DebugNode, newChildren: DebugNode[]) {
var siblingIndex = this.childNodes.indexOf(child);
if (siblingIndex !== -1) {
var previousChildren = this.childNodes.slice(0, siblingIndex + 1);
var nextChildren = this.childNodes.slice(siblingIndex + 1);
this.childNodes =
ListWrapper.concat(ListWrapper.concat(previousChildren, newChildren), nextChildren);
for (var i = 0; i < newChildren.length; ++i) {
var newChild = newChildren[i];
if (isPresent(newChild.parent)) {
newChild.parent.removeChild(newChild);
}
newChild.parent = this;
}
}
}
query(predicate: Predicate<DebugElement>): DebugElement {
var results = this.queryAll(predicate);
return results.length > 0 ? results[0] : null;
}
queryAll(predicate: Predicate<DebugElement>): DebugElement[] {
var matches = [];
_queryElementChildren(this, predicate, matches);
return matches;
}
queryAllNodes(predicate: Predicate<DebugNode>): DebugNode[] {
var matches = [];
_queryNodeChildren(this, predicate, matches);
return matches;
}
get children(): DebugElement[] {
var children = [];
this.childNodes.forEach((node) => {
if (node instanceof DebugElement) {
children.push(node);
}
});
return children;
}
triggerEventHandler(eventName: string, eventObj: Event) {
this.listeners.forEach((listener) => {
if (listener.name == eventName) {
listener.callback(eventObj);
}
});
}
}
export function asNativeElements(debugEls: DebugElement[]): any {
return debugEls.map((el) => el.nativeElement);
}
function _queryElementChildren(element: DebugElement, predicate: Predicate<DebugElement>,
matches: DebugElement[]) {
element.childNodes.forEach(node => {
if (node instanceof DebugElement) {
if (predicate(node)) {
matches.push(node);
}
_queryElementChildren(node, predicate, matches);
}
});
}
function _queryNodeChildren(parentNode: DebugNode, predicate: Predicate<DebugNode>,
matches: DebugNode[]) {
if (parentNode instanceof DebugElement) {
parentNode.childNodes.forEach(node => {
if (predicate(node)) {
matches.push(node);
}
if (node instanceof DebugElement) {
_queryNodeChildren(node, predicate, matches);
}
});
}
}
// Need to keep the nodes in a global Map so that multiple angular apps are supported.
var _nativeNodeToDebugNode = new Map<any, DebugNode>();
export function getDebugNode(nativeNode: any): DebugNode {
return _nativeNodeToDebugNode.get(nativeNode);
}
export function getAllDebugNodes(): DebugNode[] {
return MapWrapper.values(_nativeNodeToDebugNode);
}
export function indexDebugNode(node: DebugNode) {
_nativeNodeToDebugNode.set(node.nativeNode, node);
}
export function removeDebugNodeFromIndex(node: DebugNode) {
_nativeNodeToDebugNode.delete(node.nativeNode);
}

View File

@ -1,157 +0,0 @@
import {isPresent} from 'angular2/src/facade/lang';
import {
Renderer,
RootRenderer,
RenderComponentType,
RenderDebugInfo
} from 'angular2/src/core/render/api';
import {
DebugNode,
DebugElement,
EventListener,
getDebugNode,
indexDebugNode,
removeDebugNodeFromIndex
} from 'angular2/src/core/debug/debug_node';
export class DebugDomRootRenderer implements RootRenderer {
constructor(private _delegate: RootRenderer) {}
renderComponent(componentProto: RenderComponentType): Renderer {
return new DebugDomRenderer(this, this._delegate.renderComponent(componentProto));
}
}
export class DebugDomRenderer implements Renderer {
constructor(private _rootRenderer: DebugDomRootRenderer, private _delegate: Renderer) {}
renderComponent(componentType: RenderComponentType): Renderer {
return this._rootRenderer.renderComponent(componentType);
}
selectRootElement(selector: string): any {
var nativeEl = this._delegate.selectRootElement(selector);
var debugEl = new DebugElement(nativeEl, null);
indexDebugNode(debugEl);
return nativeEl;
}
createElement(parentElement: any, name: string): any {
var nativeEl = this._delegate.createElement(parentElement, name);
var debugEl = new DebugElement(nativeEl, getDebugNode(parentElement));
debugEl.name = name;
indexDebugNode(debugEl);
return nativeEl;
}
createViewRoot(hostElement: any): any { return this._delegate.createViewRoot(hostElement); }
createTemplateAnchor(parentElement: any): any {
var comment = this._delegate.createTemplateAnchor(parentElement);
var debugEl = new DebugNode(comment, getDebugNode(parentElement));
indexDebugNode(debugEl);
return comment;
}
createText(parentElement: any, value: string): any {
var text = this._delegate.createText(parentElement, value);
var debugEl = new DebugNode(text, getDebugNode(parentElement));
indexDebugNode(debugEl);
return text;
}
projectNodes(parentElement: any, nodes: any[]) {
var debugParent = getDebugNode(parentElement);
if (isPresent(debugParent) && debugParent instanceof DebugElement) {
nodes.forEach((node) => { debugParent.addChild(getDebugNode(node)); });
}
return this._delegate.projectNodes(parentElement, nodes);
}
attachViewAfter(node: any, viewRootNodes: any[]) {
var debugNode = getDebugNode(node);
if (isPresent(debugNode)) {
var debugParent = debugNode.parent;
if (viewRootNodes.length > 0 && isPresent(debugParent)) {
var debugViewRootNodes = [];
viewRootNodes.forEach((rootNode) => debugViewRootNodes.push(getDebugNode(rootNode)));
debugParent.insertChildrenAfter(debugNode, debugViewRootNodes);
}
}
return this._delegate.attachViewAfter(node, viewRootNodes);
}
detachView(viewRootNodes: any[]) {
viewRootNodes.forEach((node) => {
var debugNode = getDebugNode(node);
if (isPresent(debugNode) && isPresent(debugNode.parent)) {
debugNode.parent.removeChild(debugNode);
}
});
return this._delegate.detachView(viewRootNodes);
}
destroyView(hostElement: any, viewAllNodes: any[]) {
viewAllNodes.forEach((node) => { removeDebugNodeFromIndex(getDebugNode(node)); });
return this._delegate.destroyView(hostElement, viewAllNodes);
}
listen(renderElement: any, name: string, callback: Function) {
var debugEl = getDebugNode(renderElement);
if (isPresent(debugEl)) {
debugEl.listeners.push(new EventListener(name, callback));
}
return this._delegate.listen(renderElement, name, callback);
}
listenGlobal(target: string, name: string, callback: Function): Function {
return this._delegate.listenGlobal(target, name, callback);
}
setElementProperty(renderElement: any, propertyName: string, propertyValue: any) {
var debugEl = getDebugNode(renderElement);
if (isPresent(debugEl) && debugEl instanceof DebugElement) {
debugEl.properties.set(propertyName, propertyValue);
}
return this._delegate.setElementProperty(renderElement, propertyName, propertyValue);
}
setElementAttribute(renderElement: any, attributeName: string, attributeValue: string) {
var debugEl = getDebugNode(renderElement);
if (isPresent(debugEl) && debugEl instanceof DebugElement) {
debugEl.attributes.set(attributeName, attributeValue);
}
return this._delegate.setElementAttribute(renderElement, attributeName, attributeValue);
}
/**
* Used only in debug mode to serialize property changes to comment nodes,
* such as <template> placeholders.
*/
setBindingDebugInfo(renderElement: any, propertyName: string, propertyValue: string) {
return this._delegate.setBindingDebugInfo(renderElement, propertyName, propertyValue);
}
/**
* Used only in development mode to set information needed by the DebugNode for this element.
*/
setElementDebugInfo(renderElement: any, info: RenderDebugInfo) {
var debugEl = getDebugNode(renderElement);
debugEl.setDebugInfo(info);
return this._delegate.setElementDebugInfo(renderElement, info);
}
setElementClass(renderElement: any, className: string, isAdd: boolean) {
return this._delegate.setElementClass(renderElement, className, isAdd);
}
setElementStyle(renderElement: any, styleName: string, styleValue: string) {
return this._delegate.setElementStyle(renderElement, styleName, styleValue);
}
invokeElementMethod(renderElement: any, methodName: string, args: any[]) {
return this._delegate.invokeElementMethod(renderElement, methodName, args);
}
setText(renderNode: any, text: string) { return this._delegate.setText(renderNode, text); }
}

View File

@ -463,11 +463,7 @@ export class AppElement implements DependencyProvider, ElementRef, AfterViewChec
var inj: AppElement = this;
while (isPresent(inj)) {
inj._setQueriesAsDirty();
if (isBlank(inj.parent) && inj.parentView.proto.type === ViewType.EMBEDDED) {
inj = inj.parentView.containerAppElement;
} else {
inj = inj.parent;
}
inj = inj.parent;
}
}

View File

@ -27,7 +27,7 @@ import {
CONST_EXPR
} from 'angular2/src/facade/lang';
import {BaseException, WrappedException} from 'angular2/src/facade/exceptions';
import {Renderer, RootRenderer, RenderDebugInfo} from 'angular2/src/core/render/api';
import {Renderer, RootRenderer} from 'angular2/src/core/render/api';
import {ViewRef_, HostViewFactoryRef} from './view_ref';
import {ProtoPipes} from 'angular2/src/core/pipes/pipes';
import {camelCaseToDashCase} from 'angular2/src/core/render/util';
@ -119,12 +119,6 @@ export class AppView implements ChangeDispatcher {
(templateName, _) => { localsMap.set(templateName, null); });
for (var i = 0; i < appElements.length; i++) {
var appEl = appElements[i];
var providerTokens = [];
if (isPresent(appEl.proto.protoInjector)) {
for (var j = 0; j < appEl.proto.protoInjector.numberOfProviders; j++) {
providerTokens.push(appEl.proto.protoInjector.getProviderAtIndex(j).key.token);
}
}
StringMapWrapper.forEach(appEl.proto.directiveVariableBindings, (directiveIndex, name) => {
if (isBlank(directiveIndex)) {
localsMap.set(name, appEl.nativeElement);
@ -132,9 +126,6 @@ export class AppView implements ChangeDispatcher {
localsMap.set(name, appEl.getDirectiveAtIndex(directiveIndex));
}
});
this.renderer.setElementDebugInfo(
appEl.nativeElement, new RenderDebugInfo(appEl.getInjector(), appEl.getComponent(),
providerTokens, localsMap));
}
var parentLocals = null;
if (this.proto.type !== ViewType.COMPONENT) {

View File

@ -0,0 +1,11 @@
import {Injectable} from 'angular2/src/core/di';
import * as viewModule from './view';
/**
* Listener for view creation / destruction.
*/
@Injectable()
export class AppViewListener {
onViewCreated(view: viewModule.AppView) {}
onViewDestroyed(view: viewModule.AppView) {}
}

View File

@ -22,6 +22,7 @@ import {
} from './view_ref';
import {ViewContainerRef} from './view_container_ref';
import {TemplateRef, TemplateRef_} from './template_ref';
import {AppViewListener} from './view_listener';
import {RootRenderer, RenderComponentType} from 'angular2/src/core/render/api';
import {wtfCreateScope, wtfLeave, WtfScopeFn} from '../profile/profile';
import {APP_ID} from 'angular2/src/core/application_tokens';
@ -184,7 +185,10 @@ export abstract class AppViewManager {
export class AppViewManager_ extends AppViewManager {
private _nextCompTypeId: number = 0;
constructor(private _renderer: RootRenderer, @Inject(APP_ID) private _appId: string) { super(); }
constructor(private _renderer: RootRenderer, private _viewListener: AppViewListener,
@Inject(APP_ID) private _appId: string) {
super();
}
getViewContainer(location: ElementRef): ViewContainerRef {
return (<ElementRef_>location).internalElement.getViewContainerRef();
@ -312,10 +316,10 @@ export class AppViewManager_ extends AppViewManager {
}
/** @internal */
onViewCreated(view: AppView) {}
onViewCreated(view: AppView) { this._viewListener.onViewCreated(view); }
/** @internal */
onViewDestroyed(view: AppView) {}
onViewDestroyed(view: AppView) { this._viewListener.onViewDestroyed(view); }
/** @internal */
createRenderComponentType(encapsulation: ViewEncapsulation,

View File

@ -1268,7 +1268,7 @@ export var Input: InputFactory = makePropDecorator(InputMetadata);
* @Component({
* selector: 'app',
* template: `
* <interval-dir (everySecond)="everySecond()" (everyFiveSeconds)="everyFiveSeconds()">
* <interval-dir (every-second)="everySecond()" (every-five-seconds)="everyFiveSeconds()">
* </interval-dir>
* `,
* directives: [IntervalDir]

View File

@ -504,7 +504,7 @@ export class DirectiveMetadata extends InjectableMetadata {
* @Component({
* selector: 'app',
* template: `
* <interval-dir (everySecond)="everySecond()" (everyFiveSeconds)="everyFiveSeconds()">
* <interval-dir (every-second)="everySecond()" (every-five-seconds)="everyFiveSeconds()">
* </interval-dir>
* `,
* directives: [IntervalDir]
@ -1035,7 +1035,7 @@ export class InputMetadata {
* @Component({
* selector: 'app',
* template: `
* <interval-dir (everySecond)="everySecond()" (everyFiveSeconds)="everyFiveSeconds()">
* <interval-dir (every-second)="everySecond()" (every-five-seconds)="everyFiveSeconds()">
* </interval-dir>
* `,
* directives: [IntervalDir]

View File

@ -1,16 +1,10 @@
import {ViewEncapsulation} from 'angular2/src/core/metadata/view';
import {Injector} from 'angular2/src/core/di/injector';
export class RenderComponentType {
constructor(public id: string, public encapsulation: ViewEncapsulation,
public styles: Array<string | any[]>) {}
}
export class RenderDebugInfo {
constructor(public injector: Injector, public component: any, public providerTokens: any[],
public locals: Map<string, any>) {}
}
export interface ParentRenderer { renderComponent(componentType: RenderComponentType): Renderer; }
export abstract class Renderer implements ParentRenderer {
@ -48,8 +42,6 @@ export abstract class Renderer implements ParentRenderer {
*/
abstract setBindingDebugInfo(renderElement: any, propertyName: string, propertyValue: string);
abstract setElementDebugInfo(renderElement: any, info: RenderDebugInfo);
abstract setElementClass(renderElement: any, className: string, isAdd: boolean);
abstract setElementStyle(renderElement: any, styleName: string, styleValue: string);

View File

@ -422,14 +422,14 @@ export class NgZone {
fn();
ListWrapper.remove(ngZone._pendingTimeouts, id);
};
id = parentSetTimeout.call(this, cb, delay, args);
id = parentSetTimeout(cb, delay, args);
ngZone._pendingTimeouts.push(id);
return id;
};
},
'$clearTimeout': function(parentClearTimeout) {
return function(id: number) {
parentClearTimeout.call(this, id);
parentClearTimeout(id);
ListWrapper.remove(ngZone._pendingTimeouts, id);
};
},

View File

@ -225,19 +225,6 @@ class ListWrapper {
bool isListLikeIterable(obj) => obj is Iterable;
bool areIterablesEqual(Iterable a, Iterable b, Function comparator) {
var iterator1 = a.iterator;
var iterator2 = b.iterator;
while (true) {
var done1 = !iterator1.moveNext();
var done2 = !iterator2.moveNext();
if (done1 && done2) return true;
if (done1 || done2) return false;
if (!comparator(iterator2.current, iterator2.current)) return false;
}
}
void iterateListLike(iter, fn(item)) {
assert(iter is Iterable);
for (var item in iter) {

View File

@ -274,19 +274,6 @@ export function isListLikeIterable(obj: any): boolean {
getSymbolIterator() in obj); // JS Iterable have a Symbol.iterator prop
}
export function areIterablesEqual(a: any, b: any, comparator: Function): boolean {
var iterator1 = a[getSymbolIterator()]();
var iterator2 = b[getSymbolIterator()]();
while (true) {
let item1 = iterator1.next();
let item2 = iterator2.next();
if (item1.done && item2.done) return true;
if (item1.done || item2.done) return false;
if (!comparator(item1.value, item2.value)) return false;
}
}
export function iterateListLike(obj: any, fn: Function) {
if (isArray(obj)) {
for (var i = 0; i < obj.length; i++) {

View File

@ -345,8 +345,6 @@ class DateWrapper {
}
}
bool isPrimitive(Object obj) => obj is num || obj is bool || obj == null || obj is String;
// needed to match the exports from lang.js
var global = null;

View File

@ -427,7 +427,3 @@ export function evalExpression(sourceUrl: string, expr: string, declarations: st
}
return new Function(...fnArgNames.concat(fnBody))(...fnArgValues);
}
export function isPrimitive(obj: any): boolean {
return !isJsObject(obj);
}

View File

@ -98,15 +98,15 @@ export class MockConnection implements Connection {
* ### Example
*
* ```
* import {BaseRequestOptions, Http} from 'angular2/http';
* import {DefaultOptions, Http} from 'angular2/http';
* import {MockBackend} from 'angular2/http/testing';
* it('should get some data', inject([AsyncTestCompleter], (async) => {
* var connection;
* var injector = Injector.resolveAndCreate([
* MockBackend,
* provide(Http, {useFactory: (backend, options) => {
* return new Http(backend, options);
* }, deps: [MockBackend, BaseRequestOptions]})]);
* provide(Http, {useFactory: (backend, defaultOptions) => {
* return new Http(backend, defaultOptions)
* }, deps: [MockBackend, DefaultOptions]})]);
* var http = injector.get(Http);
* var backend = injector.get(MockBackend);
* //Assign any newly-created connection to local variable

View File

@ -30,12 +30,12 @@ import {BrowserDomAdapter} from './browser/browser_adapter';
import {BrowserGetTestability} from 'angular2/src/platform/browser/testability';
import {wtfInit} from 'angular2/src/core/profile/wtf_init';
import {EventManager, EVENT_MANAGER_PLUGINS} from "angular2/src/platform/dom/events/event_manager";
import {ELEMENT_PROBE_PROVIDERS} from 'angular2/platform/common_dom';
export {DOCUMENT} from 'angular2/src/platform/dom/dom_tokens';
export {Title} from 'angular2/src/platform/browser/title';
export {
DebugElementViewListener,
ELEMENT_PROBE_PROVIDERS,
ELEMENT_PROBE_PROVIDERS_PROD_MODE,
ELEMENT_PROBE_BINDINGS,
inspectNativeElement,
By
} from 'angular2/platform/common_dom';
@ -84,8 +84,7 @@ export const BROWSER_APP_COMMON_PROVIDERS: Array<any /*Type | Provider | any[]*/
Testability,
BrowserDetails,
AnimationBuilder,
EventManager,
ELEMENT_PROBE_PROVIDERS
EventManager
]);
export function initDomAdapter() {

View File

@ -39,6 +39,6 @@ export class By {
* {@example platform/dom/debug/ts/by/by.ts region='by_directive'}
*/
static directive(type: Type): Predicate<DebugElement> {
return (debugElement) => { return debugElement.providerTokens.indexOf(type) !== -1; };
return (debugElement) => { return debugElement.hasDirective(type); };
}
}

View File

@ -0,0 +1,89 @@
import {CONST_EXPR, isPresent, NumberWrapper, StringWrapper} from 'angular2/src/facade/lang';
import {MapWrapper, Map, ListWrapper} from 'angular2/src/facade/collection';
import {Injectable, provide, Provider} from 'angular2/src/core/di';
import {AppViewListener} from 'angular2/src/core/linker/view_listener';
import {AppView} from 'angular2/src/core/linker/view';
import {DOM} from 'angular2/src/platform/dom/dom_adapter';
import {DebugElement, DebugElement_} from 'angular2/src/core/debug/debug_element';
const NG_ID_PROPERTY = 'ngid';
const INSPECT_GLOBAL_NAME = 'ng.probe';
const NG_ID_SEPARATOR = '#';
// Need to keep the views in a global Map so that multiple angular apps are supported
var _allIdsByView = new Map<AppView, number>();
var _allViewsById = new Map<number, AppView>();
var _nextId = 0;
function _setElementId(element, indices: number[]) {
if (isPresent(element) && DOM.isElementNode(element)) {
DOM.setData(element, NG_ID_PROPERTY, indices.join(NG_ID_SEPARATOR));
}
}
function _getElementId(element): number[] {
var elId = DOM.getData(element, NG_ID_PROPERTY);
if (isPresent(elId)) {
return elId.split(NG_ID_SEPARATOR).map(partStr => NumberWrapper.parseInt(partStr, 10));
} else {
return null;
}
}
/**
* Returns a {@link DebugElement} for the given native DOM element, or
* null if the given native element does not have an Angular view associated
* with it.
*/
export function inspectNativeElement(element): DebugElement {
var elId = _getElementId(element);
if (isPresent(elId)) {
var view = _allViewsById.get(elId[0]);
if (isPresent(view)) {
return new DebugElement_(view.appElements[elId[1]]);
}
}
return null;
}
@Injectable()
export class DebugElementViewListener implements AppViewListener {
constructor() { DOM.setGlobalVar(INSPECT_GLOBAL_NAME, inspectNativeElement); }
onViewCreated(view: AppView) {
var viewId = _nextId++;
_allViewsById.set(viewId, view);
_allIdsByView.set(view, viewId);
for (var i = 0; i < view.appElements.length; i++) {
var el = view.appElements[i];
_setElementId(el.nativeElement, [viewId, i]);
}
}
onViewDestroyed(view: AppView) {
var viewId = _allIdsByView.get(view);
_allIdsByView.delete(view);
_allViewsById.delete(viewId);
}
}
/**
* Providers which support debugging Angular applications (e.g. via `ng.probe`).
*
* ## Example
*
* {@example platform/dom/debug/ts/debug_element_view_listener/providers.ts region='providers'}
*/
export const ELEMENT_PROBE_PROVIDERS: any[] = CONST_EXPR([
DebugElementViewListener,
CONST_EXPR(new Provider(AppViewListener, {useExisting: DebugElementViewListener})),
]);
/**
* Use {@link ELEMENT_PROBE_PROVIDERS}.
*
* @deprecated
*/
export const ELEMENT_PROBE_BINDINGS = ELEMENT_PROBE_PROVIDERS;

View File

@ -1,42 +0,0 @@
import {CONST_EXPR, assertionsEnabled, isPresent} from 'angular2/src/facade/lang';
import {Injectable, provide, Provider} from 'angular2/src/core/di';
import {DOM} from 'angular2/src/platform/dom/dom_adapter';
import {DebugNode, getDebugNode} from 'angular2/src/core/debug/debug_node';
import {DomRootRenderer} from 'angular2/src/platform/dom/dom_renderer';
import {RootRenderer} from 'angular2/core';
import {DebugDomRootRenderer} from 'angular2/src/core/debug/debug_renderer';
const INSPECT_GLOBAL_NAME = 'ng.probe';
/**
* Returns a {@link DebugElement} for the given native DOM element, or
* null if the given native element does not have an Angular view associated
* with it.
*/
export function inspectNativeElement(element): DebugNode {
return getDebugNode(element);
}
function _createConditionalRootRenderer(rootRenderer) {
if (assertionsEnabled()) {
return _createRootRenderer(rootRenderer);
}
return rootRenderer;
}
function _createRootRenderer(rootRenderer) {
DOM.setGlobalVar(INSPECT_GLOBAL_NAME, inspectNativeElement);
return new DebugDomRootRenderer(rootRenderer);
}
/**
* Providers which support debugging Angular applications (e.g. via `ng.probe`).
*/
export const ELEMENT_PROBE_PROVIDERS: any[] = CONST_EXPR([
new Provider(RootRenderer,
{useFactory: _createConditionalRootRenderer, deps: [DomRootRenderer]})
]);
export const ELEMENT_PROBE_PROVIDERS_PROD_MODE: any[] = CONST_EXPR(
[new Provider(RootRenderer, {useFactory: _createRootRenderer, deps: [DomRootRenderer]})]);

View File

@ -14,12 +14,7 @@ import {
import {BaseException, WrappedException} from 'angular2/src/facade/exceptions';
import {DomSharedStylesHost} from './shared_styles_host';
import {
Renderer,
RootRenderer,
RenderComponentType,
RenderDebugInfo
} from 'angular2/src/core/render/api';
import {Renderer, RootRenderer, RenderComponentType} from 'angular2/core';
import {EventManager} from './events/event_manager';
@ -206,8 +201,6 @@ export class DomRenderer implements Renderer {
}
}
setElementDebugInfo(renderElement: any, info: RenderDebugInfo) {}
setElementClass(renderElement: any, className: string, isAdd: boolean): void {
if (isAdd) {
DOM.addClass(renderElement, className);

View File

@ -36,7 +36,6 @@ import {BrowserDomAdapter} from './browser/browser_adapter';
import {wtfInit} from 'angular2/src/core/profile/wtf_init';
import {MessageBasedRenderer} from 'angular2/src/web_workers/ui/renderer';
import {MessageBasedXHRImpl} from 'angular2/src/web_workers/ui/xhr_impl';
import {BrowserPlatformLocation} from 'angular2/src/router/browser_platform_location';
import {
ServiceMessageBrokerFactory,
ServiceMessageBrokerFactory_
@ -60,13 +59,6 @@ export const WORKER_RENDER_PLATFORM: Array<any /*Type | Provider | any[]*/> = CO
new Provider(PLATFORM_INITIALIZER, {useValue: initWebWorkerRenderPlatform, multi: true})
]);
/**
* A list of {@link Provider}s. To use the router in a Worker enabled application you must
* include these providers when setting up the render thread.
*/
export const WORKER_RENDER_ROUTER: Array<any /*Type | Provider | any[]*/> =
CONST_EXPR([BrowserPlatformLocation]);
export const WORKER_RENDER_APPLICATION_COMMON: Array<any /*Type | Provider | any[]*/> = CONST_EXPR([
APPLICATION_COMMON_PROVIDERS,
WORKER_RENDER_MESSAGING_PROVIDERS,

View File

@ -1,58 +0,0 @@
import {Injectable} from 'angular2/core';
import {History, Location} from 'angular2/src/facade/browser';
import {UrlChangeListener} from './platform_location';
import {PlatformLocation} from './platform_location';
import {DOM} from 'angular2/src/platform/dom/dom_adapter';
/**
* `PlatformLocation` encapsulates all of the direct calls to platform APIs.
* This class should not be used directly by an application developer. Instead, use
* {@link Location}.
*/
@Injectable()
export class BrowserPlatformLocation extends PlatformLocation {
private _location: Location;
private _history: History;
constructor() {
super();
this._init();
}
// This is moved to its own method so that `MockPlatformLocationStrategy` can overwrite it
/** @internal */
_init() {
this._location = DOM.getLocation();
this._history = DOM.getHistory();
}
/** @internal */
get location(): Location { return this._location; }
getBaseHrefFromDOM(): string { return DOM.getBaseHref(); }
onPopState(fn: UrlChangeListener): void {
DOM.getGlobalEventTarget('window').addEventListener('popstate', fn, false);
}
onHashChange(fn: UrlChangeListener): void {
DOM.getGlobalEventTarget('window').addEventListener('hashchange', fn, false);
}
get pathname(): string { return this._location.pathname; }
get search(): string { return this._location.search; }
get hash(): string { return this._location.hash; }
set pathname(newPath: string) { this._location.pathname = newPath; }
pushState(state: any, title: string, url: string): void {
this._history.pushState(state, title, url);
}
replaceState(state: any, title: string, url: string): void {
this._history.replaceState(state, title, url);
}
forward(): void { this._history.forward(); }
back(): void { this._history.back(); }
}

View File

@ -5,7 +5,7 @@ import {
APP_BASE_HREF,
normalizeQueryParams
} from './location_strategy';
import {UrlChangeListener} from './platform_location';
import {EventListener} from 'angular2/src/facade/browser';
import {isPresent} from 'angular2/src/facade/lang';
import {PlatformLocation} from './platform_location';
@ -58,7 +58,7 @@ export class HashLocationStrategy extends LocationStrategy {
}
}
onPopState(fn: UrlChangeListener): void {
onPopState(fn: EventListener): void {
this._platformLocation.onPopState(fn);
this._platformLocation.onHashChange(fn);
}

View File

@ -297,7 +297,7 @@ export class RedirectInstruction extends ResolvedInstruction {
* `ComponentInstructions` is a public API. Instances of `ComponentInstruction` are passed
* to route lifecycle hooks, like {@link CanActivate}.
*
* `ComponentInstruction`s are [hash consed](https://en.wikipedia.org/wiki/Hash_consing). You should
* `ComponentInstruction`s are [https://en.wikipedia.org/wiki/Hash_consing](hash consed). You should
* never construct one yourself with "new." Instead, rely on {@link Router/RouteRecognizer} to
* construct `ComponentInstruction`s.
*

View File

@ -1,6 +1,5 @@
import {CONST_EXPR} from 'angular2/src/facade/lang';
import {OpaqueToken} from 'angular2/core';
import {UrlChangeListener} from './platform_location';
/**
* `LocationStrategy` is responsible for representing and reading route state
@ -25,7 +24,7 @@ export abstract class LocationStrategy {
abstract replaceState(state: any, title: string, url: string, queryParams: string): void;
abstract forward(): void;
abstract back(): void;
abstract onPopState(fn: UrlChangeListener): void;
abstract onPopState(fn: (_: any) => any): void;
abstract getBaseHref(): string;
}

View File

@ -1,4 +1,5 @@
import {Injectable, Inject, Optional} from 'angular2/core';
import {EventListener, History, Location} from 'angular2/src/facade/browser';
import {isBlank} from 'angular2/src/facade/lang';
import {BaseException} from 'angular2/src/facade/exceptions';
import {
@ -7,7 +8,7 @@ import {
normalizeQueryParams,
joinWithSlash
} from './location_strategy';
import {PlatformLocation, UrlChangeListener} from './platform_location';
import {PlatformLocation} from './platform_location';
/**
* `PathLocationStrategy` is a {@link LocationStrategy} used to configure the
@ -74,7 +75,7 @@ export class PathLocationStrategy extends LocationStrategy {
this._baseHref = href;
}
onPopState(fn: UrlChangeListener): void {
onPopState(fn: EventListener): void {
this._platformLocation.onPopState(fn);
this._platformLocation.onHashChange(fn);
}

View File

@ -1,48 +1,50 @@
import {DOM} from 'angular2/src/platform/dom/dom_adapter';
import {Injectable} from 'angular2/core';
import {EventListener, History, Location} from 'angular2/src/facade/browser';
/**
* `PlatformLocation` encapsulates all of the direct calls to platform APIs.
* This class should not be used directly by an application developer. Instead, use
* {@link Location}.
*
* `PlatformLocation` encapsulates all calls to DOM apis, which allows the Router to be platform
* agnostic.
* This means that we can have different implementation of `PlatformLocation` for the different
* platforms
* that angular supports. For example, the default `PlatformLocation` is {@link
* BrowserPlatformLocation},
* however when you run your app in a WebWorker you use {@link WebWorkerPlatformLocation}.
*
* The `PlatformLocation` class is used directly by all implementations of {@link LocationStrategy}
* when
* they need to interact with the DOM apis like pushState, popState, etc...
*
* {@link LocationStrategy} in turn is used by the {@link Location} service which is used directly
* by
* the {@link Router} in order to navigate between routes. Since all interactions between {@link
* Router} /
* {@link Location} / {@link LocationStrategy} and DOM apis flow through the `PlatformLocation`
* class
* they are all platform independent.
*/
export abstract class PlatformLocation {
abstract getBaseHrefFromDOM(): string;
abstract onPopState(fn: UrlChangeListener): void;
abstract onHashChange(fn: UrlChangeListener): void;
@Injectable()
export class PlatformLocation {
private _location: Location;
private _history: History;
pathname: string;
search: string;
hash: string;
constructor() { this._init(); }
abstract replaceState(state: any, title: string, url: string): void;
// This is moved to its own method so that `MockPlatformLocationStrategy` can overwrite it
/** @internal */
_init() {
this._location = DOM.getLocation();
this._history = DOM.getHistory();
}
abstract pushState(state: any, title: string, url: string): void;
getBaseHrefFromDOM(): string { return DOM.getBaseHref(); }
abstract forward(): void;
onPopState(fn: EventListener): void {
DOM.getGlobalEventTarget('window').addEventListener('popstate', fn, false);
}
abstract back(): void;
onHashChange(fn: EventListener): void {
DOM.getGlobalEventTarget('window').addEventListener('hashchange', fn, false);
}
get pathname(): string { return this._location.pathname; }
get search(): string { return this._location.search; }
get hash(): string { return this._location.hash; }
set pathname(newPath: string) { this._location.pathname = newPath; }
pushState(state: any, title: string, url: string): void {
this._history.pushState(state, title, url);
}
replaceState(state: any, title: string, url: string): void {
this._history.replaceState(state, title, url);
}
forward(): void { this._history.forward(); }
back(): void { this._history.back(); }
}
/**
* A serializable version of the event from onPopState or onHashChange
*/
export interface UrlChangeEvent { type: string; }
export interface UrlChangeListener { (e: UrlChangeEvent): any; }

View File

@ -1,42 +0,0 @@
// import {ROUTER_PROVIDERS_COMMON} from './router_providers_common';
import {ROUTER_PROVIDERS_COMMON} from 'angular2/router';
import {Provider} from 'angular2/core';
import {CONST_EXPR} from 'angular2/src/facade/lang';
import {BrowserPlatformLocation} from './browser_platform_location';
import {PlatformLocation} from './platform_location';
/**
* A list of {@link Provider}s. To use the router, you must add this to your application.
*
* ### Example ([live demo](http://plnkr.co/edit/iRUP8B5OUbxCWQ3AcIDm))
*
* ```
* import {Component} from 'angular2/core';
* import {
* ROUTER_DIRECTIVES,
* ROUTER_PROVIDERS,
* RouteConfig
* } from 'angular2/router';
*
* @Component({directives: [ROUTER_DIRECTIVES]})
* @RouteConfig([
* {...},
* ])
* class AppCmp {
* // ...
* }
*
* bootstrap(AppCmp, [ROUTER_PROVIDERS]);
* ```
*/
export const ROUTER_PROVIDERS: any[] = CONST_EXPR([
ROUTER_PROVIDERS_COMMON,
CONST_EXPR(new Provider(PlatformLocation, {useClass: BrowserPlatformLocation})),
]);
/**
* Use {@link ROUTER_PROVIDERS} instead.
*
* @deprecated
*/
export const ROUTER_BINDINGS = ROUTER_PROVIDERS;

View File

@ -1,40 +0,0 @@
import {LocationStrategy} from 'angular2/src/router/location_strategy';
import {PathLocationStrategy} from 'angular2/src/router/path_location_strategy';
import {Router, RootRouter} from 'angular2/src/router/router';
import {RouteRegistry, ROUTER_PRIMARY_COMPONENT} from 'angular2/src/router/route_registry';
import {Location} from 'angular2/src/router/location';
import {CONST_EXPR, Type} from 'angular2/src/facade/lang';
import {ApplicationRef, OpaqueToken, Provider} from 'angular2/core';
import {BaseException} from 'angular2/src/facade/exceptions';
/**
* The Platform agnostic ROUTER PROVIDERS
*/
export const ROUTER_PROVIDERS_COMMON: any[] = CONST_EXPR([
RouteRegistry,
CONST_EXPR(new Provider(LocationStrategy, {useClass: PathLocationStrategy})),
Location,
CONST_EXPR(new Provider(
Router,
{
useFactory: routerFactory,
deps: CONST_EXPR([RouteRegistry, Location, ROUTER_PRIMARY_COMPONENT, ApplicationRef])
})),
CONST_EXPR(new Provider(
ROUTER_PRIMARY_COMPONENT,
{useFactory: routerPrimaryComponentFactory, deps: CONST_EXPR([ApplicationRef])}))
]);
function routerFactory(registry: RouteRegistry, location: Location, primaryComponent: Type,
appRef: ApplicationRef): RootRouter {
var rootRouter = new RootRouter(registry, location, primaryComponent);
appRef.registerDisposeListener(() => rootRouter.dispose());
return rootRouter;
}
function routerPrimaryComponentFactory(app: ApplicationRef): Type {
if (app.componentTypes.length == 0) {
throw new BaseException("Bootstrap at least one component before injecting Router.");
}
return app.componentTypes[0];
}

View File

@ -1,11 +1,11 @@
import {
ComponentRef,
DebugElement,
DirectiveResolver,
DynamicComponentLoader,
Injector,
Injectable,
ViewMetadata,
ElementRef,
EmbeddedViewRef,
ViewResolver,
provide
@ -23,7 +23,7 @@ import {el} from './utils';
import {DOCUMENT} from 'angular2/src/platform/dom/dom_tokens';
import {DOM} from 'angular2/src/platform/dom/dom_adapter';
import {DebugNode, DebugElement, getDebugNode} from 'angular2/src/core/debug/debug_node';
import {DebugElement_} from 'angular2/src/core/debug/debug_element';
/**
@ -45,11 +45,6 @@ export abstract class ComponentFixture {
*/
nativeElement: any;
/**
* The ElementRef for the element at the root of the component.
*/
elementRef: ElementRef;
/**
* Trigger a change detection cycle for the component.
*/
@ -71,9 +66,7 @@ export class ComponentFixture_ extends ComponentFixture {
constructor(componentRef: ComponentRef) {
super();
this._componentParentView = (<ViewRef_>componentRef.hostView).internalView;
this.elementRef = this._componentParentView.appElements[0].ref;
this.debugElement = <DebugElement>getDebugNode(
this._componentParentView.rootNodesOrAppElements[0].nativeElement);
this.debugElement = new DebugElement_(this._componentParentView.appElements[0]);
this.componentInstance = this.debugElement.componentInstance;
this.nativeElement = this.debugElement.nativeElement;
this._componentRef = componentRef;

View File

@ -78,18 +78,11 @@ export class UpgradeNg1ComponentAdapterBuilder {
}
extractBindings() {
var btcIsObject = typeof this.directive.bindToController === 'object';
if (btcIsObject && Object.keys(this.directive.scope).length) {
throw new Error(
`Binding definitions on scope and controller at the same time are not supported.`);
}
var context = (btcIsObject) ? this.directive.bindToController : this.directive.scope;
if (typeof context == 'object') {
for (var name in context) {
if ((<any>context).hasOwnProperty(name)) {
var localName = context[name];
var scope = this.directive.scope;
if (typeof scope == 'object') {
for (var name in scope) {
if ((<any>scope).hasOwnProperty(name)) {
var localName = scope[name];
var type = localName.charAt(0);
localName = localName.substr(1) || name;
var outputName = 'output_' + name;
@ -116,7 +109,7 @@ export class UpgradeNg1ComponentAdapterBuilder {
this.propertyMap[outputName] = localName;
break;
default:
var json = JSON.stringify(context);
var json = JSON.stringify(scope);
throw new Error(
`Unexpected mapping '${type}' in '${json}' in '${this.name}' directive.`);
}

View File

@ -4,5 +4,4 @@
*/
export const RENDERER_CHANNEL = "ng-Renderer";
export const XHR_CHANNEL = "ng-XHR";
export const EVENT_CHANNEL = "ng-Events";
export const ROUTER_CHANNEL = "ng-Router";
export const EVENT_CHANNEL = "ng-events";

View File

@ -1,7 +0,0 @@
// This file contains interface versions of browser types that can be serialized to Plain Old
// JavaScript Objects
export class LocationType {
constructor(public href: string, public protocol: string, public host: string,
public hostname: string, public port: string, public pathname: string,
public search: string, public hash: string, public origin: string) {}
}

View File

@ -6,7 +6,6 @@ import {RenderComponentType} from "angular2/src/core/render/api";
import {Injectable} from "angular2/src/core/di";
import {RenderStore} from 'angular2/src/web_workers/shared/render_store';
import {ViewEncapsulation, VIEW_ENCAPSULATION_VALUES} from 'angular2/src/core/metadata/view';
import {LocationType} from './serialized_types';
// PRIMITIVE is any type that does not need to be serialized (string, number, boolean)
// We set it to String so that it is considered a Type.
@ -32,8 +31,6 @@ export class Serializer {
return this._serializeRenderComponentType(obj);
} else if (type === ViewEncapsulation) {
return serializeEnum(obj);
} else if (type === LocationType) {
return this._serializeLocation(obj);
} else {
throw new BaseException("No serializer for " + type.toString());
}
@ -58,8 +55,6 @@ export class Serializer {
return this._deserializeRenderComponentType(map);
} else if (type === ViewEncapsulation) {
return VIEW_ENCAPSULATION_VALUES[map];
} else if (type === LocationType) {
return this._deserializeLocation(map);
} else {
throw new BaseException("No deserializer for " + type.toString());
}
@ -95,25 +90,6 @@ export class Serializer {
}
}
private _serializeLocation(loc: LocationType): Object {
return {
'href': loc.href,
'protocol': loc.protocol,
'host': loc.host,
'hostname': loc.hostname,
'port': loc.port,
'pathname': loc.pathname,
'search': loc.search,
'hash': loc.hash,
'origin': loc.origin
};
}
private _deserializeLocation(loc: {[key: string]: any}): LocationType {
return new LocationType(loc['href'], loc['protocol'], loc['host'], loc['hostname'], loc['port'],
loc['pathname'], loc['search'], loc['hash'], loc['origin']);
}
private _serializeRenderComponentType(obj: RenderComponentType): Object {
return {
'id': obj.id,
@ -130,4 +106,4 @@ export class Serializer {
}
export class RenderStoreObject {}
export class RenderStoreObject {}

View File

@ -50,13 +50,11 @@ export class ServiceMessageBroker_ extends ServiceMessageBroker {
ObservableWrapper.subscribe(source, (message) => this._handleMessage(message));
}
registerMethod(methodName: string, signature: Type[], method: (..._: any[]) => Promise<any>| void,
returnType?: Type): void {
registerMethod(methodName: string, signature: Type[], method: Function, returnType?: Type): void {
this._methods.set(methodName, (message: ReceivedMessage) => {
var serializedArgs = message.args;
let numArgs = signature === null ? 0 : signature.length;
var deserializedArgs: any[] = ListWrapper.createFixedSize(numArgs);
for (var i = 0; i < numArgs; i++) {
var deserializedArgs: any[] = ListWrapper.createFixedSize(signature.length);
for (var i = 0; i < signature.length; i++) {
var serializedArg = serializedArgs[i];
deserializedArgs[i] = this._serializer.deserialize(serializedArg, signature[i]);
}

View File

@ -3,8 +3,7 @@ import {
serializeMouseEvent,
serializeKeyboardEvent,
serializeGenericEvent,
serializeEventWithTarget,
serializeTransitionEvent
serializeEventWithTarget
} from 'angular2/src/web_workers/ui/event_serializer';
import {BaseException, WrappedException} from 'angular2/src/facade/exceptions';
import {StringMapWrapper} from 'angular2/src/facade/collection';
@ -90,9 +89,6 @@ export class EventDispatcher {
case "waiting":
serializedEvent = serializeGenericEvent(event);
break;
case "transitionend":
serializedEvent = serializeTransitionEvent(event);
break;
default:
throw new BaseException(eventName + " not supported on WebWorkers");
}

View File

@ -86,14 +86,6 @@ Map<String, dynamic> serializeKeyboardEvent(dynamic e) {
return serialized;
}
Map<String, dynamic> serializeTransitionEvent(dynamic e) {
var serialized = serializeGenericEvent(e);
serialized['propertyName'] = e.propertyName;
serialized['elapsedTime'] = e.elapsedTime;
serialized['pseudoElement'] = e.pseudoElement;
return addTarget(e, serialized);
}
// TODO(jteplitz602): #3374. See above.
Map<String, dynamic> addTarget(
dynamic e, Map<String, dynamic> serializedEvent) {

View File

@ -32,8 +32,6 @@ const KEYBOARD_EVENT_PROPERTIES = [
'which'
];
const TRANSITION_EVENT_PROPERTIES = ['propertyName', 'elapsedTime', 'pseudoElement'];
const EVENT_PROPERTIES = ['type', 'bubbles', 'cancelable'];
const NODES_WITH_VALUE =
@ -59,11 +57,6 @@ export function serializeKeyboardEvent(e: KeyboardEvent): {[key: string]: any} {
return addTarget(e, serializedEvent);
}
export function serializeTransitionEvent(e: TransitionEvent): {[key: string]: any} {
var serializedEvent = serializeEvent(e, TRANSITION_EVENT_PROPERTIES);
return addTarget(e, serializedEvent);
}
// TODO(jteplitz602): #3374. See above.
function addTarget(e: Event, serializedEvent: {[key: string]: any}): {[key: string]: any} {
if (NODES_WITH_VALUE.has((<HTMLElement>e.target).tagName.toLowerCase())) {

View File

@ -1,54 +0,0 @@
import {BrowserPlatformLocation} from 'angular2/src/router/browser_platform_location';
import {Injectable} from 'angular2/src/core/di';
import {ROUTER_CHANNEL} from 'angular2/src/web_workers/shared/messaging_api';
import {
ServiceMessageBrokerFactory,
ServiceMessageBroker
} from 'angular2/src/web_workers/shared/service_message_broker';
import {PRIMITIVE, Serializer} from 'angular2/src/web_workers/shared/serializer';
import {bind} from './bind';
import {LocationType} from 'angular2/src/web_workers/shared/serialized_types';
import {MessageBus} from 'angular2/src/web_workers/shared/message_bus';
import {Promise, EventEmitter, ObservableWrapper, PromiseWrapper} from 'angular2/src/facade/async';
import {UrlChangeListener} from 'angular2/src/router/platform_location';
@Injectable()
export class MessageBasedPlatformLocation {
private _channelSink: EventEmitter<Object>;
private _broker: ServiceMessageBroker;
constructor(private _brokerFactory: ServiceMessageBrokerFactory,
private _platformLocation: BrowserPlatformLocation, bus: MessageBus,
private _serializer: Serializer) {
this._platformLocation.onPopState(<UrlChangeListener>bind(this._sendUrlChangeEvent, this));
this._platformLocation.onHashChange(<UrlChangeListener>bind(this._sendUrlChangeEvent, this));
this._broker = this._brokerFactory.createMessageBroker(ROUTER_CHANNEL);
this._channelSink = bus.to(ROUTER_CHANNEL);
}
start(): void {
this._broker.registerMethod("getLocation", null, bind(this._getLocation, this), LocationType);
this._broker.registerMethod("setPathname", [PRIMITIVE], bind(this._setPathname, this));
this._broker.registerMethod("pushState", [PRIMITIVE, PRIMITIVE, PRIMITIVE],
bind(this._platformLocation.pushState, this._platformLocation));
this._broker.registerMethod("replaceState", [PRIMITIVE, PRIMITIVE, PRIMITIVE],
bind(this._platformLocation.replaceState, this._platformLocation));
this._broker.registerMethod("forward", null,
bind(this._platformLocation.forward, this._platformLocation));
this._broker.registerMethod("back", null,
bind(this._platformLocation.back, this._platformLocation));
}
private _getLocation(): Promise<Location> {
return PromiseWrapper.resolve(this._platformLocation.location);
}
private _sendUrlChangeEvent(e: Event): void {
let loc = this._serializer.serialize(this._platformLocation.location, LocationType);
let serializedEvent = {'type': e.type};
ObservableWrapper.callEmit(this._channelSink, {'event': serializedEvent, 'location': loc});
}
private _setPathname(pathname: string): void { this._platformLocation.pathname = pathname; }
}

View File

@ -1,20 +0,0 @@
import {MessageBasedPlatformLocation} from './platform_location';
import {CONST_EXPR} from 'angular2/src/facade/lang';
import {BrowserPlatformLocation} from 'angular2/src/router/browser_platform_location';
import {APP_INITIALIZER, Provider, Injector, NgZone} from 'angular2/core';
export const WORKER_RENDER_ROUTER = CONST_EXPR([
MessageBasedPlatformLocation,
BrowserPlatformLocation,
CONST_EXPR(
new Provider(APP_INITIALIZER,
{useFactory: initRouterListeners, multi: true, deps: CONST_EXPR([Injector])}))
]);
function initRouterListeners(injector: Injector): () => void {
return () => {
let zone = injector.get(NgZone);
zone.run(() => injector.get(MessageBasedPlatformLocation).start());
};
}

View File

@ -31,10 +31,6 @@ class GenericEvent {
Point get page => _getPoint('page');
Point get screen => _getPoint('screen');
String get propertyName => properties['propertyName'];
num get elapsedTime => properties['elapsedTime'];
String get pseudoElement => properties['pseudoElement'];
EventTarget get target {
if (_target != null) {
return _target;

View File

@ -1,136 +0,0 @@
import {Injectable} from 'angular2/src/core/di';
import {
PlatformLocation,
UrlChangeEvent,
UrlChangeListener
} from 'angular2/src/router/platform_location';
import {
FnArg,
UiArguments,
ClientMessageBroker,
ClientMessageBrokerFactory
} from 'angular2/src/web_workers/shared/client_message_broker';
import {ROUTER_CHANNEL} from 'angular2/src/web_workers/shared/messaging_api';
import {LocationType} from 'angular2/src/web_workers/shared/serialized_types';
import {Promise, PromiseWrapper, EventEmitter, ObservableWrapper} from 'angular2/src/facade/async';
import {BaseException} from 'angular2/src/facade/exceptions';
import {PRIMITIVE, Serializer} from 'angular2/src/web_workers/shared/serializer';
import {MessageBus} from 'angular2/src/web_workers/shared/message_bus';
import {StringMapWrapper} from 'angular2/src/facade/collection';
import {StringWrapper} from 'angular2/src/facade/lang';
import {deserializeGenericEvent} from './event_deserializer';
@Injectable()
export class WebWorkerPlatformLocation extends PlatformLocation {
private _broker: ClientMessageBroker;
private _popStateListeners: Array<Function> = [];
private _hashChangeListeners: Array<Function> = [];
private _location: LocationType = null;
private _channelSource: EventEmitter<Object>;
constructor(brokerFactory: ClientMessageBrokerFactory, bus: MessageBus,
private _serializer: Serializer) {
super();
this._broker = brokerFactory.createMessageBroker(ROUTER_CHANNEL);
this._channelSource = bus.from(ROUTER_CHANNEL);
ObservableWrapper.subscribe(this._channelSource, (msg: {[key: string]: any}) => {
var listeners: Array<Function> = null;
if (StringMapWrapper.contains(msg, 'event')) {
let type: string = msg['event']['type'];
if (StringWrapper.equals(type, "popstate")) {
listeners = this._popStateListeners;
} else if (StringWrapper.equals(type, "hashchange")) {
listeners = this._hashChangeListeners;
}
if (listeners !== null) {
let e = deserializeGenericEvent(msg['event']);
// There was a popState or hashChange event, so the location object thas been updated
this._location = this._serializer.deserialize(msg['location'], LocationType);
listeners.forEach((fn: Function) => fn(e));
}
}
});
}
/** @internal **/
init(): Promise<boolean> {
var args: UiArguments = new UiArguments("getLocation");
var locationPromise: Promise<LocationType> = this._broker.runOnService(args, LocationType);
return PromiseWrapper.then(locationPromise, (val: LocationType): boolean => {
this._location = val;
return true;
}, (err): boolean => { throw new BaseException(err); });
}
getBaseHrefFromDOM(): string {
throw new BaseException(
"Attempt to get base href from DOM from WebWorker. You must either provide a value for the APP_BASE_HREF token through DI or use the hash location strategy.");
}
onPopState(fn: UrlChangeListener): void { this._popStateListeners.push(fn); }
onHashChange(fn: UrlChangeListener): void { this._hashChangeListeners.push(fn); }
get pathname(): string {
if (this._location === null) {
return null;
}
return this._location.pathname;
}
get search(): string {
if (this._location === null) {
return null;
}
return this._location.search;
}
get hash(): string {
if (this._location === null) {
return null;
}
return this._location.hash;
}
set pathname(newPath: string) {
if (this._location === null) {
throw new BaseException("Attempt to set pathname before value is obtained from UI");
}
this._location.pathname = newPath;
var fnArgs = [new FnArg(newPath, PRIMITIVE)];
var args = new UiArguments("setPathname", fnArgs);
this._broker.runOnService(args, null);
}
pushState(state: any, title: string, url: string): void {
var fnArgs =
[new FnArg(state, PRIMITIVE), new FnArg(title, PRIMITIVE), new FnArg(url, PRIMITIVE)];
var args = new UiArguments("pushState", fnArgs);
this._broker.runOnService(args, null);
}
replaceState(state: any, title: string, url: string): void {
var fnArgs =
[new FnArg(state, PRIMITIVE), new FnArg(title, PRIMITIVE), new FnArg(url, PRIMITIVE)];
var args = new UiArguments("replaceState", fnArgs);
this._broker.runOnService(args, null);
}
forward(): void {
var args = new UiArguments("forward");
this._broker.runOnService(args, null);
}
back(): void {
var args = new UiArguments("back");
this._broker.runOnService(args, null);
}
}

View File

@ -1,9 +1,4 @@
import {
Renderer,
RootRenderer,
RenderComponentType,
RenderDebugInfo
} from 'angular2/src/core/render/api';
import {Renderer, RootRenderer, RenderComponentType} from 'angular2/src/core/render/api';
import {
ClientMessageBroker,
ClientMessageBrokerFactory,
@ -191,8 +186,6 @@ export class WebWorkerRenderer implements Renderer, RenderStoreObject {
]);
}
setElementDebugInfo(renderElement: any, info: RenderDebugInfo) {}
setElementClass(renderElement: any, className: string, isAdd: boolean) {
this._runOnService('setElementClass', [
new FnArg(renderElement, RenderStoreObject),

View File

@ -1,21 +0,0 @@
import {ApplicationRef, Provider, NgZone, APP_INITIALIZER} from 'angular2/core';
import {PlatformLocation} from 'angular2/src/router/platform_location';
import {WebWorkerPlatformLocation} from './platform_location';
import {ROUTER_PROVIDERS_COMMON} from 'angular2/src/router/router_providers_common';
import {Promise} from 'angular2/src/facade/async';
export var WORKER_APP_ROUTER = [
ROUTER_PROVIDERS_COMMON,
new Provider(PlatformLocation, {useClass: WebWorkerPlatformLocation}),
new Provider(APP_INITIALIZER,
{
useFactory: (platformLocation: WebWorkerPlatformLocation, zone: NgZone) => () =>
initRouter(platformLocation, zone),
multi: true,
deps: [PlatformLocation, NgZone]
})
];
function initRouter(platformLocation: WebWorkerPlatformLocation, zone: NgZone): Promise<boolean> {
return zone.run(() => { return platformLocation.init(); });
}

View File

@ -19,9 +19,10 @@ import {Component, View, provide} from 'angular2/core';
import {NgFor} from 'angular2/common';
import {NgClass} from 'angular2/src/common/directives/ng_class';
function detectChangesAndCheck(fixture: ComponentFixture, classes: string) {
function detectChangesAndCheck(fixture: ComponentFixture, classes: string, elIndex: number = 0) {
fixture.detectChanges();
expect(fixture.debugElement.children[0].nativeElement.className).toEqual(classes);
expect(fixture.debugElement.componentViewChildren[elIndex].nativeElement.className)
.toEqual(classes);
}
export function main() {
@ -38,7 +39,7 @@ export function main() {
fixture.detectChanges();
fixture.debugElement.componentInstance.items = [['1']];
detectChangesAndCheck(fixture, '1');
detectChangesAndCheck(fixture, '1', 1);
async.done();
});

View File

@ -16,7 +16,7 @@ import {
import {ListWrapper} from 'angular2/src/facade/collection';
import {Component, View, TemplateRef, ContentChild} from 'angular2/core';
import {NgFor} from 'angular2/src/common/directives/ng_for';
import {By} from 'angular2/platform/common_dom';
export function main() {
describe('ngFor', () => {
@ -318,7 +318,7 @@ export function main() {
'<test-cmp><li template="#item #i=index">{{i}}: {{item}};</li></test-cmp>')
.createAsync(ComponentUsingTestComponent)
.then((fixture) => {
var testComponent = fixture.debugElement.children[0];
var testComponent = fixture.debugElement.componentViewChildren[0];
testComponent.componentInstance.items = ['a', 'b', 'c'];
fixture.detectChanges();
expect(testComponent.nativeElement).toHaveText('0: a;1: b;2: c;');
@ -334,7 +334,7 @@ export function main() {
.overrideTemplate(ComponentUsingTestComponent, '<test-cmp></test-cmp>')
.createAsync(ComponentUsingTestComponent)
.then((fixture) => {
var testComponent = fixture.debugElement.children[0];
var testComponent = fixture.debugElement.componentViewChildren[0];
testComponent.componentInstance.items = ['a', 'b', 'c'];
fixture.detectChanges();
expect(testComponent.nativeElement).toHaveText('0: a;1: b;2: c;');
@ -352,7 +352,7 @@ export function main() {
'<test-cmp><li template="#item #i=index">{{i}}: {{item}};</li></test-cmp>')
.createAsync(ComponentUsingTestComponent)
.then((fixture) => {
var testComponent = fixture.debugElement.children[0];
var testComponent = fixture.debugElement.componentViewChildren[0];
testComponent.componentInstance.items = ['a', 'b', 'c'];
fixture.detectChanges();
expect(testComponent.nativeElement).toHaveText('0: a;1: b;2: c;');
@ -360,31 +360,6 @@ export function main() {
async.done();
});
}));
it('should use custom track by if function is provided',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => {
var template =
`<template ngFor #item [ngForOf]="items" [ngForTrackBy]="customTrackBy" #i="index">
<p>{{items[i]}}</p>
</template>`;
tcb.overrideTemplate(TestComponent, template)
.createAsync(TestComponent)
.then((fixture) => {
var buildItemList =
() => {
fixture.debugElement.componentInstance.items = [{'id': 'a'}];
fixture.detectChanges();
return fixture.debugElement.queryAll(By.css('p'))[0];
}
var firstP = buildItemList();
var finalP = buildItemList();
expect(finalP.nativeElement).toBe(firstP.nativeElement);
async.done();
});
}));
});
}
@ -398,7 +373,6 @@ class TestComponent {
@ContentChild(TemplateRef) contentTpl: TemplateRef;
items: any;
constructor() { this.items = [1, 2]; }
customTrackBy(index: number, item: any): string { return item['id']; }
}
@Component({selector: 'outer-cmp'})

View File

@ -32,7 +32,8 @@ export function main() {
.createAsync(TestComponent)
.then((fixture) => {
fixture.detectChanges();
expect(DOM.getStyle(fixture.debugElement.children[0].nativeElement, 'max-width'))
expect(DOM.getStyle(fixture.debugElement.componentViewChildren[0].nativeElement,
'max-width'))
.toEqual('40px');
async.done();
@ -50,13 +51,15 @@ export function main() {
fixture.debugElement.componentInstance.expr = {'max-width': '40px'};
fixture.detectChanges();
expect(DOM.getStyle(fixture.debugElement.children[0].nativeElement, 'max-width'))
expect(DOM.getStyle(fixture.debugElement.componentViewChildren[0].nativeElement,
'max-width'))
.toEqual('40px');
expr = fixture.debugElement.componentInstance.expr;
expr['max-width'] = '30%';
fixture.detectChanges();
expect(DOM.getStyle(fixture.debugElement.children[0].nativeElement, 'max-width'))
expect(DOM.getStyle(fixture.debugElement.componentViewChildren[0].nativeElement,
'max-width'))
.toEqual('30%');
async.done();
@ -72,12 +75,14 @@ export function main() {
.then((fixture) => {
fixture.debugElement.componentInstance.expr = {'max-width': '40px'};
fixture.detectChanges();
expect(DOM.getStyle(fixture.debugElement.children[0].nativeElement, 'max-width'))
expect(DOM.getStyle(fixture.debugElement.componentViewChildren[0].nativeElement,
'max-width'))
.toEqual('40px');
StringMapWrapper.delete(fixture.debugElement.componentInstance.expr, 'max-width');
fixture.detectChanges();
expect(DOM.getStyle(fixture.debugElement.children[0].nativeElement, 'max-width'))
expect(DOM.getStyle(fixture.debugElement.componentViewChildren[0].nativeElement,
'max-width'))
.toEqual('');
async.done();
@ -93,16 +98,20 @@ export function main() {
.then((fixture) => {
fixture.debugElement.componentInstance.expr = {'max-width': '40px'};
fixture.detectChanges();
expect(DOM.getStyle(fixture.debugElement.children[0].nativeElement, 'max-width'))
expect(DOM.getStyle(fixture.debugElement.componentViewChildren[0].nativeElement,
'max-width'))
.toEqual('40px');
expect(DOM.getStyle(fixture.debugElement.children[0].nativeElement, 'font-size'))
expect(DOM.getStyle(fixture.debugElement.componentViewChildren[0].nativeElement,
'font-size'))
.toEqual('12px');
StringMapWrapper.delete(fixture.debugElement.componentInstance.expr, 'max-width');
fixture.detectChanges();
expect(DOM.getStyle(fixture.debugElement.children[0].nativeElement, 'max-width'))
expect(DOM.getStyle(fixture.debugElement.componentViewChildren[0].nativeElement,
'max-width'))
.toEqual('');
expect(DOM.getStyle(fixture.debugElement.children[0].nativeElement, 'font-size'))
expect(DOM.getStyle(fixture.debugElement.componentViewChildren[0].nativeElement,
'font-size'))
.toEqual('12px');
async.done();
@ -118,17 +127,21 @@ export function main() {
.then((fixture) => {
fixture.debugElement.componentInstance.expr = {'max-width': '40px'};
fixture.detectChanges();
expect(DOM.getStyle(fixture.debugElement.children[0].nativeElement, 'max-width'))
expect(DOM.getStyle(fixture.debugElement.componentViewChildren[0].nativeElement,
'max-width'))
.toEqual('40px');
expect(DOM.getStyle(fixture.debugElement.children[0].nativeElement, 'font-size'))
expect(DOM.getStyle(fixture.debugElement.componentViewChildren[0].nativeElement,
'font-size'))
.toEqual('12px');
StringMapWrapper.delete(fixture.debugElement.componentInstance.expr, 'max-width');
expect(DOM.getStyle(fixture.debugElement.children[0].nativeElement, 'font-size'))
expect(DOM.getStyle(fixture.debugElement.componentViewChildren[0].nativeElement,
'font-size'))
.toEqual('12px');
fixture.detectChanges();
expect(DOM.getStyle(fixture.debugElement.children[0].nativeElement, 'max-width'))
expect(DOM.getStyle(fixture.debugElement.componentViewChildren[0].nativeElement,
'max-width'))
.toEqual('');
async.done();

View File

@ -673,7 +673,7 @@ export function main() {
fixture.debugElement.componentInstance.name = null;
fixture.detectChanges();
var form = fixture.debugElement.children[0].inject(NgForm);
var form = fixture.debugElement.componentViewChildren[0].inject(NgForm);
expect(form.controls['user']).not.toBeDefined();
tick();
@ -708,7 +708,7 @@ export function main() {
fixture.debugElement.componentInstance.name = null;
fixture.detectChanges();
expect(fixture.debugElement.children[0].providerTokens.length).toEqual(0);
expect(fixture.debugElement.componentViewChildren.length).toEqual(0);
async.done();
});
}));
@ -728,7 +728,7 @@ export function main() {
fixture.debugElement.componentInstance.name = 'show';
fixture.detectChanges();
tick();
var form = fixture.debugElement.children[0].inject(NgForm);
var form = fixture.debugElement.componentViewChildren[0].inject(NgForm);
expect(form.controls['login']).toBeDefined();
@ -756,7 +756,7 @@ export function main() {
fixture.debugElement.componentInstance.name = 'show';
fixture.detectChanges();
tick();
var form = fixture.debugElement.children[0].inject(NgForm);
var form = fixture.debugElement.componentViewChildren[0].inject(NgForm);
expect(form.controls['user']).toBeDefined();

View File

@ -887,13 +887,6 @@ export function main() {
'Expression [\'"]a in location[\'"] has changed after it was checked'));
});
it('should not throw when two arrays are structurally the same', () => {
var val = _createChangeDetector('a', new TestDataWithGetter(() => ['value']));
val.changeDetector.detectChanges();
expect(() => { val.changeDetector.checkNoChanges(); }).not.toThrow();
});
it('should not break the next run', () => {
var val = _createChangeDetector('a', new TestData('value'));
expect(() => val.changeDetector.checkNoChanges())
@ -1604,12 +1597,6 @@ class TestData {
constructor(public a: any) {}
}
class TestDataWithGetter {
constructor(private fn: Function) {}
get a() { return this.fn(); }
}
class TestDispatcher implements ChangeDispatcher {
log: string[];
debugLog: string[];

View File

@ -1,60 +0,0 @@
import {
ddescribe,
describe,
it,
iit,
xit,
expect,
beforeEach,
afterEach
} from 'angular2/testing_internal';
import {ChangeDetectionUtil} from 'angular2/src/core/change_detection/change_detection_util';
export function main() {
describe("ChangeDetectionUtil", () => {
describe("devModeEqual", () => {
it("should do the deep comparison of iterables", () => {
expect(ChangeDetectionUtil.devModeEqual([['one']], [['one']])).toBe(true);
expect(ChangeDetectionUtil.devModeEqual(['one'], ['one', 'two'])).toBe(false);
expect(ChangeDetectionUtil.devModeEqual(['one', 'two'], ['one'])).toBe(false);
expect(ChangeDetectionUtil.devModeEqual(['one'], 'one')).toBe(false);
expect(ChangeDetectionUtil.devModeEqual(['one'], new Object())).toBe(false);
expect(ChangeDetectionUtil.devModeEqual('one', ['one'])).toBe(false);
expect(ChangeDetectionUtil.devModeEqual(new Object(), ['one'])).toBe(false);
});
it("should compare primitive numbers", () => {
expect(ChangeDetectionUtil.devModeEqual(1, 1)).toBe(true);
expect(ChangeDetectionUtil.devModeEqual(1, 2)).toBe(false);
expect(ChangeDetectionUtil.devModeEqual(new Object(), 2)).toBe(false);
expect(ChangeDetectionUtil.devModeEqual(1, new Object())).toBe(false);
});
it("should compare primitive strings", () => {
expect(ChangeDetectionUtil.devModeEqual('one', 'one')).toBe(true);
expect(ChangeDetectionUtil.devModeEqual('one', 'two')).toBe(false);
expect(ChangeDetectionUtil.devModeEqual(new Object(), 'one')).toBe(false);
expect(ChangeDetectionUtil.devModeEqual('one', new Object())).toBe(false);
});
it("should compare primitive booleans", () => {
expect(ChangeDetectionUtil.devModeEqual(true, true)).toBe(true);
expect(ChangeDetectionUtil.devModeEqual(true, false)).toBe(false);
expect(ChangeDetectionUtil.devModeEqual(new Object(), true)).toBe(false);
expect(ChangeDetectionUtil.devModeEqual(true, new Object())).toBe(false);
});
it("should compare null", () => {
expect(ChangeDetectionUtil.devModeEqual(null, null)).toBe(true);
expect(ChangeDetectionUtil.devModeEqual(null, 1)).toBe(false);
expect(ChangeDetectionUtil.devModeEqual(new Object(), null)).toBe(false);
expect(ChangeDetectionUtil.devModeEqual(null, new Object())).toBe(false);
});
it("should return true for other objects", () => {
expect(ChangeDetectionUtil.devModeEqual(new Object(), new Object())).toBe(true);
});
});
});
}

View File

@ -14,17 +14,11 @@ import {
} from 'angular2/src/core/change_detection/differs/default_iterable_differ';
import {NumberWrapper} from 'angular2/src/facade/lang';
import {ListWrapper} from 'angular2/src/facade/collection';
import {ListWrapper, MapWrapper} from 'angular2/src/facade/collection';
import {TestIterable} from '../../../core/change_detection/iterable';
import {iterableChangesAsString} from '../../../core/change_detection/util';
class ItemWithId {
constructor(private id: string) {}
toString() { return `{id: ${this.id}}` }
}
// todo(vicb): UnmodifiableListView / frozen object when implemented
export function main() {
describe('iterable differ', function() {
@ -260,7 +254,6 @@ export function main() {
}));
});
it('should support duplicates', () => {
let l = ['a', 'a', 'a', 'b', 'b'];
differ.check(l);
@ -331,80 +324,5 @@ export function main() {
});
});
});
describe('trackBy function', function() {
var differ;
var trackByItemId = (index: number, item: any): any => item.id;
var buildItemList =
(list: string[]) => { return list.map((val) => {return new ItemWithId(val)}) };
beforeEach(() => { differ = new DefaultIterableDiffer(trackByItemId); });
it('should not treat maps as new with track by function', () => {
let l = buildItemList(['a', 'b', 'c']);
differ.check(l);
expect(differ.toString())
.toEqual(iterableChangesAsString({
collection: [`{id: a}[null->0]`, `{id: b}[null->1]`, `{id: c}[null->2]`],
additions: [`{id: a}[null->0]`, `{id: b}[null->1]`, `{id: c}[null->2]`]
}));
l = buildItemList(['a', 'b', 'c']);
differ.check(l);
expect(differ.toString())
.toEqual(iterableChangesAsString({
collection: [`{id: a}`, `{id: b}`, `{id: c}`],
previous: [`{id: a}`, `{id: b}`, `{id: c}`]
}));
});
it('should track moves normally with track by function', () => {
let l = buildItemList(['a', 'b', 'c']);
differ.check(l);
l = buildItemList(['b', 'a', 'c']);
differ.check(l);
expect(differ.toString())
.toEqual(iterableChangesAsString({
collection: ['{id: b}[1->0]', '{id: a}[0->1]', '{id: c}'],
previous: ['{id: a}[0->1]', '{id: b}[1->0]', '{id: c}'],
moves: ['{id: b}[1->0]', '{id: a}[0->1]']
}));
});
it('should track duplicate reinsertion normally with track by function', () => {
let l = buildItemList(['a', 'a']);
differ.check(l);
l = buildItemList(['b', 'a', 'a']);
differ.check(l);
expect(differ.toString())
.toEqual(iterableChangesAsString({
collection: ['{id: b}[null->0]', '{id: a}[0->1]', '{id: a}[1->2]'],
previous: ['{id: a}[0->1]', '{id: a}[1->2]'],
moves: ['{id: a}[0->1]', '{id: a}[1->2]'],
additions: ['{id: b}[null->0]']
}));
});
it('should track removals normally with track by function', () => {
let l = buildItemList(['a', 'b', 'c']);
differ.check(l);
ListWrapper.removeAt(l, 2);
differ.check(l);
expect(differ.toString())
.toEqual(iterableChangesAsString({
collection: ['{id: a}', '{id: b}'],
previous: ['{id: a}', '{id: b}', '{id: c}[2->null]'],
removals: ['{id: c}[2->null]']
}));
});
});
});
}

View File

@ -0,0 +1,294 @@
import {
AsyncTestCompleter,
beforeEach,
ddescribe,
xdescribe,
describe,
dispatchEvent,
expect,
iit,
inject,
beforeEachProviders,
it,
xit,
TestComponentBuilder
} from 'angular2/testing_internal';
import {DOM} from 'angular2/src/platform/dom/dom_adapter';
import {PromiseWrapper, EventEmitter, ObservableWrapper} from 'angular2/src/facade/async';
import {Injectable} from 'angular2/core';
import {NgFor, NgIf} from 'angular2/common';
import {Scope} from 'angular2/core';
import {By} from 'angular2/platform/common_dom';
import {
Directive,
Component,
View,
} from 'angular2/src/core/metadata';
@Injectable()
class Logger {
log: string[];
constructor() { this.log = []; }
add(thing: string) { this.log.push(thing); }
}
@Directive({selector: '[message]', inputs: ['message']})
@Injectable()
class MessageDir {
logger: Logger;
constructor(logger: Logger) { this.logger = logger; }
set message(newMessage) { this.logger.add(newMessage); }
}
@Component({selector: 'child-comp'})
@View({
template: `<div class="child" message="child">
<span class="childnested" message="nestedchild">Child</span>
</div>
<span class="child" [innerHtml]="childBinding"></span>`,
directives: [MessageDir],
})
@Injectable()
class ChildComp {
childBinding: string;
constructor() { this.childBinding = 'Original'; }
}
@Component({selector: 'cond-content-comp', viewProviders: [Logger]})
@View({
template: `<div class="child" message="child" *ngIf="false"><ng-content></ng-content></div>`,
directives: [NgIf, MessageDir],
})
@Injectable()
class ConditionalContentComp {
}
@Component({selector: 'parent-comp', viewProviders: [Logger]})
@View({
template: `<div class="parent" message="parent">
<span class="parentnested" message="nestedparent">Parent</span>
</div>
<span class="parent" [innerHtml]="parentBinding"></span>
<child-comp class="child-comp-class"></child-comp>
<cond-content-comp class="cond-content-comp-class"></cond-content-comp>`,
directives: [ChildComp, MessageDir, ConditionalContentComp],
})
@Injectable()
class ParentComp {
parentBinding: string;
constructor() { this.parentBinding = 'OriginalParent'; }
}
@Directive({selector: 'custom-emitter', outputs: ['myevent']})
@Injectable()
class CustomEmitter {
myevent: EventEmitter<any>;
constructor() { this.myevent = new EventEmitter(); }
}
@Component({selector: 'events-comp'})
@View({
template: `<button (click)="handleClick()"></button>
<custom-emitter (myevent)="handleCustom()"></custom-emitter>`,
directives: [CustomEmitter],
})
@Injectable()
class EventsComp {
clicked: boolean;
customed: boolean;
constructor() {
this.clicked = false;
this.customed = false;
}
handleClick() { this.clicked = true; }
handleCustom() { this.customed = true; }
}
@Component({selector: 'using-for', viewProviders: [Logger]})
@View({
template: `<span *ngFor="#thing of stuff" [innerHtml]="thing"></span>
<ul message="list">
<li *ngFor="#item of stuff" [innerHtml]="item"></li>
</ul>`,
directives: [NgFor, MessageDir],
})
@Injectable()
class UsingFor {
stuff: string[];
constructor() { this.stuff = ['one', 'two', 'three']; }
}
export function main() {
describe('debug element', function() {
it('should list component child elements',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => {
tcb.createAsync(ParentComp)
.then((componentFixture) => {
componentFixture.detectChanges();
var childEls = componentFixture.debugElement.children;
// The root is a lone component, and has no children in the light dom.
expect(childEls.length).toEqual(0);
var rootCompChildren = componentFixture.debugElement.componentViewChildren;
// The root component has 4 elements in its shadow view.
expect(rootCompChildren.length).toEqual(4);
expect(DOM.hasClass(rootCompChildren[0].nativeElement, 'parent')).toBe(true);
expect(DOM.hasClass(rootCompChildren[1].nativeElement, 'parent')).toBe(true);
expect(DOM.hasClass(rootCompChildren[2].nativeElement, 'child-comp-class'))
.toBe(true);
expect(DOM.hasClass(rootCompChildren[3].nativeElement, 'cond-content-comp-class'))
.toBe(true);
var nested = rootCompChildren[0].children;
expect(nested.length).toEqual(1);
expect(DOM.hasClass(nested[0].nativeElement, 'parentnested')).toBe(true);
var childComponent = rootCompChildren[2];
expect(childComponent.children.length).toEqual(0);
var childCompChildren = childComponent.componentViewChildren;
expect(childCompChildren.length).toEqual(2);
expect(DOM.hasClass(childCompChildren[0].nativeElement, 'child')).toBe(true);
expect(DOM.hasClass(childCompChildren[1].nativeElement, 'child')).toBe(true);
var childNested = childCompChildren[0].children;
expect(childNested.length).toEqual(1);
expect(DOM.hasClass(childNested[0].nativeElement, 'childnested')).toBe(true);
var conditionalContentComp = rootCompChildren[3];
expect(conditionalContentComp.children.length).toEqual(0);
expect(conditionalContentComp.componentViewChildren.length).toEqual(1);
var ngIfWithProjectedNgContent = conditionalContentComp.componentViewChildren[0];
expect(ngIfWithProjectedNgContent.children.length).toBe(0);
expect(ngIfWithProjectedNgContent.componentViewChildren.length).toBe(0);
async.done();
});
}));
it('should list child elements within viewports',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => {
tcb.createAsync(UsingFor).then((componentFixture) => {
componentFixture.detectChanges();
var childEls = componentFixture.debugElement.componentViewChildren;
// TODO should this count include the <template> element?
expect(childEls.length).toEqual(5);
var list = childEls[4];
expect(list.children.length).toEqual(4);
async.done();
});
}));
it('should query child elements',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => {
tcb.createAsync(ParentComp)
.then((componentFixture) => {
componentFixture.detectChanges();
var childTestEls = componentFixture.debugElement.queryAll(By.directive(MessageDir));
expect(childTestEls.length).toBe(4);
expect(DOM.hasClass(childTestEls[0].nativeElement, 'parent')).toBe(true);
expect(DOM.hasClass(childTestEls[1].nativeElement, 'parentnested')).toBe(true);
expect(DOM.hasClass(childTestEls[2].nativeElement, 'child')).toBe(true);
expect(DOM.hasClass(childTestEls[3].nativeElement, 'childnested')).toBe(true);
async.done();
});
}));
it('should query child elements in the light DOM',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => {
tcb.createAsync(ParentComp)
.then((componentFixture) => {
componentFixture.detectChanges();
var parentEl = componentFixture.debugElement.componentViewChildren[0];
var childTestEls = parentEl.queryAll(By.directive(MessageDir), Scope.light);
expect(childTestEls.length).toBe(1);
expect(DOM.hasClass(childTestEls[0].nativeElement, 'parentnested')).toBe(true);
async.done();
});
}));
it('should query child elements in the current component view DOM',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => {
tcb.createAsync(ParentComp)
.then((componentFixture) => {
componentFixture.detectChanges();
var childTestEls =
componentFixture.debugElement.queryAll(By.directive(MessageDir), Scope.view);
expect(childTestEls.length).toBe(2);
expect(DOM.hasClass(childTestEls[0].nativeElement, 'parent')).toBe(true);
expect(DOM.hasClass(childTestEls[1].nativeElement, 'parentnested')).toBe(true);
async.done();
});
}));
it('should allow injecting from the element injector',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => {
tcb.createAsync(ParentComp)
.then((componentFixture) => {
componentFixture.detectChanges();
expect(componentFixture.debugElement.componentViewChildren[0].inject(Logger).log)
.toEqual(['parent', 'nestedparent', 'child', 'nestedchild']);
async.done();
});
}));
it('should trigger event handlers',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => {
tcb.createAsync(EventsComp)
.then((componentFixture) => {
componentFixture.detectChanges();
expect(componentFixture.debugElement.componentInstance.clicked).toBe(false);
expect(componentFixture.debugElement.componentInstance.customed).toBe(false);
componentFixture.debugElement.componentViewChildren[0].triggerEventHandler(
'click', <Event>{});
expect(componentFixture.debugElement.componentInstance.clicked).toBe(true);
componentFixture.debugElement.componentViewChildren[1].triggerEventHandler(
'myevent', <Event>{});
expect(componentFixture.debugElement.componentInstance.customed).toBe(true);
async.done();
});
}));
});
}

View File

@ -1,392 +0,0 @@
import {
AsyncTestCompleter,
beforeEach,
ddescribe,
xdescribe,
describe,
dispatchEvent,
expect,
iit,
inject,
beforeEachProviders,
it,
xit,
TestComponentBuilder
} from 'angular2/testing_internal';
import {DOM} from 'angular2/src/platform/dom/dom_adapter';
import {PromiseWrapper, EventEmitter, ObservableWrapper} from 'angular2/src/facade/async';
import {Injectable} from 'angular2/core';
import {NgFor, NgIf} from 'angular2/common';
import {By} from 'angular2/platform/common_dom';
import {Directive, Component, View, Input} from 'angular2/src/core/metadata';
@Injectable()
class Logger {
log: string[];
constructor() { this.log = []; }
add(thing: string) { this.log.push(thing); }
}
@Directive({selector: '[message]', inputs: ['message']})
@Injectable()
class MessageDir {
logger: Logger;
constructor(logger: Logger) { this.logger = logger; }
set message(newMessage) { this.logger.add(newMessage); }
}
@Component({selector: 'child-comp'})
@View({
template: `<div class="child" message="child">
<span class="childnested" message="nestedchild">Child</span>
</div>
<span class="child" [innerHtml]="childBinding"></span>`,
directives: [MessageDir],
})
@Injectable()
class ChildComp {
childBinding: string;
constructor() { this.childBinding = 'Original'; }
}
@Component({selector: 'parent-comp', viewProviders: [Logger]})
@View({
template: `<div class="parent" message="parent">
<span class="parentnested" message="nestedparent">Parent</span>
</div>
<span class="parent" [innerHtml]="parentBinding"></span>
<child-comp class="child-comp-class"></child-comp>`,
directives: [ChildComp, MessageDir],
})
@Injectable()
class ParentComp {
parentBinding: string;
constructor() { this.parentBinding = 'OriginalParent'; }
}
@Directive({selector: 'custom-emitter', outputs: ['myevent']})
@Injectable()
class CustomEmitter {
myevent: EventEmitter<any>;
constructor() { this.myevent = new EventEmitter(); }
}
@Component({selector: 'events-comp'})
@View({
template: `<button (click)="handleClick()"></button>
<custom-emitter (myevent)="handleCustom()"></custom-emitter>`,
directives: [CustomEmitter],
})
@Injectable()
class EventsComp {
clicked: boolean;
customed: boolean;
constructor() {
this.clicked = false;
this.customed = false;
}
handleClick() { this.clicked = true; }
handleCustom() { this.customed = true; }
}
@Component({selector: 'cond-content-comp', viewProviders: [Logger]})
@View({
template: `<div class="child" message="child" *ngIf="myBool"><ng-content></ng-content></div>`,
directives: [NgIf, MessageDir],
})
@Injectable()
class ConditionalContentComp {
myBool: boolean = false;
}
@Component({selector: 'conditional-parent-comp', viewProviders: [Logger]})
@View({
template: `<span class="parent" [innerHtml]="parentBinding"></span>
<cond-content-comp class="cond-content-comp-class">
<span class="from-parent"></span>
</cond-content-comp>`,
directives: [ConditionalContentComp],
})
@Injectable()
class ConditionalParentComp {
parentBinding: string;
constructor() { this.parentBinding = 'OriginalParent'; }
}
@Component({selector: 'using-for', viewProviders: [Logger]})
@View({
template: `<span *ngFor="#thing of stuff" [innerHtml]="thing"></span>
<ul message="list">
<li *ngFor="#item of stuff" [innerHtml]="item"></li>
</ul>`,
directives: [NgFor, MessageDir],
})
@Injectable()
class UsingFor {
stuff: string[];
constructor() { this.stuff = ['one', 'two', 'three']; }
}
@Directive({selector: '[mydir]', exportAs: 'mydir'})
class MyDir {
}
@Component({
selector: 'locals-comp',
template: `
<div mydir #alice="mydir"></div>
`,
directives: [MyDir]
})
class LocalsComp {
}
@Component({
selector: 'bank-account',
template: `
Bank Name: {{bank}}
Account Id: {{id}}
`
})
class BankAccount {
@Input() bank: string;
@Input('account') id: string;
normalizedBankName: string;
}
@Component({
selector: 'test-app',
template: `
<bank-account bank="RBC" account="4747"></bank-account>
`,
directives: [BankAccount]
})
class TestApp {
}
export function main() {
describe('debug element', function() {
it('should list all child nodes',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => {
tcb.createAsync(ParentComp)
.then((fixture) => {
fixture.detectChanges();
// The root component has 3 elements and 2 text node children.
expect(fixture.debugElement.childNodes.length).toEqual(5);
async.done();
});
}));
it('should list all component child elements',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => {
tcb.createAsync(ParentComp)
.then((fixture) => {
fixture.detectChanges();
var childEls = fixture.debugElement.children;
// The root component has 3 elements in its view.
expect(childEls.length).toEqual(3);
expect(DOM.hasClass(childEls[0].nativeElement, 'parent')).toBe(true);
expect(DOM.hasClass(childEls[1].nativeElement, 'parent')).toBe(true);
expect(DOM.hasClass(childEls[2].nativeElement, 'child-comp-class')).toBe(true);
var nested = childEls[0].children;
expect(nested.length).toEqual(1);
expect(DOM.hasClass(nested[0].nativeElement, 'parentnested')).toBe(true);
var childComponent = childEls[2];
var childCompChildren = childComponent.children;
expect(childCompChildren.length).toEqual(2);
expect(DOM.hasClass(childCompChildren[0].nativeElement, 'child')).toBe(true);
expect(DOM.hasClass(childCompChildren[1].nativeElement, 'child')).toBe(true);
var childNested = childCompChildren[0].children;
expect(childNested.length).toEqual(1);
expect(DOM.hasClass(childNested[0].nativeElement, 'childnested')).toBe(true);
async.done();
});
}));
it('should list conditional component child elements',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => {
tcb.createAsync(ConditionalParentComp)
.then((fixture) => {
fixture.detectChanges();
var childEls = fixture.debugElement.children;
// The root component has 2 elements in its view.
expect(childEls.length).toEqual(2);
expect(DOM.hasClass(childEls[0].nativeElement, 'parent')).toBe(true);
expect(DOM.hasClass(childEls[1].nativeElement, 'cond-content-comp-class'))
.toBe(true);
var conditionalContentComp = childEls[1];
expect(conditionalContentComp.children.length).toEqual(0);
conditionalContentComp.componentInstance.myBool = true;
fixture.detectChanges();
expect(conditionalContentComp.children.length).toEqual(1);
async.done();
});
}));
it('should list child elements within viewports',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => {
tcb.createAsync(UsingFor).then((fixture) => {
fixture.detectChanges();
var childEls = fixture.debugElement.children;
expect(childEls.length).toEqual(4);
// The 4th child is the <ul>
var list = childEls[3];
expect(list.children.length).toEqual(3);
async.done();
});
}));
it('should list element attributes',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => {
tcb.createAsync(TestApp).then((fixture) => {
fixture.detectChanges();
var bankElem = fixture.debugElement.children[0];
expect(bankElem.attributes.get('bank')).toEqual('RBC');
expect(bankElem.attributes.get('account')).toEqual('4747');
async.done();
});
}));
it('should query child elements by css',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => {
tcb.createAsync(ParentComp)
.then((fixture) => {
fixture.detectChanges();
var childTestEls = fixture.debugElement.queryAll(By.css('child-comp'));
expect(childTestEls.length).toBe(1);
expect(DOM.hasClass(childTestEls[0].nativeElement, 'child-comp-class')).toBe(true);
async.done();
});
}));
it('should query child elements by directive',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => {
tcb.createAsync(ParentComp)
.then((fixture) => {
fixture.detectChanges();
var childTestEls = fixture.debugElement.queryAll(By.directive(MessageDir));
expect(childTestEls.length).toBe(4);
expect(DOM.hasClass(childTestEls[0].nativeElement, 'parent')).toBe(true);
expect(DOM.hasClass(childTestEls[1].nativeElement, 'parentnested')).toBe(true);
expect(DOM.hasClass(childTestEls[2].nativeElement, 'child')).toBe(true);
expect(DOM.hasClass(childTestEls[3].nativeElement, 'childnested')).toBe(true);
async.done();
});
}));
it('should list providerTokens',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => {
tcb.createAsync(ParentComp)
.then((fixture) => {
fixture.detectChanges();
expect(fixture.debugElement.providerTokens).toContain(Logger);
async.done();
});
}));
it('should list locals',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => {
tcb.createAsync(LocalsComp)
.then((fixture) => {
fixture.detectChanges();
expect(fixture.debugElement.children[0].getLocal('alice')).toBeAnInstanceOf(MyDir);
async.done();
});
}));
it('should allow injecting from the element injector',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => {
tcb.createAsync(ParentComp)
.then((fixture) => {
fixture.detectChanges();
expect(fixture.debugElement.children[0].inject(Logger).log)
.toEqual(['parent', 'nestedparent', 'child', 'nestedchild']);
async.done();
});
}));
it('should list event listeners',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => {
tcb.createAsync(EventsComp)
.then((fixture) => {
fixture.detectChanges();
expect(fixture.debugElement.children[0].listeners.length).toEqual(1);
expect(fixture.debugElement.children[1].listeners.length).toEqual(1);
async.done();
});
}));
it('should trigger event handlers',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => {
tcb.createAsync(EventsComp)
.then((fixture) => {
fixture.detectChanges();
expect(fixture.debugElement.componentInstance.clicked).toBe(false);
expect(fixture.debugElement.componentInstance.customed).toBe(false);
fixture.debugElement.children[0].triggerEventHandler('click', <Event>{});
expect(fixture.debugElement.componentInstance.clicked).toBe(true);
fixture.debugElement.children[1].triggerEventHandler('myevent', <Event>{});
expect(fixture.debugElement.componentInstance.customed).toBe(true);
async.done();
});
}));
});
}

View File

@ -32,7 +32,8 @@ export function main() {
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => {
tcb.createAsync(App).then((tc) => {
tc.detectChanges();
expect(asNativeElements(tc.debugElement.children)).toHaveText('frame(lock)');
expect(asNativeElements(tc.debugElement.componentViewChildren))
.toHaveText('frame(lock)');
async.done();
});
}));

View File

@ -17,11 +17,12 @@ import {
} from 'angular2/testing_internal';
import {OnDestroy} from 'angular2/core';
import {Injector} from 'angular2/core';
import {Injector, inspectElement} from 'angular2/core';
import {NgIf} from 'angular2/common';
import {By} from 'angular2/platform/common_dom';
import {Component, View, ViewMetadata} from 'angular2/src/core/metadata';
import {DynamicComponentLoader} from 'angular2/src/core/linker/dynamic_component_loader';
import {ElementRef, ElementRef_} from 'angular2/src/core/linker/element_ref';
import {ElementRef} from 'angular2/src/core/linker/element_ref';
import {DOCUMENT} from 'angular2/src/platform/dom/dom_tokens';
import {DOM} from 'angular2/src/platform/dom/dom_adapter';
import {ComponentFixture_} from "angular2/src/testing/test_component_builder";
@ -33,80 +34,6 @@ export function main() {
describe('DynamicComponentLoader', function() {
describe("loading into a location", () => {
it('should work',
inject([DynamicComponentLoader, TestComponentBuilder, AsyncTestCompleter],
(loader, tcb: TestComponentBuilder, async) => {
tcb.overrideView(
MyComp,
new ViewMetadata(
{template: '<location #loc></location>', directives: [Location]}))
.createAsync(MyComp)
.then((tc) => {
loader.loadIntoLocation(DynamicallyLoaded, tc.elementRef, 'loc')
.then(ref => {
expect(tc.debugElement.nativeElement)
.toHaveText("Location;DynamicallyLoaded;");
async.done();
});
});
}));
it('should return a disposable component ref',
inject([DynamicComponentLoader, TestComponentBuilder, AsyncTestCompleter],
(loader, tcb: TestComponentBuilder, async) => {
tcb.overrideView(
MyComp,
new ViewMetadata(
{template: '<location #loc></location>', directives: [Location]}))
.createAsync(MyComp)
.then((tc) => {
loader.loadIntoLocation(DynamicallyLoaded, tc.elementRef, 'loc')
.then(ref => {
ref.dispose();
expect(tc.debugElement.nativeElement).toHaveText("Location;");
async.done();
});
});
}));
it('should allow to dispose even if the location has been removed',
inject(
[DynamicComponentLoader, TestComponentBuilder, AsyncTestCompleter],
(loader, tcb: TestComponentBuilder, async) => {
tcb.overrideView(MyComp, new ViewMetadata({
template: '<child-cmp *ngIf="ctxBoolProp"></child-cmp>',
directives: [NgIf, ChildComp]
}))
.overrideView(
ChildComp,
new ViewMetadata(
{template: '<location #loc></location>', directives: [Location]}))
.createAsync(MyComp)
.then((tc) => {
tc.debugElement.componentInstance.ctxBoolProp = true;
tc.detectChanges();
var childCompEl = (<ElementRef_>tc.elementRef).internalElement;
// TODO(juliemr): This is hideous, see if there's a better way to handle
// child element refs now.
var childElementRef =
childCompEl.componentView.appElements[0].nestedViews[0].appElements[0].ref;
loader.loadIntoLocation(DynamicallyLoaded, childElementRef, 'loc')
.then(ref => {
expect(tc.debugElement.nativeElement)
.toHaveText("Location;DynamicallyLoaded;");
tc.debugElement.componentInstance.ctxBoolProp = false;
tc.detectChanges();
expect(tc.debugElement.nativeElement).toHaveText("");
ref.dispose();
expect(tc.debugElement.nativeElement).toHaveText("");
async.done();
});
});
}));
it('should update host properties',
inject(
[DynamicComponentLoader, TestComponentBuilder, AsyncTestCompleter],
(loader, tcb: TestComponentBuilder, async) => {
@ -115,20 +42,91 @@ export function main() {
{template: '<location #loc></location>', directives: [Location]}))
.createAsync(MyComp)
.then((tc) => {
loader.loadIntoLocation(DynamicallyLoadedWithHostProps, tc.elementRef, 'loc')
loader.loadIntoLocation(DynamicallyLoaded, tc.debugElement.elementRef, 'loc')
.then(ref => {
ref.instance.id = "new value";
tc.detectChanges();
var newlyInsertedElement =
DOM.childNodes(tc.debugElement.nativeElement)[1];
expect((<HTMLElement>newlyInsertedElement).id).toEqual("new value");
expect(tc.debugElement.nativeElement)
.toHaveText("Location;DynamicallyLoaded;");
async.done();
});
});
}));
it('should return a disposable component ref',
inject(
[DynamicComponentLoader, TestComponentBuilder, AsyncTestCompleter],
(loader, tcb: TestComponentBuilder, async) => {
tcb.overrideView(
MyComp, new ViewMetadata(
{template: '<location #loc></location>', directives: [Location]}))
.createAsync(MyComp)
.then((tc) => {
loader.loadIntoLocation(DynamicallyLoaded, tc.debugElement.elementRef, 'loc')
.then(ref => {
ref.dispose();
expect(tc.debugElement.nativeElement).toHaveText("Location;");
async.done();
});
});
}));
it('should allow to dispose even if the location has been removed',
inject([DynamicComponentLoader, TestComponentBuilder, AsyncTestCompleter],
(loader, tcb: TestComponentBuilder, async) => {
tcb.overrideView(MyComp, new ViewMetadata({
template: '<child-cmp *ngIf="ctxBoolProp"></child-cmp>',
directives: [NgIf, ChildComp]
}))
.overrideView(
ChildComp,
new ViewMetadata(
{template: '<location #loc></location>', directives: [Location]}))
.createAsync(MyComp)
.then((tc) => {
tc.debugElement.componentInstance.ctxBoolProp = true;
tc.detectChanges();
var childCompEl = tc.debugElement.query(By.css('child-cmp'));
loader.loadIntoLocation(DynamicallyLoaded, childCompEl.elementRef, 'loc')
.then(ref => {
expect(tc.debugElement.nativeElement)
.toHaveText("Location;DynamicallyLoaded;");
tc.debugElement.componentInstance.ctxBoolProp = false;
tc.detectChanges();
expect(tc.debugElement.nativeElement).toHaveText("");
ref.dispose();
expect(tc.debugElement.nativeElement).toHaveText("");
async.done();
});
});
}));
it('should update host properties',
inject([DynamicComponentLoader, TestComponentBuilder, AsyncTestCompleter],
(loader, tcb: TestComponentBuilder, async) => {
tcb.overrideView(
MyComp,
new ViewMetadata(
{template: '<location #loc></location>', directives: [Location]}))
.createAsync(MyComp)
.then((tc) => {
loader.loadIntoLocation(DynamicallyLoadedWithHostProps,
tc.debugElement.elementRef, 'loc')
.then(ref => {
ref.instance.id = "new value";
tc.detectChanges();
var newlyInsertedElement =
DOM.childNodes(tc.debugElement.nativeElement)[1];
expect((<HTMLElement>newlyInsertedElement).id).toEqual("new value");
async.done();
});
});
}));
it('should leave the view tree in a consistent state if hydration fails',
inject([DynamicComponentLoader, TestComponentBuilder, AsyncTestCompleter],
(loader, tcb: TestComponentBuilder, async) => {
@ -141,8 +139,8 @@ export function main() {
tc.debugElement
PromiseWrapper.catchError(
loader.loadIntoLocation(DynamicallyLoadedThrows, tc.elementRef,
'loc'),
loader.loadIntoLocation(DynamicallyLoadedThrows,
tc.debugElement.elementRef, 'loc'),
error => {
expect(error.message).toContain("ThrownInConstructor");
expect(() => tc.detectChanges()).not.toThrow();
@ -161,7 +159,8 @@ export function main() {
.createAsync(MyComp)
.then((tc) => {
expect(() => loader.loadIntoLocation(DynamicallyLoadedWithHostProps,
tc.elementRef, 'someUnknownVariable'))
tc.debugElement.elementRef,
'someUnknownVariable'))
.toThrowError('Could not find variable someUnknownVariable');
async.done();
});
@ -174,8 +173,9 @@ export function main() {
new ViewMetadata({template: '<div #loc></div>', directives: []}))
.createAsync(MyComp)
.then((tc) => {
loader.loadIntoLocation(DynamicallyLoadedWithNgContent, tc.elementRef,
'loc', null, [[DOM.createTextNode('hello')]])
loader.loadIntoLocation(DynamicallyLoadedWithNgContent,
tc.debugElement.elementRef, 'loc', null,
[[DOM.createTextNode('hello')]])
.then(ref => {
tc.detectChanges();
expect(tc.nativeElement).toHaveText('dynamic(hello)');
@ -193,8 +193,8 @@ export function main() {
.createAsync(MyComp)
.then((tc) => {
PromiseWrapper.catchError(
loader.loadIntoLocation(DynamicallyLoadedWithNgContent, tc.elementRef,
'loc', null, []),
loader.loadIntoLocation(DynamicallyLoadedWithNgContent,
tc.debugElement.elementRef, 'loc', null, []),
(e) => {
expect(e.message).toContain(
`The component ${stringify(DynamicallyLoadedWithNgContent)} has 1 <ng-content> elements, but only 0 slots were provided`);
@ -215,7 +215,7 @@ export function main() {
}))
.createAsync(MyComp)
.then((tc) => {
loader.loadNextToLocation(DynamicallyLoaded, tc.elementRef)
loader.loadNextToLocation(DynamicallyLoaded, tc.debugElement.elementRef)
.then(ref => {
expect(tc.debugElement.nativeElement).toHaveText("Location;");
expect(DOM.nextSibling(tc.debugElement.nativeElement))
@ -227,38 +227,38 @@ export function main() {
}));
it('should return a disposable component ref',
inject([DynamicComponentLoader, TestComponentBuilder, AsyncTestCompleter],
(loader, tcb: TestComponentBuilder, async) => {
tcb.overrideView(MyComp, new ViewMetadata({
template: '<div><location #loc></location></div>',
directives: [Location]
}))
.
inject(
[DynamicComponentLoader, TestComponentBuilder, AsyncTestCompleter],
(loader, tcb: TestComponentBuilder, async) => {
tcb.overrideView(MyComp, new ViewMetadata({
template: '<div><location #loc></location></div>',
directives: [Location]
}))
.
createAsync(MyComp)
.then((tc) => {
loader.loadNextToLocation(DynamicallyLoaded, tc.elementRef)
.then(ref => {
loader.loadNextToLocation(DynamicallyLoaded2, tc.elementRef)
.then(ref2 => {
var firstSibling =
DOM.nextSibling(tc.debugElement.nativeElement);
var secondSibling = DOM.nextSibling(firstSibling);
expect(tc.debugElement.nativeElement).toHaveText("Location;");
expect(firstSibling).toHaveText("DynamicallyLoaded;");
expect(secondSibling).toHaveText("DynamicallyLoaded2;");
createAsync(MyComp)
.then((tc) => {
loader.loadNextToLocation(DynamicallyLoaded, tc.debugElement.elementRef)
.then(ref => {
loader.loadNextToLocation(DynamicallyLoaded2, tc.debugElement.elementRef)
.then(ref2 => {
var firstSibling = DOM.nextSibling(tc.debugElement.nativeElement);
var secondSibling = DOM.nextSibling(firstSibling);
expect(tc.debugElement.nativeElement).toHaveText("Location;");
expect(firstSibling).toHaveText("DynamicallyLoaded;");
expect(secondSibling).toHaveText("DynamicallyLoaded2;");
ref2.dispose();
ref2.dispose();
firstSibling = DOM.nextSibling(tc.debugElement.nativeElement);
secondSibling = DOM.nextSibling(firstSibling);
expect(secondSibling).toBeNull();
firstSibling = DOM.nextSibling(tc.debugElement.nativeElement);
secondSibling = DOM.nextSibling(firstSibling);
expect(secondSibling).toBeNull();
async.done();
});
});
});
}));
async.done();
});
});
});
}));
it('should update host properties',
inject([DynamicComponentLoader, TestComponentBuilder, AsyncTestCompleter],
@ -271,7 +271,8 @@ export function main() {
.createAsync(MyComp)
.then((tc) => {
loader.loadNextToLocation(DynamicallyLoadedWithHostProps, tc.elementRef)
loader.loadNextToLocation(DynamicallyLoadedWithHostProps,
tc.debugElement.elementRef)
.then(ref => {
ref.instance.id = "new value";
@ -292,8 +293,9 @@ export function main() {
tcb.overrideView(MyComp, new ViewMetadata({template: '', directives: [Location]}))
.createAsync(MyComp)
.then((tc) => {
loader.loadNextToLocation(DynamicallyLoadedWithNgContent, tc.elementRef,
null, [[DOM.createTextNode('hello')]])
loader.loadNextToLocation(DynamicallyLoadedWithNgContent,
tc.debugElement.elementRef, null,
[[DOM.createTextNode('hello')]])
.then(ref => {
tc.detectChanges();
var newlyInsertedElement =

View File

@ -3,7 +3,7 @@ library angular2.test.di.integration_dart_spec;
import 'package:angular2/angular2.dart';
import 'package:angular2/core.dart';
import 'package:angular2/src/core/debug/debug_node.dart';
import 'package:angular2/src/core/debug/debug_element.dart';
import 'package:angular2/testing_internal.dart';
import 'package:observe/observe.dart';
import 'package:angular2/src/core/change_detection/differs/default_iterable_differ.dart';
@ -56,7 +56,7 @@ main() {
.createAsync(Dummy)
.then((tc) {
tc.detectChanges();
expect(asNativeElements(tc.debugElement.children))
expect(asNativeElements(tc.debugElement.componentViewChildren))
.toHaveText('[Hello, World]');
async.done();
});
@ -112,7 +112,7 @@ main() {
.createAsync(Dummy)
.then((tc) {
tc.detectChanges();
expect(asNativeElements(tc.debugElement.children))
expect(asNativeElements(tc.debugElement.componentViewChildren))
.toHaveText('prop:foo-prop;map:foo-map');
async.done();
});
@ -149,7 +149,7 @@ main() {
.createAsync(Dummy)
.then((tc) {
tc.detectChanges();
var cmp = tc.debugElement.children[0]
var cmp = tc.debugElement.componentViewChildren[0]
.inject(OnChangeComponent);
expect(cmp.prop).toEqual('hello');
expect(cmp.changes.containsKey('prop')).toEqual(true);
@ -178,7 +178,7 @@ main() {
tc.detectChanges();
expect(log.result()).toEqual("check");
expect(asNativeElements(tc.debugElement.children))
expect(asNativeElements(tc.debugElement.componentViewChildren))
.toHaveText('12');
tc.detectChanges();
@ -194,7 +194,7 @@ main() {
// we changed the list => a check
expect(log.result()).toEqual("check; check");
expect(asNativeElements(tc.debugElement.children))
expect(asNativeElements(tc.debugElement.componentViewChildren))
.toHaveText('123');
// we replaced the list => a check
@ -204,7 +204,7 @@ main() {
tc.detectChanges();
expect(log.result()).toEqual("check; check; check");
expect(asNativeElements(tc.debugElement.children))
expect(asNativeElements(tc.debugElement.componentViewChildren))
.toHaveText('567');
});
})));

View File

@ -160,7 +160,8 @@ function declareTests() {
fixture.debugElement.componentInstance.ctxProp = 'Hello World!';
fixture.detectChanges();
expect(fixture.debugElement.children[0].nativeElement.id).toEqual('Hello World!');
expect(fixture.debugElement.componentViewChildren[0].nativeElement.id)
.toEqual('Hello World!');
async.done();
});
}));
@ -175,13 +176,15 @@ function declareTests() {
fixture.debugElement.componentInstance.ctxProp = 'Initial aria label';
fixture.detectChanges();
expect(
DOM.getAttribute(fixture.debugElement.children[0].nativeElement, 'aria-label'))
DOM.getAttribute(fixture.debugElement.componentViewChildren[0].nativeElement,
'aria-label'))
.toEqual('Initial aria label');
fixture.debugElement.componentInstance.ctxProp = 'Changed aria label';
fixture.detectChanges();
expect(
DOM.getAttribute(fixture.debugElement.children[0].nativeElement, 'aria-label'))
DOM.getAttribute(fixture.debugElement.componentViewChildren[0].nativeElement,
'aria-label'))
.toEqual('Changed aria label');
async.done();
@ -198,12 +201,14 @@ function declareTests() {
fixture.debugElement.componentInstance.ctxProp = 'bar';
fixture.detectChanges();
expect(DOM.getAttribute(fixture.debugElement.children[0].nativeElement, 'foo'))
expect(DOM.getAttribute(
fixture.debugElement.componentViewChildren[0].nativeElement, 'foo'))
.toEqual('bar');
fixture.debugElement.componentInstance.ctxProp = null;
fixture.detectChanges();
expect(DOM.hasAttribute(fixture.debugElement.children[0].nativeElement, 'foo'))
expect(DOM.hasAttribute(
fixture.debugElement.componentViewChildren[0].nativeElement, 'foo'))
.toBeFalsy();
async.done();
@ -220,12 +225,14 @@ function declareTests() {
fixture.debugElement.componentInstance.ctxProp = '10';
fixture.detectChanges();
expect(DOM.getStyle(fixture.debugElement.children[0].nativeElement, 'height'))
expect(DOM.getStyle(fixture.debugElement.componentViewChildren[0].nativeElement,
'height'))
.toEqual('10px');
fixture.debugElement.componentInstance.ctxProp = null;
fixture.detectChanges();
expect(DOM.getStyle(fixture.debugElement.children[0].nativeElement, 'height'))
expect(DOM.getStyle(fixture.debugElement.componentViewChildren[0].nativeElement,
'height'))
.toEqual('');
async.done();
@ -241,11 +248,13 @@ function declareTests() {
.then((fixture) => {
fixture.detectChanges();
expect(fixture.debugElement.children[0].nativeElement.tabIndex).toEqual(0);
expect(fixture.debugElement.componentViewChildren[0].nativeElement.tabIndex)
.toEqual(0);
fixture.debugElement.componentInstance.ctxNumProp = 5;
fixture.detectChanges();
expect(fixture.debugElement.children[0].nativeElement.tabIndex).toEqual(5);
expect(fixture.debugElement.componentViewChildren[0].nativeElement.tabIndex)
.toEqual(5);
async.done();
});
@ -260,11 +269,13 @@ function declareTests() {
.then((fixture) => {
fixture.detectChanges();
expect(fixture.debugElement.children[0].nativeElement.readOnly).toBeFalsy();
expect(fixture.debugElement.componentViewChildren[0].nativeElement.readOnly)
.toBeFalsy();
fixture.debugElement.componentInstance.ctxBoolProp = true;
fixture.detectChanges();
expect(fixture.debugElement.children[0].nativeElement.readOnly).toBeTruthy();
expect(fixture.debugElement.componentViewChildren[0].nativeElement.readOnly)
.toBeTruthy();
async.done();
});
@ -280,12 +291,14 @@ function declareTests() {
fixture.debugElement.componentInstance.ctxProp = 'Some <span>HTML</span>';
fixture.detectChanges();
expect(DOM.getInnerHTML(fixture.debugElement.children[0].nativeElement))
expect(
DOM.getInnerHTML(fixture.debugElement.componentViewChildren[0].nativeElement))
.toEqual('Some <span>HTML</span>');
fixture.debugElement.componentInstance.ctxProp = 'Some other <div>HTML</div>';
fixture.detectChanges();
expect(DOM.getInnerHTML(fixture.debugElement.children[0].nativeElement))
expect(
DOM.getInnerHTML(fixture.debugElement.componentViewChildren[0].nativeElement))
.toEqual('Some other <div>HTML</div>');
async.done();
@ -300,7 +313,7 @@ function declareTests() {
.createAsync(MyComp)
.then((fixture) => {
var nativeEl = fixture.debugElement.children[0].nativeElement;
var nativeEl = fixture.debugElement.componentViewChildren[0].nativeElement;
fixture.debugElement.componentInstance.ctxProp = 'foo bar';
fixture.detectChanges();
@ -327,12 +340,13 @@ function declareTests() {
fixture.debugElement.componentInstance.ctxProp = 'Hello World!';
fixture.detectChanges();
var containerSpan = fixture.debugElement.children[0];
expect(containerSpan.children[0].inject(MyDir).dirProp).toEqual('Hello World!');
expect(containerSpan.children[1].inject(MyDir).dirProp).toEqual('Hi there!');
expect(containerSpan.children[2].inject(MyDir).dirProp).toEqual('Hi there!');
expect(containerSpan.children[3].inject(MyDir).dirProp)
expect(fixture.debugElement.componentViewChildren[0].inject(MyDir).dirProp)
.toEqual('Hello World!');
expect(fixture.debugElement.componentViewChildren[1].inject(MyDir).dirProp)
.toEqual('Hi there!');
expect(fixture.debugElement.componentViewChildren[2].inject(MyDir).dirProp)
.toEqual('Hi there!');
expect(fixture.debugElement.componentViewChildren[3].inject(MyDir).dirProp)
.toEqual('One more Hello World!');
async.done();
});
@ -354,7 +368,7 @@ function declareTests() {
fixture.debugElement.componentInstance.ctxProp = 'a';
fixture.detectChanges();
var dir = fixture.debugElement.children[0].getLocal('dir');
var dir = fixture.debugElement.componentViewChildren[0].getLocal('dir');
expect(dir.dirProp).toEqual('aa');
async.done();
});
@ -391,7 +405,7 @@ function declareTests() {
fixture.debugElement.componentInstance.ctxProp = 'Hello World!';
fixture.detectChanges();
var tc = fixture.debugElement.children[0];
var tc = fixture.debugElement.componentViewChildren[0];
expect(tc.inject(MyDir).dirProp).toEqual('Hello World!');
expect(tc.inject(ChildComp).dirProp).toEqual(null);
@ -433,7 +447,7 @@ function declareTests() {
.createAsync(MyComp)
.then((fixture) => {
var tc = fixture.debugElement.children[0];
var tc = fixture.debugElement.componentViewChildren[0];
var idDir = tc.inject(IdDir);
fixture.debugElement.componentInstance.ctxProp = 'some_id';
@ -549,7 +563,7 @@ function declareTests() {
.createAsync(MyComp)
.then((fixture) => {
expect(fixture.debugElement.children[0].children[0].getLocal('alice'))
expect(fixture.debugElement.componentViewChildren[0].getLocal('alice'))
.toBeAnInstanceOf(ChildComp);
async.done();
@ -565,7 +579,7 @@ function declareTests() {
.createAsync(MyComp)
.then((fixture) => {
expect(fixture.debugElement.children[0].children[0].getLocal('localdir'))
expect(fixture.debugElement.componentViewChildren[0].getLocal('localdir'))
.toBeAnInstanceOf(ExportDir);
async.done();
@ -606,31 +620,34 @@ function declareTests() {
.createAsync(MyComp)
.then((fixture) => {
var childCmp = fixture.debugElement.children[0].children[0];
expect(childCmp.getLocal('alice')).toBeAnInstanceOf(ChildComp);
expect(childCmp.getLocal('bob')).toBeAnInstanceOf(ChildComp);
expect(childCmp.getLocal('alice')).not.toBe(childCmp.getLocal('bob'));
expect(fixture.debugElement.componentViewChildren[0].getLocal('alice'))
.toBeAnInstanceOf(ChildComp);
expect(fixture.debugElement.componentViewChildren[0].getLocal('bob'))
.toBeAnInstanceOf(ChildComp);
expect(fixture.debugElement.componentViewChildren[0].getLocal('alice'))
.not.toBe(
fixture.debugElement.componentViewChildren[0].getLocal('bob'));
async.done();
})}));
it('should assign the component instance to a var- with shorthand syntax',
inject([TestComponentBuilder, AsyncTestCompleter],
(tcb: TestComponentBuilder,
async) => {tcb.overrideView(MyComp, new ViewMetadata({
template: '<child-cmp #alice></child-cmp>',
directives: [ChildComp]
}))
(tcb: TestComponentBuilder, async) => {
tcb.overrideView(MyComp, new ViewMetadata({
template: '<child-cmp #alice></child-cmp>',
directives: [ChildComp]
}))
.createAsync(MyComp)
.then((fixture) => {
.createAsync(MyComp)
.then((fixture) => {
expect(fixture.debugElement.children[0].getLocal('alice'))
.toBeAnInstanceOf(ChildComp);
expect(fixture.debugElement.componentViewChildren[0].getLocal('alice'))
.toBeAnInstanceOf(ChildComp);
async.done();
})}));
async.done();
})}));
it('should assign the element instance to a user-defined variable',
inject([TestComponentBuilder, AsyncTestCompleter],
@ -643,7 +660,7 @@ function declareTests() {
.then((fixture) => {
var value =
fixture.debugElement.children[0].children[0].getLocal('alice');
fixture.debugElement.componentViewChildren[0].getLocal('alice');
expect(value).not.toBe(null);
expect(value.tagName.toLowerCase()).toEqual('div');
@ -660,7 +677,7 @@ function declareTests() {
.createAsync(MyComp)
.then((fixture) => {
expect(fixture.debugElement.children[0].children[0].getLocal('superAlice'))
expect(fixture.debugElement.componentViewChildren[0].getLocal('superAlice'))
.toBeAnInstanceOf(ChildComp);
async.done();
@ -702,7 +719,7 @@ function declareTests() {
.createAsync(MyComp)
.then((fixture) => {
var cmp = fixture.debugElement.children[0].getLocal('cmp');
var cmp = fixture.debugElement.componentViewChildren[0].getLocal('cmp');
fixture.detectChanges();
expect(cmp.numberOfChecks).toEqual(1);
@ -728,7 +745,7 @@ function declareTests() {
.createAsync(MyComp)
.then((fixture) => {
var cmp = fixture.debugElement.children[0].getLocal('cmp');
var cmp = fixture.debugElement.componentViewChildren[0].getLocal('cmp');
fixture.debugElement.componentInstance.ctxProp = "one";
fixture.detectChanges();
@ -754,7 +771,7 @@ function declareTests() {
.createAsync(MyComp)
.then((fixture) => {
var cmp = fixture.debugElement.children[0].getLocal('cmp');
var cmp = fixture.debugElement.componentViewChildren[0].getLocal('cmp');
fixture.debugElement.componentInstance.ctxProp = "one";
fixture.detectChanges();
@ -780,7 +797,7 @@ function declareTests() {
tcb.createAsync(MyComp).then(root => { fixture = root; });
tick();
var cmp = fixture.debugElement.children[0].getLocal('cmp');
var cmp = fixture.debugElement.componentViewChildren[0].getLocal('cmp');
fixture.detectChanges();
expect(cmp.numberOfChecks).toEqual(1);
@ -813,7 +830,8 @@ function declareTests() {
.createAsync(MyComp)
.then((fixture) => {
var childComponent = fixture.debugElement.children[0].getLocal('child');
var childComponent =
fixture.debugElement.componentViewChildren[0].getLocal('child');
expect(childComponent.myHost).toBeAnInstanceOf(SomeDirective);
async.done();
@ -835,7 +853,7 @@ function declareTests() {
.then((fixture) => {
fixture.detectChanges();
var tc = fixture.debugElement.children[0].children[0].children[0];
var tc = fixture.debugElement.componentViewChildren[0].children[1];
var childComponent = tc.getLocal('child');
expect(childComponent.myHost).toBeAnInstanceOf(SomeDirective);
@ -854,7 +872,7 @@ function declareTests() {
.createAsync(MyComp)
.then((fixture) => {
var tc = fixture.debugElement.children[0];
var tc = fixture.debugElement.componentViewChildren[0];
var emitter = tc.inject(DirectiveEmittingEvent);
var listener = tc.inject(DirectiveListeningEvent);
@ -889,10 +907,9 @@ function declareTests() {
.createAsync(MyComp)
.then((fixture) => {
var tc = fixture.debugElement.childNodes[0];
var tc = fixture.debugElement.componentViewChildren[0];
var emitter = tc.inject(DirectiveEmittingEvent);
var myComp = fixture.debugElement.inject(MyComp);
var myComp = tc.inject(MyComp);
var listener = tc.inject(DirectiveListeningEvent);
myComp.ctxProp = '';
@ -917,7 +934,7 @@ function declareTests() {
.createAsync(MyComp)
.then((fixture) => {
var tc = fixture.debugElement.children[0];
var tc = fixture.debugElement.componentViewChildren[0];
var dir = tc.inject(DirectiveWithTwoWayBinding);
fixture.debugElement.componentInstance.ctxProp = 'one';
@ -944,7 +961,7 @@ function declareTests() {
.createAsync(MyComp)
.then((fixture) => {
var tc = fixture.debugElement.children[0];
var tc = fixture.debugElement.componentViewChildren[0];
var listener = tc.inject(DirectiveListeningDomEvent);
dispatchEvent(tc.nativeElement, 'domEvent');
@ -971,7 +988,7 @@ function declareTests() {
.createAsync(MyComp)
.then((fixture) => {
var tc = fixture.debugElement.children[0];
var tc = fixture.debugElement.componentViewChildren[0];
var listener = tc.inject(DirectiveListeningDomEvent);
dispatchEvent(DOM.getGlobalEventTarget("window"), 'domEvent');
expect(listener.eventTypes).toEqual(['window_domEvent']);
@ -1000,7 +1017,8 @@ function declareTests() {
.then((fixture) => {
fixture.detectChanges();
expect(DOM.getAttribute(fixture.debugElement.children[0].nativeElement, "role"))
expect(DOM.getAttribute(
fixture.debugElement.componentViewChildren[0].nativeElement, "role"))
.toEqual("button");
async.done();
@ -1016,7 +1034,7 @@ function declareTests() {
.createAsync(MyComp)
.then((fixture) => {
var tc = fixture.debugElement.children[0];
var tc = fixture.debugElement.componentViewChildren[0];
var updateHost = tc.inject(DirectiveUpdatingHostProperties);
updateHost.id = "newId";
@ -1048,15 +1066,17 @@ function declareTests() {
.then((fixture) => {
var dispatchedEvent = DOM.createMouseEvent('click');
var dispatchedEvent2 = DOM.createMouseEvent('click');
DOM.dispatchEvent(fixture.debugElement.children[0].nativeElement,
DOM.dispatchEvent(fixture.debugElement.componentViewChildren[0].nativeElement,
dispatchedEvent);
DOM.dispatchEvent(fixture.debugElement.children[1].nativeElement,
DOM.dispatchEvent(fixture.debugElement.componentViewChildren[1].nativeElement,
dispatchedEvent2);
expect(DOM.isPrevented(dispatchedEvent)).toBe(true);
expect(DOM.isPrevented(dispatchedEvent2)).toBe(false);
expect(DOM.getChecked(fixture.debugElement.children[0].nativeElement))
expect(
DOM.getChecked(fixture.debugElement.componentViewChildren[0].nativeElement))
.toBeFalsy();
expect(DOM.getChecked(fixture.debugElement.children[1].nativeElement))
expect(
DOM.getChecked(fixture.debugElement.componentViewChildren[1].nativeElement))
.toBeTruthy();
async.done();
});
@ -1078,7 +1098,7 @@ function declareTests() {
fixture.debugElement.componentInstance.ctxBoolProp = true;
fixture.detectChanges();
var tc = fixture.debugElement.children[0];
var tc = fixture.debugElement.componentViewChildren[1];
var listener = tc.inject(DirectiveListeningDomEvent);
var listenerother = tc.inject(DirectiveListeningDomEventOther);
@ -1116,11 +1136,11 @@ function declareTests() {
.createAsync(MyComp)
.then((fixture) => {
var tc = fixture.debugElement.children[0].children[0];
var tc = fixture.debugElement.componentViewChildren[0];
var dynamicVp = tc.inject(DynamicViewport);
dynamicVp.done.then((_) => {
fixture.detectChanges();
expect(fixture.debugElement.children[0].children[1].nativeElement)
expect(fixture.debugElement.componentViewChildren[1].nativeElement)
.toHaveText('dynamic greet');
async.done();
});
@ -1137,7 +1157,7 @@ function declareTests() {
{template: '<input static type="text" title>', directives: [NeedsAttribute]}))
.createAsync(MyComp)
.then((fixture) => {
var tc = fixture.debugElement.children[0];
var tc = fixture.debugElement.componentViewChildren[0];
var needsAttribute = tc.inject(NeedsAttribute);
expect(needsAttribute.typeAttribute).toEqual('text');
expect(needsAttribute.staticAttribute).toEqual('');
@ -1163,7 +1183,7 @@ function declareTests() {
}))
.createAsync(MyComp)
.then((fixture) => {
var comp = fixture.debugElement.children[0].getLocal("consuming");
var comp = fixture.debugElement.componentViewChildren[0].getLocal("consuming");
expect(comp.injectable).toBeAnInstanceOf(InjectableService);
async.done();
@ -1181,7 +1201,7 @@ function declareTests() {
}))
.createAsync(DirectiveProvidingInjectableInView)
.then((fixture) => {
var comp = fixture.debugElement.children[0].getLocal("consuming");
var comp = fixture.debugElement.componentViewChildren[0].getLocal("consuming");
expect(comp.injectable).toBeAnInstanceOf(InjectableService);
async.done();
@ -1211,7 +1231,7 @@ function declareTests() {
.createAsync(MyComp)
.then((fixture) => {
var comp = fixture.debugElement.children[0].getLocal("dir");
var comp = fixture.debugElement.componentViewChildren[0].getLocal("dir");
expect(comp.directive.injectable).toBeAnInstanceOf(InjectableService);
async.done();
@ -1237,7 +1257,7 @@ function declareTests() {
}))
.createAsync(MyComp)
.then((fixture) => {
var gpComp = fixture.debugElement.children[0];
var gpComp = fixture.debugElement.componentViewChildren[0];
var parentComp = gpComp.children[0];
var childComp = parentComp.children[0];
@ -1269,7 +1289,8 @@ function declareTests() {
}))
.createAsync(MyComp)
.then((fixture) => {
var providing = fixture.debugElement.children[0].getLocal("providing");
var providing =
fixture.debugElement.componentViewChildren[0].getLocal("providing");
expect(providing.created).toBe(false);
fixture.debugElement.componentInstance.ctxBoolProp = true;
@ -1414,7 +1435,7 @@ function declareTests() {
tcb.createAsync(MyComp).then(root => { fixture = root; });
tick();
var tc = fixture.debugElement.children[0];
var tc = fixture.debugElement.componentViewChildren[0];
tc.inject(DirectiveEmittingEvent).fireEvent("boom");
try {
@ -1729,7 +1750,8 @@ function declareTests() {
.createAsync(MyComp)
.then((fixture) => {
fixture.detectChanges();
var dir = fixture.debugElement.children[0].inject(DirectiveWithPropDecorators);
var dir = fixture.debugElement.componentViewChildren[0].inject(
DirectiveWithPropDecorators);
expect(dir.dirProp).toEqual("aaa");
async.done();
});
@ -1744,11 +1766,13 @@ function declareTests() {
.createAsync(MyComp)
.then((fixture) => {
fixture.detectChanges();
var dir = fixture.debugElement.children[0].inject(DirectiveWithPropDecorators);
var dir = fixture.debugElement.componentViewChildren[0].inject(
DirectiveWithPropDecorators);
dir.myAttr = "aaa";
fixture.detectChanges();
expect(DOM.getOuterHTML(fixture.debugElement.children[0].nativeElement))
expect(
DOM.getOuterHTML(fixture.debugElement.componentViewChildren[0].nativeElement))
.toContain('my-attr="aaa"');
async.done();
});
@ -1767,8 +1791,8 @@ function declareTests() {
tcb.createAsync(MyComp).then(root => { fixture = root; });
tick();
var emitter =
fixture.debugElement.children[0].inject(DirectiveWithPropDecorators);
var emitter = fixture.debugElement.componentViewChildren[0].inject(
DirectiveWithPropDecorators);
emitter.fireEvent('fired !');
tick();
@ -1778,23 +1802,24 @@ function declareTests() {
it('should support host listener decorators',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder,
async) => {
tcb.overrideView(MyComp, new ViewMetadata({
template: '<with-prop-decorators></with-prop-decorators>',
directives: [DirectiveWithPropDecorators]
}))
.createAsync(MyComp)
.then((fixture) => {
fixture.detectChanges();
var dir = fixture.debugElement.children[0].inject(DirectiveWithPropDecorators);
var native = fixture.debugElement.children[0].nativeElement;
DOM.dispatchEvent(native, DOM.createMouseEvent('click'));
inject([TestComponentBuilder, AsyncTestCompleter],
(tcb: TestComponentBuilder, async) => {
tcb.overrideView(MyComp, new ViewMetadata({
template: '<with-prop-decorators></with-prop-decorators>',
directives: [DirectiveWithPropDecorators]
}))
.createAsync(MyComp)
.then((fixture) => {
fixture.detectChanges();
var dir = fixture.debugElement.componentViewChildren[0].inject(
DirectiveWithPropDecorators);
var native = fixture.debugElement.componentViewChildren[0].nativeElement;
DOM.dispatchEvent(native, DOM.createMouseEvent('click'));
expect(dir.target).toBe(native);
async.done();
});
}));
expect(dir.target).toBe(native);
async.done();
});
}));
}
it('should support defining views in the component decorator',
@ -1806,7 +1831,7 @@ function declareTests() {
.createAsync(MyComp)
.then((fixture) => {
fixture.detectChanges();
var native = fixture.debugElement.children[0].nativeElement;
var native = fixture.debugElement.componentViewChildren[0].nativeElement;
expect(native).toHaveText("No View Decorator: 123");
async.done();
});

View File

@ -21,6 +21,7 @@ import {
} from 'angular2/testing_internal';
import {DOM} from 'angular2/src/platform/dom/dom_adapter';
import {AppViewListener} from 'angular2/src/core/linker/view_listener';
import {
bind,
@ -33,15 +34,17 @@ import {
View,
ViewContainerRef,
ViewEncapsulation,
ViewMetadata
ViewMetadata,
Scope
} from 'angular2/core';
import {
By,
} from 'angular2/platform/common_dom';
import {getAllDebugNodes} from 'angular2/src/core/debug/debug_node';
export function main() {
describe('projection', () => {
beforeEachProviders(() => [provide(AppViewListener, {useClass: AppViewListener})]);
it('should support simple components',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => {
tcb.overrideView(MainComp, new ViewMetadata({
@ -196,8 +199,7 @@ export function main() {
.then((main) => {
var viewportDirectives =
main.debugElement.children[0]
.childNodes.filter(By.directive(ManualViewportDirective))
main.debugElement.queryAll(By.directive(ManualViewportDirective))
.map(de => de.inject(ManualViewportDirective));
expect(main.debugElement.nativeElement).toHaveText('(, B)');
@ -242,8 +244,8 @@ export function main() {
.then((main) => {
var viewportDirective =
main.debugElement.queryAllNodes(By.directive(ManualViewportDirective))[0].inject(
ManualViewportDirective);
main.debugElement.query(By.directive(ManualViewportDirective))
.inject(ManualViewportDirective);
expect(main.debugElement.nativeElement).toHaveText('OUTER(INNER(INNERINNER(,BC)))');
viewportDirective.show();
@ -267,8 +269,8 @@ export function main() {
.then((main) => {
var viewportDirective =
main.debugElement.queryAllNodes(By.directive(ManualViewportDirective))[0].inject(
ManualViewportDirective);
main.debugElement.query(By.directive(ManualViewportDirective))
.inject(ManualViewportDirective);
expect(main.debugElement.nativeElement).toHaveText('(, BC)');
@ -334,20 +336,12 @@ export function main() {
}))
.createAsync(MainComp)
.then((main) => {
var sourceDirective;
// We can't use the child nodes to get a hold of this because it's not in the dom at
// all.
getAllDebugNodes().forEach((debug) => {
if (debug.providerTokens.indexOf(ManualViewportDirective) !== -1) {
sourceDirective = debug.inject(ManualViewportDirective);
}
});
var sourceDirective: ManualViewportDirective =
main.debugElement.query(By.directive(ManualViewportDirective))
.inject(ManualViewportDirective);
var projectDirective: ProjectDirective =
main.debugElement.queryAllNodes(By.directive(ProjectDirective))[0].inject(
ProjectDirective);
main.debugElement.query(By.directive(ProjectDirective)).inject(ProjectDirective);
expect(main.debugElement.nativeElement).toHaveText('START()END');
projectDirective.show(sourceDirective.templateRef);
@ -367,11 +361,10 @@ export function main() {
.then((main) => {
var sourceDirective: ManualViewportDirective =
main.debugElement.queryAllNodes(By.directive(ManualViewportDirective))[0].inject(
ManualViewportDirective);
main.debugElement.query(By.directive(ManualViewportDirective))
.inject(ManualViewportDirective);
var projectDirective: ProjectDirective =
main.debugElement.queryAllNodes(By.directive(ProjectDirective))[0].inject(
ProjectDirective);
main.debugElement.query(By.directive(ProjectDirective)).inject(ProjectDirective);
expect(main.debugElement.nativeElement).toHaveText('SIMPLE()START()END');
projectDirective.show(sourceDirective.templateRef);
@ -396,11 +389,10 @@ export function main() {
.then((main) => {
var sourceDirective: ManualViewportDirective =
main.debugElement.queryAllNodes(By.directive(ManualViewportDirective))[0].inject(
ManualViewportDirective);
main.debugElement.query(By.directive(ManualViewportDirective))
.inject(ManualViewportDirective);
var projectDirective: ProjectDirective =
main.debugElement.queryAllNodes(By.directive(ProjectDirective))[0].inject(
ProjectDirective);
main.debugElement.query(By.directive(ProjectDirective)).inject(ProjectDirective);
expect(main.debugElement.nativeElement).toHaveText('(, B)START()END');
projectDirective.show(sourceDirective.templateRef);
@ -427,8 +419,8 @@ export function main() {
main.detectChanges();
var manualDirective: ManualViewportDirective =
main.debugElement.queryAllNodes(By.directive(ManualViewportDirective))[0].inject(
ManualViewportDirective);
main.debugElement.query(By.directive(ManualViewportDirective))
.inject(ManualViewportDirective);
expect(main.debugElement.nativeElement).toHaveText('TREE(0:)');
manualDirective.show();
main.detectChanges();
@ -488,12 +480,12 @@ export function main() {
expect(main.debugElement.nativeElement).toHaveText('MAIN()');
var viewportElement =
main.debugElement.queryAllNodes(By.directive(ManualViewportDirective))[0];
main.debugElement.componentViewChildren[0].componentViewChildren[0];
viewportElement.inject(ManualViewportDirective).show();
expect(main.debugElement.nativeElement).toHaveText('MAIN(FIRST())');
viewportElement =
main.debugElement.queryAllNodes(By.directive(ManualViewportDirective))[1];
main.debugElement.componentViewChildren[0].componentViewChildren[1];
viewportElement.inject(ManualViewportDirective).show();
expect(main.debugElement.nativeElement).toHaveText('MAIN(FIRST(SECOND(a)))');
@ -548,24 +540,21 @@ export function main() {
.then((main) => {
var conditionalComp =
main.debugElement.query(By.directive(ConditionalContentComponent));
var viewViewportDir =
conditionalComp.queryAllNodes(By.directive(ManualViewportDirective))[0].inject(
ManualViewportDirective);
expect(main.debugElement.nativeElement).toHaveText('(, D)');
expect(main.debugElement.nativeElement).toHaveText('(, D)');
viewViewportDir.show();
expect(main.debugElement.nativeElement).toHaveText('(AC, D)');
conditionalComp.query(By.directive(ManualViewportDirective), Scope.view)
.inject(ManualViewportDirective);
var contentViewportDir =
conditionalComp.queryAllNodes(By.directive(ManualViewportDirective))[1].inject(
ManualViewportDirective);
conditionalComp.query(By.directive(ManualViewportDirective), Scope.light)
.inject(ManualViewportDirective);
expect(main.debugElement.nativeElement).toHaveText('(, D)');
expect(main.debugElement.nativeElement).toHaveText('(, D)');
// first show content viewport, then the view viewport,
// i.e. projection needs to take create of already
// created views
contentViewportDir.show();
viewViewportDir.show();
expect(main.debugElement.nativeElement).toHaveText('(ABC, D)');
// hide view viewport, and test that it also hides

View File

@ -53,7 +53,8 @@ export function main() {
.then((view) => {
view.detectChanges();
expect(asNativeElements(view.debugElement.children)).toHaveText('2|3|');
expect(asNativeElements(view.debugElement.componentViewChildren))
.toHaveText('2|3|');
async.done();
});
@ -69,7 +70,7 @@ export function main() {
.then((view) => {
view.detectChanges();
var q = view.debugElement.children[0].getLocal('q');
var q = view.debugElement.componentViewChildren[0].getLocal('q');
view.detectChanges();
@ -91,7 +92,7 @@ export function main() {
view.debugElement.componentInstance.shouldShow = true;
view.detectChanges();
var q = view.debugElement.children[0].getLocal('q');
var q = view.debugElement.componentViewChildren[0].getLocal('q');
expect(q.log).toEqual([["setter", "foo"], ["init", "foo"], ["check", "foo"]]);
@ -120,36 +121,7 @@ export function main() {
.createAsync(MyComp)
.then((view) => {
view.detectChanges();
var q = view.debugElement.children[0].getLocal('q');
expect(q.log).toEqual([["setter", "foo"], ["init", "foo"], ["check", "foo"]]);
q.shouldShow = false;
view.detectChanges();
expect(q.log).toEqual([
["setter", "foo"],
["init", "foo"],
["check", "foo"],
["setter", null],
["check", null]
]);
async.done();
});
}));
it('should contain the first view child accross embedded views',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => {
var template = '<needs-view-child #q></needs-view-child>';
tcb.overrideTemplate(MyComp, template)
.overrideTemplate(
NeedsViewChild,
'<div *ngIf="true"><div *ngIf="shouldShow" text="foo"></div></div>')
.createAsync(MyComp)
.then((view) => {
view.detectChanges();
var q = view.debugElement.children[0].getLocal('q');
var q = view.debugElement.componentViewChildren[0].getLocal('q');
expect(q.log).toEqual([["setter", "foo"], ["init", "foo"], ["check", "foo"]]);
@ -180,7 +152,8 @@ export function main() {
.createAsync(MyComp)
.then((view) => {
view.detectChanges();
expect(asNativeElements(view.debugElement.children)).toHaveText('2|3|4|');
expect(asNativeElements(view.debugElement.componentViewChildren))
.toHaveText('2|3|4|');
async.done();
});
@ -196,7 +169,8 @@ export function main() {
.createAsync(MyComp)
.then((view) => {
view.detectChanges();
expect(asNativeElements(view.debugElement.children)).toHaveText('2|3|');
expect(asNativeElements(view.debugElement.componentViewChildren))
.toHaveText('2|3|');
async.done();
});
@ -214,11 +188,12 @@ export function main() {
.then((view) => {
view.detectChanges();
expect(asNativeElements(view.debugElement.children)).toHaveText('2|');
expect(asNativeElements(view.debugElement.componentViewChildren)).toHaveText('2|');
view.debugElement.componentInstance.shouldShow = true;
view.detectChanges();
expect(asNativeElements(view.debugElement.children)).toHaveText('2|3|');
expect(asNativeElements(view.debugElement.componentViewChildren))
.toHaveText('2|3|');
async.done();
});
@ -254,11 +229,13 @@ export function main() {
.then((view) => {
view.detectChanges();
expect(asNativeElements(view.debugElement.children)).toHaveText('2|1d|2d|3d|');
expect(asNativeElements(view.debugElement.componentViewChildren))
.toHaveText('2|1d|2d|3d|');
view.debugElement.componentInstance.list = ['3d', '2d'];
view.detectChanges();
expect(asNativeElements(view.debugElement.children)).toHaveText('2|3d|2d|');
expect(asNativeElements(view.debugElement.componentViewChildren))
.toHaveText('2|3d|2d|');
async.done();
});
@ -273,7 +250,8 @@ export function main() {
.createAsync(MyComp)
.then((view) => {
view.detectChanges();
var needsTpl: NeedsTpl = view.debugElement.children[0].inject(NeedsTpl);
var needsTpl: NeedsTpl =
view.debugElement.componentViewChildren[0].inject(NeedsTpl);
expect(needsTpl.vc.createEmbeddedView(needsTpl.query.first).hasLocal('light'))
.toBe(true);
@ -297,7 +275,7 @@ export function main() {
tcb.overrideTemplate(MyComp, template)
.createAsync(MyComp)
.then((view) => {
var q = view.debugElement.children[0].getLocal("q");
var q = view.debugElement.componentViewChildren[0].getLocal("q");
view.detectChanges();
ObservableWrapper.subscribe(q.query.changes, (_) => {
@ -322,8 +300,8 @@ export function main() {
tcb.overrideTemplate(MyComp, template)
.createAsync(MyComp)
.then((view) => {
var q1 = view.debugElement.children[0].getLocal("q1");
var q2 = view.debugElement.children[0].getLocal("q2");
var q1 = view.debugElement.componentViewChildren[0].getLocal("q1");
var q2 = view.debugElement.componentViewChildren[0].getLocal("q2");
var firedQ2 = false;
@ -347,8 +325,7 @@ export function main() {
view.debugElement.componentInstance.shouldShow = true;
view.detectChanges();
var q: NeedsQuery = view.debugElement.children[0].getLocal('q');
var q: NeedsQuery = view.debugElement.componentViewChildren[1].getLocal('q');
expect(q.query.length).toEqual(1);
view.debugElement.componentInstance.shouldShow = false;
@ -357,7 +334,7 @@ export function main() {
view.debugElement.componentInstance.shouldShow = true;
view.detectChanges();
var q2: NeedsQuery = view.debugElement.children[0].getLocal('q');
var q2: NeedsQuery = view.debugElement.componentViewChildren[1].getLocal('q');
expect(q2.query.length).toEqual(1);
@ -376,7 +353,7 @@ export function main() {
tcb.overrideTemplate(MyComp, template)
.createAsync(MyComp)
.then((view) => {
var q = view.debugElement.children[0].getLocal("q");
var q = view.debugElement.componentViewChildren[0].getLocal("q");
view.debugElement.componentInstance.list = ['1d', '2d'];
@ -399,7 +376,7 @@ export function main() {
tcb.overrideTemplate(MyComp, template)
.createAsync(MyComp)
.then((view) => {
var q = view.debugElement.children[0].getLocal("q");
var q = view.debugElement.componentViewChildren[0].getLocal("q");
view.detectChanges();
expect(q.query.first.text).toEqual("one");
@ -418,7 +395,7 @@ export function main() {
tcb.overrideTemplate(MyComp, template)
.createAsync(MyComp)
.then((view) => {
var q = view.debugElement.children[0].getLocal("q");
var q = view.debugElement.componentViewChildren[0].getLocal("q");
view.debugElement.componentInstance.list = ['1d', '2d'];
@ -445,7 +422,7 @@ export function main() {
tcb.overrideTemplate(MyComp, template)
.createAsync(MyComp)
.then((view) => {
var q = view.debugElement.children[0].getLocal("q");
var q = view.debugElement.componentViewChildren[0].getLocal("q");
view.debugElement.componentInstance.list = ['1d', '2d'];
@ -469,7 +446,8 @@ export function main() {
.then((view) => {
view.detectChanges();
expect(asNativeElements(view.debugElement.children)).toHaveText('hello|world|');
expect(asNativeElements(view.debugElement.componentViewChildren))
.toHaveText('hello|world|');
async.done();
});
@ -482,7 +460,8 @@ export function main() {
tcb.overrideTemplate(MyComp, template)
.createAsync(MyComp)
.then((view) => {
var q: NeedsViewQueryByLabel = view.debugElement.children[0].getLocal("q");
var q: NeedsViewQueryByLabel =
view.debugElement.componentViewChildren[0].getLocal("q");
view.detectChanges();
expect(q.query.first.nativeElement).toHaveText("text");
@ -500,7 +479,7 @@ export function main() {
.then((view) => {
view.detectChanges();
var q = view.debugElement.children[0].getLocal('q');
var q = view.debugElement.componentViewChildren[0].getLocal('q');
view.detectChanges();
@ -521,7 +500,7 @@ export function main() {
tcb.overrideTemplate(MyComp, template)
.createAsync(MyComp)
.then((view) => {
var q: NeedsViewQuery = view.debugElement.children[0].getLocal("q");
var q: NeedsViewQuery = view.debugElement.componentViewChildren[0].getLocal("q");
view.detectChanges();
@ -538,7 +517,7 @@ export function main() {
tcb.overrideTemplate(MyComp, template)
.createAsync(MyComp)
.then((view) => {
var q: NeedsViewQuery = view.debugElement.children[0].getLocal("q");
var q: NeedsViewQuery = view.debugElement.componentViewChildren[0].getLocal("q");
view.detectChanges();
@ -555,7 +534,7 @@ export function main() {
tcb.overrideTemplate(MyComp, template)
.createAsync(MyComp)
.then((view) => {
var q: NeedsViewQueryIf = view.debugElement.children[0].getLocal("q");
var q: NeedsViewQueryIf = view.debugElement.componentViewChildren[0].getLocal("q");
view.detectChanges();
@ -578,7 +557,8 @@ export function main() {
tcb.overrideTemplate(MyComp, template)
.createAsync(MyComp)
.then((view) => {
var q: NeedsViewQueryNestedIf = view.debugElement.children[0].getLocal("q");
var q: NeedsViewQueryNestedIf =
view.debugElement.componentViewChildren[0].getLocal("q");
view.detectChanges();
@ -603,7 +583,8 @@ export function main() {
tcb.overrideTemplate(MyComp, template)
.createAsync(MyComp)
.then((view) => {
var q: NeedsViewQueryOrder = view.debugElement.children[0].getLocal("q");
var q: NeedsViewQueryOrder =
view.debugElement.componentViewChildren[0].getLocal("q");
view.detectChanges();
@ -626,7 +607,8 @@ export function main() {
tcb.overrideTemplate(MyComp, template)
.createAsync(MyComp)
.then((view) => {
var q: NeedsViewQueryOrderWithParent = view.debugElement.children[0].getLocal("q");
var q: NeedsViewQueryOrderWithParent =
view.debugElement.componentViewChildren[0].getLocal("q");
view.detectChanges();
@ -649,7 +631,8 @@ export function main() {
tcb.overrideTemplate(MyComp, template)
.createAsync(MyComp)
.then((view) => {
var q: NeedsViewQueryOrder = view.debugElement.children[0].getLocal('q');
var q: NeedsViewQueryOrder =
view.debugElement.componentViewChildren[0].getLocal('q');
// no significance to 50, just a reasonably large cycle.
for (var i = 0; i < 50; i++) {
@ -673,7 +656,7 @@ export function main() {
.then((view) => {
view.detectChanges();
var q = view.debugElement.children[0].getLocal('q');
var q = view.debugElement.componentViewChildren[0].getLocal('q');
expect(q.query1).toBeDefined();
expect(q.query2).toBeDefined();
expect(q.query3).toBeDefined();
@ -758,6 +741,7 @@ class NeedsViewChild implements AfterViewInit,
ngAfterViewChecked() { this.log.push(["check", isPresent(this.child) ? this.child.text : null]); }
}
@Directive({selector: '[dir]'})
@Injectable()
class InertDirective {

View File

@ -8,6 +8,7 @@ import 'package:angular2/src/core/linker/directive_resolver.dart';
import 'package:angular2/src/core/linker/view.dart';
import 'package:angular2/src/core/linker/element_ref.dart';
import 'package:angular2/src/core/linker/view_manager.dart';
import 'package:angular2/src/core/linker/view_listener.dart';
import 'package:angular2/src/platform/dom/dom_adapter.dart';
import 'package:angular2/testing_internal.dart';
@ -51,5 +52,8 @@ class SpyRenderer extends SpyObject implements Renderer {}
@proxy
class SpyRootRenderer extends SpyObject implements RootRenderer {}
@proxy
class SpyAppViewListener extends SpyObject implements AppViewListener {}
@proxy
class SpyDomAdapter extends SpyObject implements DomAdapter {}

View File

@ -11,6 +11,7 @@ import {DirectiveResolver} from 'angular2/src/core/linker/directive_resolver';
import {AppView, AppProtoView, HostViewFactory} from 'angular2/src/core/linker/view';
import {ElementRef} from 'angular2/src/core/linker/element_ref';
import {AppViewManager_} from 'angular2/src/core/linker/view_manager';
import {AppViewListener} from 'angular2/src/core/linker/view_listener';
import {DomAdapter} from 'angular2/src/platform/dom/dom_adapter';
import {SpyObject, proxy} from 'angular2/testing_internal';
@ -70,7 +71,6 @@ export class SpyRenderer extends SpyObject {
this.spy('setElementProperty');
this.spy('setElementAttribute');
this.spy('setBindingDebugInfo');
this.spy('setElementDebugInfo');
this.spy('setElementClass');
this.spy('setElementStyle');
this.spy('invokeElementMethod');
@ -88,6 +88,10 @@ export class SpyRootRenderer extends SpyObject {
}
}
export class SpyAppViewListener extends SpyObject {
constructor() { super(AppViewListener); }
}
export class SpyDomAdapter extends SpyObject {
constructor() { super(DomAdapter); }
}

View File

@ -0,0 +1,71 @@
import {
AsyncTestCompleter,
beforeEach,
ddescribe,
xdescribe,
describe,
dispatchEvent,
expect,
iit,
inject,
beforeEachProviders,
it,
xit,
TestComponentBuilder,
} from 'angular2/testing_internal';
import {global} from 'angular2/src/facade/lang';
import {provide, Component, Directive, Injectable, View} from 'angular2/core';
import {inspectNativeElement} from 'angular2/platform/browser';
import {IS_DART} from 'angular2/src/facade/lang';
@Component({selector: 'my-comp'})
@View({directives: []})
@Injectable()
class MyComp {
ctxProp: string;
}
export function main() {
describe('element probe', function() {
it('should return a TestElement from a dom element',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => {
tcb.overrideTemplate(MyComp, '<div some-dir></div>')
.createAsync(MyComp)
.then((componentFixture) => {
expect(inspectNativeElement(componentFixture.debugElement.nativeElement)
.componentInstance)
.toBeAnInstanceOf(MyComp);
async.done();
});
}));
it('should clean up whent the view is destroyed',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => {
tcb.overrideTemplate(MyComp, '')
.createAsync(MyComp)
.then((componentFixture) => {
componentFixture.destroy();
expect(inspectNativeElement(componentFixture.debugElement.nativeElement)).toBe(null);
async.done();
});
}));
if (!IS_DART) {
it('should provide a global function to inspect elements',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => {
tcb.overrideTemplate(MyComp, '')
.createAsync(MyComp)
.then((componentFixture) => {
expect(global['ng']['probe'](componentFixture.debugElement.nativeElement)
.componentInstance)
.toBeAnInstanceOf(MyComp);
async.done();
});
}), 1000);
}
});
}

View File

@ -290,7 +290,6 @@ var NG_COMMON = [
'NgFor.ngDoCheck()',
'NgFor.ngForOf=',
'NgFor.ngForTemplate=',
'NgFor.ngForTrackBy=',
'NgForm',
'NgForm.addControl()',
'NgForm.addControlGroup()',
@ -889,60 +888,21 @@ var NG_CORE = [
'CyclicDependencyError.message=',
'CyclicDependencyError.stackTrace',
'PLATFORM_PIPES:js',
'DebugNode',
'DebugNode.getLocal()',
'DebugNode.inject()',
'DebugNode.setDebugInfo()',
'DebugNode.componentInstance',
'DebugNode.componentInstance=',
'DebugNode.injector',
'DebugNode.injector=',
'DebugNode.listeners',
'DebugNode.listeners=',
'DebugNode.locals',
'DebugNode.locals=',
'DebugNode.nativeNode',
'DebugNode.nativeNode=',
'DebugNode.parent',
'DebugNode.parent=',
'DebugNode.providerTokens',
'DebugNode.providerTokens=',
'DebugElement',
'DebugElement.children',
'DebugElement.attributes',
'DebugElement.attributes=',
'DebugElement.properties',
'DebugElement.properties=',
'DebugElement.childNodes',
'DebugElement.childNodes=',
'DebugElement.injector',
'DebugElement.injector=',
'DebugElement.listeners',
'DebugElement.listeners=',
'DebugElement.locals',
'DebugElement.locals=',
'DebugElement.name',
'DebugElement.name=',
'DebugElement.parent',
'DebugElement.parent=',
'DebugElement.componentInstance',
'DebugElement.componentInstance=',
'DebugElement.componentViewChildren',
'DebugElement.elementRef',
/*
Abstract methods
'DebugElement.getDirectiveInstance()',
'DebugElement.getLocal()',
'DebugElement.providerTokens',
'DebugElement.providerTokens=',
'DebugElement.hasDirective()',
'DebugElement.inject()',
'DebugElement.nativeNode',
'DebugElement.nativeNode=',
*/
'DebugElement.nativeElement',
'DebugElement.nativeElement=',
'DebugElement.query()',
'DebugElement.queryAll()',
'DebugElement.queryAllNodes()',
'DebugElement.triggerEventHandler()',
'DebugElement.setDebugInfo()',
'DebugElement.addChild()',
'DebugElement.removeChild()',
'DebugElement.insertChildrenAfter()',
'Dependency#fromKey()',
'Dependency',
'Dependency.key',
@ -1248,6 +1208,10 @@ var NG_CORE = [
'ResolvedFactory.dependencies=',
'ResolvedFactory.factory',
'ResolvedFactory.factory=',
'Scope#all()',
'Scope#light()',
'Scope#view()',
'Scope', // TODO(misko): rename?
'Self',
'SelfMetadata',
'SkipSelf',
@ -1390,6 +1354,7 @@ var NG_CORE = [
'provide()',
'createNgZone()',
'forwardRef():js',
'inspectElement()',
'platform():js',
'resolveForwardRef():js',
'PLATFORM_COMMON_PROVIDERS',
@ -1635,8 +1600,8 @@ var NG_PLATFORM_BROWSER = [
'By#directive():js',
'By:js',
'DOCUMENT',
'ELEMENT_PROBE_BINDINGS:js',
'ELEMENT_PROBE_PROVIDERS:js',
'ELEMENT_PROBE_PROVIDERS_PROD_MODE:js',
'Title.getTitle():js',
'Title.setTitle():js',
'Title:js',

View File

@ -12,9 +12,6 @@ import {
xit,
} from 'angular2/testing_internal';
import {By} from 'angular2/platform/common_dom';
import {specs, compile, TEST_ROUTER_PROVIDERS, clickOnElement, getHref} from '../util';
import {Router, AsyncRoute, Route, Location} from 'angular2/router';
@ -36,7 +33,7 @@ import {
} from './fixture_components';
function getLinkElement(rtc: ComponentFixture) {
return rtc.debugElement.query(By.css('a')).nativeElement;
return rtc.debugElement.componentViewChildren[0].nativeElement;
}
function asyncRoutesWithoutChildrenWithRouteData() {

View File

@ -15,7 +15,6 @@ import {
xit
} from 'angular2/testing_internal';
import {By} from 'angular2/platform/common_dom';
import {provide, Component, Injector, Inject} from 'angular2/core';
import {Router, ROUTER_DIRECTIVES, RouteParams, RouteData, Location} from 'angular2/router';
@ -25,7 +24,7 @@ import {specs, compile, TEST_ROUTER_PROVIDERS, clickOnElement, getHref} from '..
import {BaseException} from 'angular2/src/facade/exceptions';
function getLinkElement(rtc: ComponentFixture, linkIndex: number = 0) {
return rtc.debugElement.queryAll(By.css('a'))[linkIndex].nativeElement;
return rtc.debugElement.componentViewChildren[linkIndex].nativeElement;
}
function auxRoutes() {

View File

@ -14,14 +14,13 @@ import {
import {specs, compile, TEST_ROUTER_PROVIDERS, clickOnElement, getHref} from '../util';
import {By} from 'angular2/platform/common_dom';
import {Router, Route, Location} from 'angular2/router';
import {HelloCmp, UserCmp, TeamCmp, ParentCmp, ParentWithDefaultCmp} from './fixture_components';
function getLinkElement(rtc: ComponentFixture) {
return rtc.debugElement.query(By.css('a')).nativeElement;
return rtc.debugElement.componentViewChildren[0].nativeElement;
}
function syncRoutesWithoutChildrenWithoutParams() {

View File

@ -17,7 +17,6 @@ import {
SpyObject
} from 'angular2/testing_internal';
import {By} from 'angular2/platform/common_dom';
import {NumberWrapper} from 'angular2/src/facade/lang';
import {PromiseWrapper} from 'angular2/src/facade/async';
import {ListWrapper} from 'angular2/src/facade/collection';
@ -112,7 +111,9 @@ export function main() {
fixture.debugElement.componentInstance.name = 'brian';
fixture.detectChanges();
expect(fixture.debugElement.nativeElement).toHaveText('brian');
expect(getHref(fixture)).toEqual('/user/brian');
expect(DOM.getAttribute(fixture.debugElement.componentViewChildren[0].nativeElement,
'href'))
.toEqual('/user/brian');
async.done();
});
}));
@ -126,7 +127,11 @@ export function main() {
.then((_) => router.navigateByUrl('/page/1'))
.then((_) => {
fixture.detectChanges();
expect(getHref(fixture)).toEqual('/page/2');
expect(DOM.getAttribute(fixture.debugElement.componentViewChildren[1]
.componentViewChildren[0]
.nativeElement,
'href'))
.toEqual('/page/2');
async.done();
});
}));
@ -141,7 +146,11 @@ export function main() {
.then((_) => router.navigateByUrl('/page/1'))
.then((_) => {
fixture.detectChanges();
expect(getHref(fixture)).toEqual('/page/2');
expect(DOM.getAttribute(fixture.debugElement.componentViewChildren[1]
.componentViewChildren[0]
.nativeElement,
'href'))
.toEqual('/page/2');
async.done();
});
}));
@ -155,7 +164,11 @@ export function main() {
.then((_) => router.navigateByUrl('/book/1984/page/1'))
.then((_) => {
fixture.detectChanges();
expect(getHref(fixture)).toEqual('/book/1984/page/100');
expect(DOM.getAttribute(fixture.debugElement.componentViewChildren[1]
.componentViewChildren[0]
.nativeElement,
'href'))
.toEqual('/book/1984/page/100');
async.done();
});
}));
@ -189,7 +202,11 @@ export function main() {
.then((_) => router.navigateByUrl('/child-with-grandchild/grandchild'))
.then((_) => {
fixture.detectChanges();
expect(getHref(fixture)).toEqual('/child-with-grandchild/grandchild');
expect(DOM.getAttribute(fixture.debugElement.componentViewChildren[1]
.componentViewChildren[0]
.nativeElement,
'href'))
.toEqual('/child-with-grandchild/grandchild');
async.done();
});
}));
@ -202,17 +219,15 @@ export function main() {
.then((_) => router.navigateByUrl('/book/1984/page/1'))
.then((_) => {
fixture.detectChanges();
// TODO(juliemr): This should be one By.css('book-cmp a') query, but the parse5
// adapter
// can't handle css child selectors.
expect(DOM.getAttribute(fixture.debugElement.query(By.css('book-cmp'))
.query(By.css('a'))
expect(DOM.getAttribute(fixture.debugElement.componentViewChildren[1]
.componentViewChildren[0]
.nativeElement,
'href'))
.toEqual('/book/1984/page/100');
expect(DOM.getAttribute(fixture.debugElement.query(By.css('page-cmp'))
.query(By.css('a'))
expect(DOM.getAttribute(fixture.debugElement.componentViewChildren[1]
.componentViewChildren[2]
.componentViewChildren[0]
.nativeElement,
'href'))
.toEqual('/book/1984/page/2');
@ -226,7 +241,11 @@ export function main() {
.then((_) => router.navigateByUrl('/'))
.then((_) => {
fixture.detectChanges();
expect(getHref(fixture)).toEqual('/(aside)');
expect(DOM.getAttribute(fixture.debugElement.componentViewChildren[1]
.componentViewChildren[0]
.nativeElement,
'href'))
.toEqual('/(aside)');
async.done();
});
}));
@ -316,7 +335,9 @@ export function main() {
fixture.debugElement.componentInstance.name = 'brian';
fixture.detectChanges();
expect(fixture.debugElement.nativeElement).toHaveText('brian');
expect(getHref(fixture)).toEqual('/user/brian');
expect(DOM.getAttribute(
fixture.debugElement.componentViewChildren[0].nativeElement, 'href'))
.toEqual('/user/brian');
async.done();
});
}));
@ -326,7 +347,7 @@ export function main() {
describe('when clicked', () => {
var clickOnElement = function(view) {
var anchorEl = fixture.debugElement.query(By.css('a')).nativeElement;
var anchorEl = fixture.debugElement.componentViewChildren[0].nativeElement;
var dispatchedEvent = DOM.createMouseEvent('click');
DOM.dispatchEvent(anchorEl, dispatchedEvent);
return dispatchedEvent;
@ -377,7 +398,7 @@ export function main() {
}
function getHref(tc: ComponentFixture) {
return DOM.getAttribute(tc.debugElement.query(By.css('a')).nativeElement, 'href');
return DOM.getAttribute(tc.debugElement.componentViewChildren[0].nativeElement, 'href');
}
@Component({selector: 'my-comp'})

View File

@ -325,7 +325,7 @@ export function main() {
done();
});
restoreJasmineIt();
}, 10000);
});
describe('using beforeEachProviders', () => {
beforeEachProviders(() => [bind(FancyService).toValue(new FancyService())]);

View File

@ -417,35 +417,6 @@ export function main() {
});
}));
it('should support bindToController with bindings', inject([AsyncTestCompleter], (async) => {
var adapter = new UpgradeAdapter();
var ng1Module = angular.module('ng1', []);
var ng1 = function() {
return {
scope: {},
bindToController: {title: '@'},
template: '{{ctl.title}}',
controllerAs: 'ctl',
controller: Class({constructor: function() {}})
};
};
ng1Module.directive('ng1', ng1);
var Ng2 = Component({
selector: 'ng2',
template: '<ng1 title="WORKS"></ng1>',
directives: [adapter.upgradeNg1Component('ng1')]
}).Class({constructor: function() {}});
ng1Module.directive('ng2', adapter.downgradeNg2Component(Ng2));
var element = html(`<div><ng2></ng2></div>`);
adapter.bootstrap(element, ['ng1'])
.ready((ref) => {
expect(multiTrim(document.body.textContent)).toEqual('WORKS');
ref.dispose();
async.done();
});
}));
it('should support single require in linking fn', inject([AsyncTestCompleter], (async) => {
var adapter = new UpgradeAdapter();
var ng1Module = angular.module('ng1', []);

Some files were not shown because too many files have changed in this diff Show More