diff --git a/.gitignore b/.gitignore
new file mode 100644
index 00000000000..e2a9e85ddf0
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,47 @@
+.DS_STORE
+
+# Don’t commit the following directories created by pub.
+packages
+pubspec.lock
+.pub
+.packages
+
+/dist/
+.buildlog
+node_modules
+bower_components
+
+# Or broccoli working directory
+tmp
+
+# Or the files created by dart2js.
+*.dart.js
+*.dart.precompiled.js
+*.js_
+*.js.deps
+*.js.map
+
+# Or type definitions we mirror from github
+**/typings/**/*.d.ts
+**/typings/tsd.cached.json
+
+# Include when developing application packages.
+pubspec.lock
+.c9
+.idea/
+.settings/
+*.swo
+modules/.settings
+.vscode
+modules/.vscode
+
+# Don't check in secret files
+*secret.js
+
+# Ignore npm debug log
+npm-debug.log
+
+/docs/bower_components/
+
+# build-analytics
+.build-analytics
diff --git a/README.dart.md b/README.dart.md
new file mode 100644
index 00000000000..35cead77114
--- /dev/null
+++ b/README.dart.md
@@ -0,0 +1,6 @@
+Angular2
+=========
+
+The sources for this package are in the main [Angular2](https://github.com/angular/angular) repo. Please file issues and pull requests against that repo. This is the repository for the upcoming 2.0 version. If you're looking for the current official version of Angular you should go to [angular/angular.js](https://github.com/angular/angular.js)
+
+License: Apache MIT 2.0
diff --git a/README.js.md b/README.js.md
new file mode 100644
index 00000000000..24f3f372f3d
--- /dev/null
+++ b/README.js.md
@@ -0,0 +1,15 @@
+Angular2
+=========
+
+The sources for this package are in the main [Angular2](https://github.com/angular/angular) repo. Please file issues and pull requests against that repo. This is the repository for the upcoming 2.0 version. If you're looking for the current official version of Angular you should go to [angular/angular.js](https://github.com/angular/angular.js)
+
+This package contains different sources for different users:
+
+1. The files located in the root folder can be consumed using CommonJS.
+2. The files under `/es6` are es6 compatible files that can be transpiled to
+ es5 using any transpiler. This contains:
+ * `dev/`: a development version that includes runtime type assertions
+ * `prod/`: a production version that does not include runtime type assertions
+3. The files under `/ts` are the TypeScript source files.
+
+License: Apache MIT 2.0
diff --git a/SOURCE_SHA b/SOURCE_SHA
new file mode 100644
index 00000000000..dca55bf7a44
--- /dev/null
+++ b/SOURCE_SHA
@@ -0,0 +1 @@
+f2beef551567fd5d25d634c572938cbfd9207bcb
diff --git a/angular2.js b/angular2.js
new file mode 100644
index 00000000000..7a0ae1e6dd8
--- /dev/null
+++ b/angular2.js
@@ -0,0 +1,10 @@
+function __export(m) {
+ for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p];
+}
+__export(require('./common'));
+__export(require('./core'));
+__export(require('./profile'));
+__export(require('./lifecycle_hooks'));
+__export(require('./bootstrap'));
+__export(require('./upgrade'));
+//# sourceMappingURL=angular2.js.map
\ No newline at end of file
diff --git a/angular2_sfx.js b/angular2_sfx.js
new file mode 100644
index 00000000000..2d238a39d1b
--- /dev/null
+++ b/angular2_sfx.js
@@ -0,0 +1,19 @@
+var ng = require('./angular2');
+// the router and http should have their own SFX bundle
+// But currently the module arithmetic 'angular2/router_sfx - angular2/angular2',
+// is not support by system builder.
+var router = require('./router');
+var http = require('./http');
+var _prevNg = window.ng;
+window.ng = ng;
+window.ngRouter = router;
+window.ngHttp = http;
+/**
+ * Calling noConflict will restore window.angular to its pre-angular loading state
+ * and return the angular module object.
+ */
+ng.noConflict = function () {
+ window.ng = _prevNg;
+ return ng;
+};
+//# sourceMappingURL=angular2_sfx.js.map
\ No newline at end of file
diff --git a/animate.js b/animate.js
new file mode 100644
index 00000000000..759a5e579fd
--- /dev/null
+++ b/animate.js
@@ -0,0 +1,11 @@
+var animation_1 = require('./src/animate/animation');
+exports.Animation = animation_1.Animation;
+var animation_builder_1 = require('./src/animate/animation_builder');
+exports.AnimationBuilder = animation_builder_1.AnimationBuilder;
+var browser_details_1 = require('./src/animate/browser_details');
+exports.BrowserDetails = browser_details_1.BrowserDetails;
+var css_animation_builder_1 = require('./src/animate/css_animation_builder');
+exports.CssAnimationBuilder = css_animation_builder_1.CssAnimationBuilder;
+var css_animation_options_1 = require('./src/animate/css_animation_options');
+exports.CssAnimationOptions = css_animation_options_1.CssAnimationOptions;
+//# sourceMappingURL=animate.js.map
\ No newline at end of file
diff --git a/bootstrap.js b/bootstrap.js
new file mode 100644
index 00000000000..177c5849b63
--- /dev/null
+++ b/bootstrap.js
@@ -0,0 +1,7 @@
+/**
+ * This file is only used for dart applications and for internal examples
+ * that compile with both JavaScript and Dart.
+ */
+var bootstrap_1 = require('angular2/src/core/bootstrap');
+exports.bootstrap = bootstrap_1.bootstrap;
+//# sourceMappingURL=bootstrap.js.map
\ No newline at end of file
diff --git a/common.js b/common.js
new file mode 100644
index 00000000000..b6585083ad4
--- /dev/null
+++ b/common.js
@@ -0,0 +1,8 @@
+function __export(m) {
+ for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p];
+}
+__export(require('./src/common/pipes'));
+__export(require('./src/common/directives'));
+__export(require('./src/common/forms'));
+__export(require('./src/common/common_directives'));
+//# sourceMappingURL=common.js.map
\ No newline at end of file
diff --git a/compiler.js b/compiler.js
new file mode 100644
index 00000000000..eeb789a57ed
--- /dev/null
+++ b/compiler.js
@@ -0,0 +1,11 @@
+function __export(m) {
+ for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p];
+}
+/**
+ * @module
+ * @description
+ * Starting point to import all compiler APIs.
+ */
+__export(require('./src/compiler/url_resolver'));
+__export(require('./src/compiler/xhr'));
+//# sourceMappingURL=compiler.js.map
\ No newline at end of file
diff --git a/core.js b/core.js
new file mode 100644
index 00000000000..1c0458ccd54
--- /dev/null
+++ b/core.js
@@ -0,0 +1,28 @@
+function __export(m) {
+ for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p];
+}
+/**
+ * @module
+ * @description
+ * Starting point to import all public core APIs.
+ */
+__export(require('./src/core/metadata'));
+__export(require('./src/core/util'));
+__export(require('./src/core/di'));
+__export(require('./src/common/pipes'));
+__export(require('./src/facade/facade'));
+__export(require('./src/core/application'));
+__export(require('./src/core/bootstrap'));
+__export(require('./src/core/services'));
+__export(require('./src/core/linker'));
+var application_ref_1 = require('./src/core/application_ref');
+exports.ApplicationRef = application_ref_1.ApplicationRef;
+__export(require('./src/core/zone'));
+__export(require('./src/core/render'));
+__export(require('./src/common/directives'));
+__export(require('./src/common/forms'));
+__export(require('./src/core/debug'));
+__export(require('./src/core/change_detection'));
+__export(require('./src/core/ambient'));
+__export(require('./src/core/dev_mode'));
+//# sourceMappingURL=core.js.map
\ No newline at end of file
diff --git a/docs/change_detection/change_detection.md b/docs/change_detection/change_detection.md
new file mode 100644
index 00000000000..4207687163d
--- /dev/null
+++ b/docs/change_detection/change_detection.md
@@ -0,0 +1,10 @@
+@name Change Detection
+@description
+# Change Detection
+
+* Mechanisms by which changes are detected in the model
+* DAG
+* Order of evaluation
+* Pure Functions
+* `onChange` method
+* Parser
diff --git a/docs/change_detection/expressions.md b/docs/change_detection/expressions.md
new file mode 100644
index 00000000000..e9cdc9aa9bb
--- /dev/null
+++ b/docs/change_detection/expressions.md
@@ -0,0 +1,7 @@
+# Expressions
+
+## Binding Semantics
+
+### Formatters
+
+## Statement Semantics
\ No newline at end of file
diff --git a/docs/change_detection/record.md b/docs/change_detection/record.md
new file mode 100644
index 00000000000..343624acec2
--- /dev/null
+++ b/docs/change_detection/record.md
@@ -0,0 +1,3 @@
+# Record
+
+## RecordRange
\ No newline at end of file
diff --git a/docs/core/00_index.md b/docs/core/00_index.md
new file mode 100644
index 00000000000..95c575cf1b0
--- /dev/null
+++ b/docs/core/00_index.md
@@ -0,0 +1,3 @@
+# Overview
+
+* High level description of all of the components.
\ No newline at end of file
diff --git a/docs/core/01_templates.md b/docs/core/01_templates.md
new file mode 100644
index 00000000000..e152763f43e
--- /dev/null
+++ b/docs/core/01_templates.md
@@ -0,0 +1,610 @@
+# Templates
+
+Templates are markup which is added to HTML to declaratively describe how the application model should be
+projected to DOM as well as which DOM events should invoke which methods on the controller. Templates contain
+syntaxes which are core to Angular and allows for data-binding, event-binding, template-instantiation.
+
+The design of the template syntax has these properties:
+
+
+* All data-binding expressions are easily identifiable. (i.e. there is never an ambiguity whether the value should be
+ interpreted as string literal or as an expression.)
+* All events and their statements are easily identifiable.
+* All places of DOM instantiation are easily identifiable.
+* All places of variable declaration are easily identifiable.
+
+The above properties guarantee that the templates are easy to parse by tools (such as IDEs) and reason about by people.
+At no point is it necessary to understand which directives are active or what their semantics are in order to reason
+about the template runtime characteristics.
+
+
+
+## Summary
+
+Below is a summary of the kinds of syntaxes which Angular templating supports. The syntaxes are explained in more
+detail in the following sections.
+
+
+
+
+
+## Property Binding
+
+Binding application model data to the UI is the most common kind of bindings in an Angular application. The bindings
+are always in the form of `property-name` which is assigned an `expression`. The generic form is:
+
+
+
+
Short form
+
<some-element [some-property]="expression">
+
+
+
Canonical form
+
<some-element bind-some-property="expression">
+
+
+
+
+Where:
+* `some-element` can be any existing DOM element.
+* `some-property` (escaped with `[]` or `bind-`) is the name of the property on `some-element`. In this case the
+ dash-case is converted into camel-case `someProperty`.
+* `expression` is a valid expression (as defined in section below).
+
+Example:
+```
+
+```
+
+In the above example the `title` property of the `div` element will be updated whenever the `user.firstName` changes
+its value.
+
+Key points:
+* The binding is to the element property not the element attribute.
+* To prevent custom element from accidentally reading the literal `expression` on the title element, the attribute name
+ is escaped. In our case the `title` is escaped to `[title]` through the addition of square brackets `[]`.
+* A binding value (in this case `user.firstName`) will always be an expression, never a string literal.
+
+NOTE: Unlike Angular v1, Angular v2 binds to properties of elements rather than attributes of elements. This is
+done to better support custom elements, and to allow binding for values other than strings.
+
+NOTE: Some editors/server side pre-processors may have trouble generating `[]` around the attribute name. For this
+reason Angular also supports a canonical version which is prefixed using `bind-`.
+
+
+
+### String Interpolation
+
+Property bindings are the only data bindings which Angular supports, but for convenience Angular supports an interpolation
+syntax which is just a short hand for the data binding syntax.
+
+```
+Hello {{name}}!
+```
+
+is a short hand for:
+
+```
+
+```
+
+The above says to bind the `'Hello ' + stringify(name) + '!'` expression to the zero-th child of the `span`'s `text`
+property. The index is necessary in case there are more than one text nodes, or if the text node we wish to bind to
+is not the first one.
+
+Similarly the same rules apply to interpolation inside attributes.
+
+```
+
+```
+
+is a short hand for:
+
+```
+
+```
+
+NOTE: `stringify()` is a built in implicit function which converts its argument to a string representation, while
+keeping `null` and `undefined` as empty strings.
+
+
+
+
+## Local Variables
+
+
+
+
+## Inline Templates
+
+Data binding allows updating the DOM's properties, but it does not allow for changing of the DOM structure. To change
+DOM structure we need the ability to define child templates, and then instantiate these templates into Views. The
+Views than can be inserted and removed as needed to change the DOM structure.
+
+
+
+Where:
+* `template` defines a child template and designates the anchor where Views (instances of the template) will be
+ inserted. The template can be defined implicitly with `template` attribute, which turns the current element into
+ a template, or explicitly with `` element. Explicit declaration is longer, but it allows for having
+ templates which have more than one root DOM node.
+* `viewport` is required for templates. The directive is responsible for deciding when
+ and in which order should child views be inserted into this location. Such a directive usually has one or
+ more bindings and can be represented as either `viewport-directive-bindings` or
+ `viewport-directive-microsyntax` on `template` element or attribute. See template microsyntax for more details.
+
+
+Example of conditionally included template:
+
+```
+Hello {{user}}!
+
+ ...administrator menu here...
+
+```
+
+In the above example the `ng-if` directive determines whether the child view (an instance of the child template) should be
+inserted into the root view. The `ng-if` makes this decision based on if the `isAdministrator` binding is true.
+
+The above example is in the short form, for better clarity let's rewrite it in the canonical form, which is functionally
+identical.
+
+```
+Hello {{user}}!
+
+
+ ...administrator menu here...
+
+
+```
+
+
+### Template Microsyntax
+
+Often times it is necessary to encode a lot of different bindings into a template to control how the instantiation
+of the templates occurs. One such example is `ng-for`.
+
+```
+
+
+
+
{{i}}. {{person}}
+
+
+```
+
+Where:
+* `[ng-for]` triggers the for directive.
+* `#person` exports the implicit `ng-for` item.
+* `[ng-for-of]="people"` binds an iterable object to the `ng-for` controller.
+* `#i=index` exports item index as `i`.
+
+The above example is explicit but quite wordy. For this reason in most situations a short hand version of the
+syntax is preferable.
+
+```
+
+
{{i}}. {{person}}
+
+```
+
+Notice how each key value pair is translated to a `key=value;` statement in the `template` attribute. This makes the
+repeat syntax a much shorter, but we can do better. Turns out that most punctuation is optional in the short version
+which allows us to further shorten the text.
+
+```
+
+
{{i}}. {{person}}
+
+```
+
+We can also optionally use `var` instead of `#` and add `:` to `for` which creates the following recommended
+microsyntax for `ng-for`.
+
+```
+
+
{{i}}. {{person}}
+
+```
+
+Finally, we can move the `ng-for` keyword to the left hand side and prefix it with `*` as so:
+
+```
+
+
{{i}}. {{person}}
+
+```
+
+
+The format is intentionally defined freely, so that developers of directives can build an expressive microsyntax for
+their directives. The following code describes a more formal definition.
+
+```
+expression: ... // as defined in Expressions section
+local: [a-zA-Z][a-zA-Z0-9]* // exported variable name available for binding
+internal: [a-zA-Z][a-zA-Z0-9]* // internal variable name which the directive exports.
+key: [a-z][-|_|a-z0-9]]* // key which maps to attribute name
+keyExpression: key[:|=]?expression // binding which maps an expression to a property
+varExport: [#|var]local(=internal)? // binding which exports a local variable from a directive
+microsyntax: ([[key|keyExpression|varExport][;|,]?)*
+```
+
+Where
+* `expression` is an Angular expression as defined in section: Expressions.
+* `local` is a local identifier for local variables.
+* `internal` is an internal variable which the directive exports for binding.
+* `key` is an attribute name usually only used to trigger a specific directive.
+* `keyExpression` is an property name to which the expression will be bound to.
+* `varExport` allows exporting of directive internal state as variables for further binding. If no `internal` name
+ is specified, the exporting is to an implicit variable.
+* `microsyntax` allows you to build a simple microsyntax which can still clearly identify which expressions bind to
+ which properties as well as which variables are exported for binding.
+
+
+NOTE: the `template` attribute must be present to make it clear to the user that a sub-template is being created. This
+goes along with the philosophy that the developer should be able to reason about the template without understanding the
+semantics of the instantiator directive.
+
+
+
+
+## Binding Events
+
+Binding events allows wiring events from DOM (or other components) to the Angular controller.
+
+
+
+
Short form
+
<some-element (some-event)="statement">
+
+
+
Canonical form
+
<some-element on-some-event="statement">
+
+
+
+Where:
+* `some-element` Any element which can generate DOM events (or has an angular directive which generates the event).
+* `some-event` (escaped with `()` or `on-`) is the name of the event `some-event`. In this case the
+ dash-case is converted into camel-case `someEvent`.
+* `statement` is a valid statement (as defined in section below).
+If the execution of the statement returns `false`, then `preventDefault`is applied on the DOM event.
+
+Angular listens to bubbled DOM events (as in the case of clicking on any child), as shown below:
+
+
+
+
Short form
+
<some-element (some-event)="statement">
+
+
+
Canonical form
+
<some-element on-some-event="statement">
+
+
+
+
+Example:
+```
+@Component(...)
+class Example {
+ submit() {
+ // do something when button is clicked
+ }
+}
+
+
+```
+
+In the above example, when clicking on the submit button angular will invoke the `submit` method on the surrounding
+component's controller.
+
+
+NOTE: Unlike Angular v1, Angular v2 treats event bindings as core constructs not as directives. This means that there
+is no need to create an event directive for each kind of event. This makes it possible for Angular v2 to easily
+bind to custom events of Custom Elements, whose event names are not known ahead of time.
+
+
+
+
+## Expressions, Statements and Formatters
+
+Angular templates contain expressions for binding to data and statements for binding to events. Expressions and statements
+have different semantics.
+
+
+### Expressions
+
+Expressions can be used to bind to properties only. Expressions represent how data should be projected to the View.
+Expressions should not have any side effect and should be idempotent. Examples of where expressions can be used in
+Angular are:
+```
+
{{expression}}
+
...
+
...
+
...
+```
+
+Expressions are simplified version of expression in the language in which you are writing your application. (i.e.
+expressions follow JS syntax and semantics in JS and Dart syntax and semantics in Dart). Unlike expressions in the
+language, binding expressions behave differently in following ways:
+
+* *Must be defined*: Unlike Angular v1, Angular v2 will throw an error on dereferencing fields which are not defined.
+ For example: `user.name` will throw an error if `user` is defined but it does not have `name` property. If the `name`
+ property is not known, it must be declared and set to some value such as empty string, `null` (or `undefined` in JS).
+ This is done to allow early detection of errors in the templates.
+* *Safe dereference*: Expressions `user.name` where `user` is null will throw `NullPointerException` in the language.
+ In contrast Angular will silently ignore `null` on `user`. This is done because Views often have to wait for the data
+ to arrive from the backend and many fields will be `null` until the data arrives. Safe dereference is so common in the
+ Views that we have made it the default.
+* *Single expression*: An expression must be a single statement. (i.e. no `;`)
+* *No assignments*: Binding expressions can not contain assignments.
+* *No keywords*: Binding expressions can not contain keywords such as: `var`, `if`, and so on.
+* *Formatters*: Angular expressions can be piped through formatters to further transform the binding value.
+ (See: Formatters)
+
+Examples of some expressions and their behavior:
+
+Given:
+```
+class Greeter {
+ name:string;
+}
+```
+
+* `name` : Will result in the value of the `name` property on the `Greeter` class.
+* `name.length`: Will result in either the length of the `name` string or `undefined` (`null` in Dart) if `name`
+ property is `null` or `undefined`. Example of: safe dereference.
+* `foo`: Will throw an error because `foo` is not declared on the `Greeter` class. Example of: Must be defined
+* `name=1`: Not allowed because of assignment.
+* `name; name.length`: Not allowed because of multiple statements.
+
+
+
+### Statements
+
+Statements can be used to bind to events only. Statements represent actions to trigger as a response to an event.
+Examples of where statements can be used in Angular are:
+```
+
...
+
...
+```
+
+Statements are similar to statements in the language in which you are writing your application. (i.e.
+statements follow JS syntax and semantics in JS and Dart syntax and semantics in Dart). Unlike statements in the
+language, binding expressions behave differently in the following ways:
+
+* *Unsafe dereference*: Expressions `user.verify()` where `user` is `null` will throw `NullPointerException` in the
+ language as well as in statements. (In contrast to Safe dereference in Angular expressions.) While Angular protects
+ you from null dereferencing in expressions due to lazy loading of data, no such protection is required for statements,
+ and doing so would make it harder to detect typos in statements.
+* *Multiple statements OK*: Statements can be composed from more than one statement. (i.e. no `doA(); doB()`)
+* *Assignments OK*: Event bindings can have side effects and hence assignments are allowed.
+* *No keywords*: Statements can not contain keywords such as: `var`, `if`, and so on.
+* *No Formatters*: Angular statements can not contain formatters. (Formatters are only useful for data binding)
+
+## Further Reading
+
+* [Template Syntax Constraints and Reasoning](https://docs.google.com/document/d/1HHy_zPLGqJj0bHMiWPzPCxn1pO5GlOYwmv-qGgl4f_s)
diff --git a/docs/core/02_directives.md b/docs/core/02_directives.md
new file mode 100644
index 00000000000..0b5b1d6b8e6
--- /dev/null
+++ b/docs/core/02_directives.md
@@ -0,0 +1,390 @@
+# Directives
+
+Directives are classes which get instantiated as a response to a particular DOM structure. By controlling the DOM structure, what directives are imported, and their selectors, the developer can use the [composition pattern](http://en.wikipedia.org/wiki/Object_composition) to get a desirable application behavior.
+
+Directives are the cornerstone of an Angular application. We use Directives to break complex problems into smaller more reusable components. Directives allow the developer to turn HTML into a DSL and then control the application assembly process.
+
+Angular applications do not have a main method. Instead they have a root Component. Dependency Injection then assembles the directives into a working Angular application.
+
+Directives with an encapsulated view and an optional injector are called *Components*.
+
+
+## CSS Selectors
+
+Directives are instantiated whenever the CSS selector matches the DOM structure.
+
+Angular supports these CSS selector constructs:
+* Element name: `name`
+* Attribute: `[attribute]`
+* Attribute has value: `[attribute=value]`
+* Attribute contains value: `[attribute*=value]`
+* Class: `.class`
+* AND operation: `name[attribute]`
+* OR operation: `name,.class`
+* NOT operation: `:not(.class)`
+
+Angular does not support these (and any CSS selector which crosses element boundaries):
+* Descendant: `body div`
+* Direct descendant: `body > div`
+* Adjacent: `div + table`
+* Sibling: `div ~ table`
+* Wildcard: `*`
+* ID: `#id`
+* Pseudo selectors: `:pseudo` other than `:not`
+
+
+
+Given this DOM:
+
+``````
+
+These CSS selectors will match:
+* `input`: Triggers whenever element name is `input`.
+* `[required]`: Triggers whenever element contains a required attribute.
+* `[type=text]`: Triggers whenever element contains attribute `type` whose value is `text`.
+* `.primary`: Triggers whenever element class contains `primary`.
+
+CSS Selectors can be combined:
+* `input[type=text]`: Triggers on element name `input` which is of `type` `text`.
+* `input[type=text], textarea`: triggers on element name `input` which is of `type` `text` or element name `textarea`.
+
+
+
+## Directives
+
+The simplest kind of directive is a decorator. Directives are useful for encapsulating behavior.
+
+* Multiple decorators can be placed on a single element.
+* Directives do not introduce new evaluation context.
+* Directives are registered through the `@Directive` meta-data annotation.
+
+Here is a trivial example of a tooltip decorator. The directive will log a tooltip into the console on every time mouse enters a region:
+
+```
+@Directive({
+ selector: '[tooltip]', | CSS Selector which triggers the decorator
+ properties: [ | List which properties need to be bound
+ 'text: tooltip' | - DOM element tooltip property should be
+ ], | mapped to the directive text property.
+ host: { | List which events need to be mapped.
+ '(mouseover)': 'show()' | - Invoke the show() method every time
+ } | the mouseover event is fired.
+}) |
+class Form { | Directive controller class, instantiated
+ | when CSS matches.
+ text:string; | text property on the Directive Controller.
+ |
+ show() { | Show method which implements the show action.
+ console.log(this.text); |
+ }
+}
+```
+
+Example of usage:
+
+```Some text here.```
+
+The developer of an application can now freely use the `tooltip` attribute wherever the behavior is needed. The code above has taught the browser a new reusable and declarative behavior.
+
+Notice that data binding will work with this decorator with no further effort as shown below.
+
+```Some text here.```
+
+
+
+## Components
+
+Component is a directive which uses shadow DOM to create encapsulate visual behavior. Components are typically used to create UI widgets or to break up the application into smaller components.
+
+* Only one component can be present per DOM element.
+* Component's CSS selectors usually trigger on element names. (Best practice)
+* Component has its own shadow view which is attached to the element as a Shadow DOM.
+* Shadow view context is the component instance. (i.e. template expressions are evaluated against the component instance.)
+
+>> TODO(misko): Configuring the injector
+
+Example of a component:
+
+```
+@Component({ | Component annotation
+ selector: 'pane', | CSS selector on element
+ properties: [ | List which property need to be bound
+ 'title', | - title mapped to component title
+ 'open' | - open attribute mapped to component's open property
+ ], |
+}) |
+@View({ | View annotation
+ templateUrl: 'pane.html' | - URL of template HTML
+}) |
+class Pane { | Component controller class
+ title:string; | - title property
+ open:boolean;
+
+ constructor() {
+ this.title = '';
+ this.open = true;
+ }
+
+ // Public API
+ toggle() => this.open = !this.open;
+ open() => this.open = true;
+ close() => this.open = false;
+}
+```
+
+`pane.html`:
+```
+
+
{{title}}
+
+
+
+
+```
+
+`pane.css`:
+```
+.outer, .inner { border: 1px solid blue;}
+.h1 {background-color: blue;}
+```
+
+Example of usage:
+```
+
+ Some text to wrap.
+
+
+
+```
+
+
+
+## Directives that use a ViewContainer
+
+Directives that use a ViewContainer can control instantiation of child views which are then inserted into the DOM. (Examples are `ng-if` and `ng-for`.)
+
+* Every `template` element creates a `ProtoView` which can be used to create Views via the ViewContainer.
+* The child views show up as siblings of the directive in the DOM.
+
+>> TODO(misko): Relationship with Injection
+>> TODO(misko): Instantiator can not be injected into child Views
+
+
+```
+@Directive({
+ selector: '[if]',
+ properties: [
+ 'condition: if'
+ ]
+})
+export class If {
+ viewContainer: ViewContainerRef;
+ protoViewRef: ProtoViewRef;
+ view: View;
+
+ constructor(viewContainer: ViewContainerRef, protoViewRef: ProtoViewRef) {
+ this.viewContainer = viewContainer;
+ this.protoViewRef = protoViewRef;
+ this.view = null;
+ }
+
+ set condition(value) {
+ if (value) {
+ if (this.view === null) {
+ this.view = this.viewContainer.create(protoViewRef);
+ }
+ } else {
+ if (this.view !== null) {
+ this.viewContainer.remove(this.view);
+ this.view = null;
+ }
+ }
+ }
+}
+```
+
+## Dependency Injection
+
+Dependency Injection (DI) is a key aspect of directives. DI allows directives to be assembled into different [compositional](http://en.wikipedia.org/wiki/Object_composition) hierarchies. Angular encourages [composition over inheritance](http://en.wikipedia.org/wiki/Composition_over_inheritance) in the application design (but inheritance based approaches are still supported).
+
+When Angular directives are instantiated, the directive can ask for other related directives to be injected into it. By assembling the directives in different order and subtypes the application behavior can be controlled. A good mental model is that the DOM structure controls the directive instantiation graph.
+
+Directive instantiation is triggered by the directive CSS selector matching the DOM structure. In a directive's constructor, it can ask for other directives or application services. When asking for directives, the dependency is attempted to be located by its DOM hierarchy first, then if not found, by using the application level injector.
+
+To better understand the kinds of injections which are supported in Angular we have broken them down into use case examples.
+
+
+### Injecting Services
+
+Service injection is the most straight forward kind of injection which Angular supports. It involves a component configuring the `bindings` or `viewBindings` and then letting the directive ask for the configured service.
+
+This example illustrates how to inject `MyService` into `House` directive.
+
+
+```
+class MyService {} | Assume a service which needs to be injected
+ | into a directive.
+ |
+@Component({ | Assume a top level application component which
+ selector: 'my-app', | configures the services to be injected.
+ viewBindings: [MyService] |
+}) |
+@View({ | Assume we have a template that needs to be
+ templateUrl: 'my_app.html', | configured with directives to be injected.
+ directives: [House] |
+}) |
+class MyApp {} |
+ |
+@Directive({ | This is the directive into which we would like
+ selector: '[house]' | to inject the MyService.
+}) |
+class House { |
+ constructor(myService:MyService) { | Notice that in the constructor we can simply
+ } | ask for MyService.
+} |
+
+
+```
+
+Assume the following DOM structure for `my_app.html`:
+```
+
| The house attribute triggers the creation of the House directive.
+
| This is equivalent to:
+ | new House(injector.get(MyService));
+```
+
+
+### Injecting other Directives
+
+Injecting other directives into directives follows a similar mechanism as injecting services into directives, but with added constraint of visibility governed by DOM structure.
+
+There are five kinds of visibilities:
+
+* (no annotation): Inject dependent directives only if they are on the current element.
+* `@SkipSelf()`: Inject a directive if it is at any element above the current element.
+* `@child`: Inject a list of direct children which match a given type. (Used with `Query`)
+* `@descendant`: Inject a list of any children which match a given type. (Used with `Query`)
+
+NOTE: if the injection constraint can not be satisfied by the current visibility constraint, then it is forwarded to the normal injector which either provides a default value for the directive or throws an error.
+
+Here is an example of the kinds of injections which can be achieved:
+
+
+```
+@Component({ |
+ selector: 'my-app' |
+}) |
+@View({ |
+ templateUrl: 'my_app.html', |
+ directives: [Form, FieldSet, |
+ Field, Primary] |
+}) |
+class MyApp {} |
+ |
+@Directive({ selector: 'form' }) |
+class Form { |
+ constructor( |
+ @descendant sets:Query
', [])))
+ .toEqual([
+ [template_ast_1.ElementAst, 'div', 'TestComp > div:nth-child(0)'],
+ [template_ast_1.AttrAst, 'ng-non-bindable', '', 'TestComp > div:nth-child(0)[ng-non-bindable=]'],
+ [template_ast_1.TextAst, 'a', 'TestComp > div:nth-child(0) > #text(a):nth-child(1)']
+ ]);
+ });
+ testing_internal_1.it('should ignore a', [])))
+ .toEqual([
+ [template_ast_1.ElementAst, 'div', 'TestComp > div:nth-child(0)'],
+ [template_ast_1.AttrAst, 'ng-non-bindable', '', 'TestComp > div:nth-child(0)[ng-non-bindable=]'],
+ [template_ast_1.TextAst, 'a', 'TestComp > div:nth-child(0) > #text(a):nth-child(1)']
+ ]);
+ });
+ testing_internal_1.it('should ignore elements inside of elements with ng-non-bindable but include them for source info', function () {
+ testing_internal_1.expect(humanizeTemplateAsts(parse('
a
', [])))
+ .toEqual([
+ [template_ast_1.ElementAst, 'div', 'TestComp > div:nth-child(0)'],
+ [template_ast_1.AttrAst, 'ng-non-bindable', '', 'TestComp > div:nth-child(0)[ng-non-bindable=]'],
+ [template_ast_1.TextAst, 'a', 'TestComp > div:nth-child(0) > #text(a):nth-child(1)']
+ ]);
+ });
+ testing_internal_1.it('should convert elements into regular elements inside of elements with ng-non-bindable but include them for source info', function () {
+ testing_internal_1.expect(humanizeTemplateAsts(parse('
"
+ }))
+ .createAsync(MyComp)
+ .then(function (fixture) {
+ testing_internal_1.expect(dom_adapter_1.DOM.querySelectorAll(fixture.debugElement.nativeElement, 'script').length)
+ .toEqual(0);
+ async.done();
+ });
+ }));
+ });
+ testing_internal_1.describe("error handling", function () {
+ testing_internal_1.it('should report a meaningful error when a directive is missing annotation', testing_internal_1.inject([testing_internal_1.TestComponentBuilder, testing_internal_1.AsyncTestCompleter], function (tcb, async) {
+ tcb = tcb.overrideView(MyComp, new metadata_1.ViewMetadata({ template: '', directives: [SomeDirectiveMissingAnnotation] }));
+ async_1.PromiseWrapper.catchError(tcb.createAsync(MyComp), function (e) {
+ testing_internal_1.expect(e.message).toEqual("No Directive annotation found on " + lang_1.stringify(SomeDirectiveMissingAnnotation));
+ async.done();
+ return null;
+ });
+ }));
+ testing_internal_1.it('should report a meaningful error when a component is missing view annotation', testing_internal_1.inject([testing_internal_1.TestComponentBuilder], function (tcb) {
+ try {
+ tcb.createAsync(ComponentWithoutView);
+ }
+ catch (e) {
+ testing_internal_1.expect(e.message)
+ .toContain("must have either 'template', 'templateUrl', or '@View' set.");
+ return null;
+ }
+ }));
+ testing_internal_1.it('should report a meaningful error when a directive is null', testing_internal_1.inject([testing_internal_1.TestComponentBuilder, testing_internal_1.AsyncTestCompleter], function (tcb, async) {
+ tcb = tcb.overrideView(MyComp, new metadata_1.ViewMetadata({ directives: [[null]], template: '' }));
+ async_1.PromiseWrapper.catchError(tcb.createAsync(MyComp), function (e) {
+ testing_internal_1.expect(e.message).toEqual("Unexpected directive value 'null' on the View of component '" + lang_1.stringify(MyComp) + "'");
+ async.done();
+ return null;
+ });
+ }));
+ testing_internal_1.it('should provide an error context when an error happens in DI', testing_internal_1.inject([testing_internal_1.TestComponentBuilder, testing_internal_1.AsyncTestCompleter], function (tcb, async) {
+ tcb =
+ tcb.overrideView(MyComp, new metadata_1.ViewMetadata({
+ directives: [DirectiveThrowingAnError],
+ template: ""
+ }));
+ async_1.PromiseWrapper.catchError(tcb.createAsync(MyComp), function (e) {
+ var c = e.context;
+ testing_internal_1.expect(dom_adapter_1.DOM.nodeName(c.element).toUpperCase()).toEqual("DIRECTIVE-THROWING-ERROR");
+ testing_internal_1.expect(dom_adapter_1.DOM.nodeName(c.componentElement).toUpperCase()).toEqual("DIV");
+ testing_internal_1.expect(c.injector).toBeAnInstanceOf(core_1.Injector);
+ async.done();
+ return null;
+ });
+ }));
+ testing_internal_1.it('should provide an error context when an error happens in change detection', testing_internal_1.inject([testing_internal_1.TestComponentBuilder, testing_internal_1.AsyncTestCompleter], function (tcb, async) {
+ tcb = tcb.overrideView(MyComp, new metadata_1.ViewMetadata({ template: "" }));
+ tcb.createAsync(MyComp).then(function (fixture) {
+ try {
+ fixture.detectChanges();
+ throw "Should throw";
+ }
+ catch (e) {
+ var c = e.context;
+ testing_internal_1.expect(dom_adapter_1.DOM.nodeName(c.element).toUpperCase()).toEqual("INPUT");
+ testing_internal_1.expect(dom_adapter_1.DOM.nodeName(c.componentElement).toUpperCase()).toEqual("DIV");
+ testing_internal_1.expect(c.injector).toBeAnInstanceOf(core_1.Injector);
+ testing_internal_1.expect(c.expression).toContain("one.two.three");
+ testing_internal_1.expect(c.context).toBe(fixture.debugElement.componentInstance);
+ testing_internal_1.expect(c.locals["local"]).toBeDefined();
+ }
+ async.done();
+ });
+ }));
+ testing_internal_1.it('should provide an error context when an error happens in change detection (text node)', testing_internal_1.inject([testing_internal_1.TestComponentBuilder, testing_internal_1.AsyncTestCompleter], function (tcb, async) {
+ tcb = tcb.overrideView(MyComp, new metadata_1.ViewMetadata({ template: "{{one.two.three}}" }));
+ tcb.createAsync(MyComp).then(function (fixture) {
+ try {
+ fixture.detectChanges();
+ throw "Should throw";
+ }
+ catch (e) {
+ var c = e.context;
+ testing_internal_1.expect(c.element).toBeNull();
+ testing_internal_1.expect(c.injector).toBeNull();
+ }
+ async.done();
+ });
+ }));
+ if (dom_adapter_1.DOM.supportsDOMEvents()) {
+ testing_internal_1.it('should provide an error context when an error happens in an event handler', testing_internal_1.inject([testing_internal_1.TestComponentBuilder], testing_internal_1.fakeAsync(function (tcb) {
+ tcb = tcb.overrideView(MyComp, new metadata_1.ViewMetadata({
+ template: "",
+ directives: [DirectiveEmitingEvent, DirectiveListeningEvent]
+ }));
+ var fixture;
+ tcb.createAsync(MyComp).then(function (root) { fixture = root; });
+ testing_internal_1.tick();
+ var tc = fixture.debugElement.componentViewChildren[0];
+ tc.inject(DirectiveEmitingEvent).fireEvent("boom");
+ try {
+ testing_internal_1.tick();
+ throw "Should throw";
+ }
+ catch (e) {
+ testing_internal_1.clearPendingTimers();
+ var c = e.context;
+ testing_internal_1.expect(dom_adapter_1.DOM.nodeName(c.element).toUpperCase()).toEqual("SPAN");
+ testing_internal_1.expect(dom_adapter_1.DOM.nodeName(c.componentElement).toUpperCase()).toEqual("DIV");
+ testing_internal_1.expect(c.injector).toBeAnInstanceOf(core_1.Injector);
+ testing_internal_1.expect(c.context).toBe(fixture.debugElement.componentInstance);
+ testing_internal_1.expect(c.locals["local"]).toBeDefined();
+ }
+ })));
+ }
+ if (!lang_2.IS_DART) {
+ testing_internal_1.it('should report a meaningful error when a directive is undefined', testing_internal_1.inject([testing_internal_1.TestComponentBuilder, testing_internal_1.AsyncTestCompleter], function (tcb, async) {
+ var undefinedValue;
+ tcb = tcb.overrideView(MyComp, new metadata_1.ViewMetadata({ directives: [undefinedValue], template: '' }));
+ async_1.PromiseWrapper.catchError(tcb.createAsync(MyComp), function (e) {
+ testing_internal_1.expect(e.message).toEqual("Unexpected directive value 'undefined' on the View of component '" + lang_1.stringify(MyComp) + "'");
+ async.done();
+ return null;
+ });
+ }));
+ }
+ testing_internal_1.it('should specify a location of an error that happened during change detection (text)', testing_internal_1.inject([testing_internal_1.TestComponentBuilder, testing_internal_1.AsyncTestCompleter], function (tcb, async) {
+ tcb.overrideView(MyComp, new metadata_1.ViewMetadata({ template: '{{a.b}}' }))
+ .createAsync(MyComp)
+ .then(function (fixture) {
+ testing_internal_1.expect(function () { return fixture.detectChanges(); })
+ .toThrowError(testing_internal_1.containsRegexp("{{a.b}} in " + lang_1.stringify(MyComp)));
+ async.done();
+ });
+ }));
+ testing_internal_1.it('should specify a location of an error that happened during change detection (element property)', testing_internal_1.inject([testing_internal_1.TestComponentBuilder, testing_internal_1.AsyncTestCompleter], function (tcb, async) {
+ tcb.overrideView(MyComp, new metadata_1.ViewMetadata({ template: '' }))
+ .createAsync(MyComp)
+ .then(function (fixture) {
+ testing_internal_1.expect(function () { return fixture.detectChanges(); })
+ .toThrowError(testing_internal_1.containsRegexp("a.b in " + lang_1.stringify(MyComp)));
+ async.done();
+ });
+ }));
+ testing_internal_1.it('should specify a location of an error that happened during change detection (directive property)', testing_internal_1.inject([testing_internal_1.TestComponentBuilder, testing_internal_1.AsyncTestCompleter], function (tcb, async) {
+ tcb.overrideView(MyComp, new metadata_1.ViewMetadata({
+ template: '',
+ directives: [ChildComp]
+ }))
+ .createAsync(MyComp)
+ .then(function (fixture) {
+ testing_internal_1.expect(function () { return fixture.detectChanges(); })
+ .toThrowError(testing_internal_1.containsRegexp("a.b in " + lang_1.stringify(MyComp)));
+ async.done();
+ });
+ }));
+ });
+ testing_internal_1.it('should support imperative views', testing_internal_1.inject([testing_internal_1.TestComponentBuilder, testing_internal_1.AsyncTestCompleter], function (tcb, async) {
+ tcb.overrideView(MyComp, new metadata_1.ViewMetadata({
+ template: '',
+ directives: [SimpleImperativeViewComponent]
+ }))
+ .createAsync(MyComp)
+ .then(function (fixture) {
+ testing_internal_1.expect(fixture.debugElement.nativeElement).toHaveText('hello imp view');
+ async.done();
+ });
+ }));
+ testing_internal_1.it('should support moving embedded views around', testing_internal_1.inject([testing_internal_1.TestComponentBuilder, testing_internal_1.AsyncTestCompleter, ANCHOR_ELEMENT], function (tcb, async, anchorElement) {
+ tcb.overrideView(MyComp, new metadata_1.ViewMetadata({
+ template: '
hello
',
+ directives: [SomeImperativeViewport]
+ }))
+ .createAsync(MyComp)
+ .then(function (fixture) {
+ fixture.detectChanges();
+ testing_internal_1.expect(anchorElement).toHaveText('');
+ fixture.debugElement.componentInstance.ctxBoolProp = true;
+ fixture.detectChanges();
+ testing_internal_1.expect(anchorElement).toHaveText('hello');
+ fixture.debugElement.componentInstance.ctxBoolProp = false;
+ fixture.detectChanges();
+ testing_internal_1.expect(fixture.debugElement.nativeElement).toHaveText('');
+ async.done();
+ });
+ }));
+ testing_internal_1.describe('Property bindings', function () {
+ if (!lang_2.IS_DART) {
+ testing_internal_1.it('should throw on bindings to unknown properties', testing_internal_1.inject([testing_internal_1.TestComponentBuilder, testing_internal_1.AsyncTestCompleter], function (tcb, async) {
+ tcb =
+ tcb.overrideView(MyComp, new metadata_1.ViewMetadata({ template: '' }));
+ async_1.PromiseWrapper.catchError(tcb.createAsync(MyComp), function (e) {
+ testing_internal_1.expect(e.message).toEqual("Template parse errors:\nCan't bind to 'unknown' since it isn't a known native property in MyComp > div:nth-child(0)[unknown={{ctxProp}}]");
+ async.done();
+ return null;
+ });
+ }));
+ testing_internal_1.it('should not throw for property binding to a non-existing property when there is a matching directive property', testing_internal_1.inject([testing_internal_1.TestComponentBuilder, testing_internal_1.AsyncTestCompleter], function (tcb, async) {
+ tcb.overrideView(MyComp, new metadata_1.ViewMetadata({ template: '', directives: [MyDir] }))
+ .createAsync(MyComp)
+ .then(function (val) { async.done(); });
+ }));
+ }
+ testing_internal_1.it('should not be created when there is a directive with the same property', testing_internal_1.inject([testing_internal_1.TestComponentBuilder, testing_internal_1.AsyncTestCompleter], function (tcb, async) {
+ tcb.overrideView(MyComp, new metadata_1.ViewMetadata({
+ template: '',
+ directives: [DirectiveWithTitle]
+ }))
+ .createAsync(MyComp)
+ .then(function (fixture) {
+ fixture.debugElement.componentInstance.ctxProp = "TITLE";
+ fixture.detectChanges();
+ var el = dom_adapter_1.DOM.querySelector(fixture.debugElement.nativeElement, "span");
+ testing_internal_1.expect(lang_1.isBlank(el.title) || el.title == '').toBeTruthy();
+ async.done();
+ });
+ }));
+ testing_internal_1.it('should work when a directive uses hostProperty to update the DOM element', testing_internal_1.inject([testing_internal_1.TestComponentBuilder, testing_internal_1.AsyncTestCompleter], function (tcb, async) {
+ tcb.overrideView(MyComp, new metadata_1.ViewMetadata({
+ template: '',
+ directives: [DirectiveWithTitleAndHostProperty]
+ }))
+ .createAsync(MyComp)
+ .then(function (fixture) {
+ fixture.debugElement.componentInstance.ctxProp = "TITLE";
+ fixture.detectChanges();
+ var el = dom_adapter_1.DOM.querySelector(fixture.debugElement.nativeElement, "span");
+ testing_internal_1.expect(el.title).toEqual("TITLE");
+ async.done();
+ });
+ }));
+ });
+ testing_internal_1.describe('logging property updates', function () {
+ testing_internal_1.beforeEachBindings(function () { return [
+ core_1.provide(change_detection_1.ChangeDetectorGenConfig, { useValue: new change_detection_1.ChangeDetectorGenConfig(true, true, false) })
+ ]; });
+ testing_internal_1.it('should reflect property values as attributes', testing_internal_1.inject([testing_internal_1.TestComponentBuilder, testing_internal_1.AsyncTestCompleter], function (tcb, async) {
+ var tpl = '
' +
+ '' +
+ '
';
+ tcb.overrideView(MyComp, new metadata_1.ViewMetadata({ template: tpl, directives: [MyDir] }))
+ .createAsync(MyComp)
+ .then(function (fixture) {
+ fixture.debugElement.componentInstance.ctxProp = 'hello';
+ fixture.detectChanges();
+ testing_internal_1.expect(dom_adapter_1.DOM.getInnerHTML(fixture.debugElement.nativeElement))
+ .toContain('ng-reflect-dir-prop="hello"');
+ async.done();
+ });
+ }));
+ });
+ testing_internal_1.describe('different proto view storages', function () {
+ function runWithMode(mode) {
+ return testing_internal_1.inject([testing_internal_1.TestComponentBuilder, testing_internal_1.AsyncTestCompleter], function (tcb, async) {
+ tcb.overrideView(MyComp, new metadata_1.ViewMetadata({ template: "
{{ctxProp}}
" }))
+ .createAsync(MyComp)
+ .then(function (fixture) {
+ fixture.debugElement.componentInstance.ctxProp = 'Hello World!';
+ fixture.detectChanges();
+ testing_internal_1.expect(fixture.debugElement.nativeElement).toHaveText('Hello World!');
+ async.done();
+ });
+ });
+ }
+ testing_internal_1.it('should work with storing DOM nodes', runWithMode('cache'));
+ testing_internal_1.it('should work with serializing the DOM nodes', runWithMode('nocache'));
+ });
+ // Disabled until a solution is found, refs:
+ // - https://github.com/angular/angular/issues/776
+ // - https://github.com/angular/angular/commit/81f3f32
+ testing_internal_1.xdescribe('Missing directive checks', function () {
+ function expectCompileError(tcb, inlineTpl, errMessage, done) {
+ tcb = tcb.overrideView(MyComp, new metadata_1.ViewMetadata({ template: inlineTpl }));
+ async_1.PromiseWrapper.then(tcb.createAsync(MyComp), function (value) {
+ throw new exceptions_1.BaseException("Test failure: should not have come here as an exception was expected");
+ }, function (err) {
+ testing_internal_1.expect(err.message).toEqual(errMessage);
+ done();
+ });
+ }
+ if (lang_1.assertionsEnabled()) {
+ testing_internal_1.it('should raise an error if no directive is registered for a template with template bindings', testing_internal_1.inject([testing_internal_1.TestComponentBuilder, testing_internal_1.AsyncTestCompleter], function (tcb, async) {
+ expectCompileError(tcb, '
', 'Missing directive to handle \'if\' in
', function () { return async.done(); });
+ }));
+ testing_internal_1.it('should raise an error for missing template directive (1)', testing_internal_1.inject([testing_internal_1.TestComponentBuilder, testing_internal_1.AsyncTestCompleter], function (tcb, async) {
+ expectCompileError(tcb, '', 'Missing directive to handle: ', function () { return async.done(); });
+ }));
+ testing_internal_1.it('should raise an error for missing template directive (2)', testing_internal_1.inject([testing_internal_1.TestComponentBuilder, testing_internal_1.AsyncTestCompleter], function (tcb, async) {
+ expectCompileError(tcb, '', 'Missing directive to handle: ', function () { return async.done(); });
+ }));
+ testing_internal_1.it('should raise an error for missing template directive (3)', testing_internal_1.inject([testing_internal_1.TestComponentBuilder, testing_internal_1.AsyncTestCompleter], function (tcb, async) {
+ expectCompileError(tcb, '', 'Missing directive to handle \'if\' in MyComp:
' +
+ '',
+ directives: [Simple]
+ }))
+ .createAsync(MainComp)
+ .then(function (main) {
+ testing_internal_1.expect(main.debugElement.nativeElement).toHaveText('SIMPLE(A)');
+ async.done();
+ });
+ }));
+ testing_internal_1.it('should support simple components with text interpolation as direct children', testing_internal_1.inject([testing_internal_1.TestComponentBuilder, testing_internal_1.AsyncTestCompleter], function (tcb, async) {
+ tcb.overrideView(MainComp, new core_1.ViewMetadata({
+ template: '{{\'START(\'}}' +
+ '{{text}}' +
+ '{{\')END\'}}',
+ directives: [Simple]
+ }))
+ .createAsync(MainComp)
+ .then(function (main) {
+ main.debugElement.componentInstance.text = 'A';
+ main.detectChanges();
+ testing_internal_1.expect(main.debugElement.nativeElement).toHaveText('START(SIMPLE(A))END');
+ async.done();
+ });
+ }));
+ testing_internal_1.it('should support projecting text interpolation to a non bound element', testing_internal_1.inject([testing_internal_1.TestComponentBuilder, testing_internal_1.AsyncTestCompleter], function (tcb, async) {
+ tcb.overrideView(Simple, new core_1.ViewMetadata({ template: 'SIMPLE(
)', directives: [] }))
+ .overrideView(MainComp, new core_1.ViewMetadata({ template: '{{text}}', directives: [Simple] }))
+ .createAsync(MainComp)
+ .then(function (main) {
+ main.debugElement.componentInstance.text = 'A';
+ main.detectChanges();
+ testing_internal_1.expect(main.debugElement.nativeElement).toHaveText('SIMPLE(A)');
+ async.done();
+ });
+ }));
+ testing_internal_1.it('should support projecting text interpolation to a non bound element with other bound elements after it', testing_internal_1.inject([testing_internal_1.TestComponentBuilder, testing_internal_1.AsyncTestCompleter], function (tcb, async) {
+ tcb.overrideView(Simple, new core_1.ViewMetadata({
+ template: 'SIMPLE(
EL
)',
+ directives: []
+ }))
+ .overrideView(MainComp, new core_1.ViewMetadata({ template: '{{text}}', directives: [Simple] }))
+ .createAsync(MainComp)
+ .then(function (main) {
+ main.debugElement.componentInstance.text = 'A';
+ main.detectChanges();
+ testing_internal_1.expect(main.debugElement.nativeElement).toHaveText('SIMPLE(AEL)');
+ async.done();
+ });
+ }));
+ testing_internal_1.it('should project content components', testing_internal_1.inject([testing_internal_1.TestComponentBuilder, testing_internal_1.AsyncTestCompleter], function (tcb, async) {
+ tcb.overrideView(Simple, new core_1.ViewMetadata({ template: 'SIMPLE({{0}}||{{2}})', directives: [] }))
+ .overrideView(OtherComp, new core_1.ViewMetadata({ template: '{{1}}', directives: [] }))
+ .overrideView(MainComp, new core_1.ViewMetadata({
+ template: '',
+ directives: [Simple, OtherComp]
+ }))
+ .createAsync(MainComp)
+ .then(function (main) {
+ main.detectChanges();
+ testing_internal_1.expect(main.debugElement.nativeElement).toHaveText('SIMPLE(0|1|2)');
+ async.done();
+ });
+ }));
+ testing_internal_1.it('should not show the light dom even if there is no content tag', testing_internal_1.inject([testing_internal_1.TestComponentBuilder, testing_internal_1.AsyncTestCompleter], function (tcb, async) {
+ tcb.overrideView(MainComp, new core_1.ViewMetadata({ template: 'A', directives: [Empty] }))
+ .createAsync(MainComp)
+ .then(function (main) {
+ testing_internal_1.expect(main.debugElement.nativeElement).toHaveText('');
+ async.done();
+ });
+ }));
+ testing_internal_1.it('should support multiple content tags', testing_internal_1.inject([testing_internal_1.TestComponentBuilder, testing_internal_1.AsyncTestCompleter], function (tcb, async) {
+ tcb.overrideView(MainComp, new core_1.ViewMetadata({
+ template: '' +
+ '
' +
+ '',
+ directives: [OuterWithIndirectNestedComponent]
+ }))
+ .createAsync(MainComp)
+ .then(function (main) {
+ testing_internal_1.expect(main.debugElement.nativeElement).toHaveText('OUTER(SIMPLE(AB))');
+ async.done();
+ });
+ }));
+ testing_internal_1.it("should support nesting with content being direct child of a nested component", testing_internal_1.inject([testing_internal_1.TestComponentBuilder, testing_internal_1.AsyncTestCompleter], function (tcb, async) {
+ tcb.overrideView(MainComp, new core_1.ViewMetadata({
+ template: '' +
+ '
A
' +
+ '
B
' +
+ '
C
' +
+ '',
+ directives: [OuterComponent, ManualViewportDirective],
+ }))
+ .createAsync(MainComp)
+ .then(function (main) {
+ var viewportDirective = main.debugElement.query(debug_1.By.directive(ManualViewportDirective))
+ .inject(ManualViewportDirective);
+ testing_internal_1.expect(main.debugElement.nativeElement).toHaveText('OUTER(INNER(INNERINNER(,BC)))');
+ viewportDirective.show();
+ testing_internal_1.expect(main.debugElement.nativeElement).toHaveText('OUTER(INNER(INNERINNER(A,BC)))');
+ async.done();
+ });
+ }));
+ testing_internal_1.it('should redistribute when the shadow dom changes', testing_internal_1.inject([testing_internal_1.TestComponentBuilder, testing_internal_1.AsyncTestCompleter], function (tcb, async) {
+ tcb.overrideView(MainComp, new core_1.ViewMetadata({
+ template: '' +
+ '
A
' +
+ '
B
' +
+ '
C
' +
+ '',
+ directives: [ConditionalContentComponent]
+ }))
+ .createAsync(MainComp)
+ .then(function (main) {
+ var viewportDirective = main.debugElement.query(debug_1.By.directive(ManualViewportDirective))
+ .inject(ManualViewportDirective);
+ testing_internal_1.expect(main.debugElement.nativeElement).toHaveText('(, BC)');
+ viewportDirective.show();
+ testing_internal_1.expect(main.debugElement.nativeElement).toHaveText('(A, BC)');
+ viewportDirective.hide();
+ testing_internal_1.expect(main.debugElement.nativeElement).toHaveText('(, BC)');
+ async.done();
+ });
+ }));
+ // GH-2095 - https://github.com/angular/angular/issues/2095
+ // important as we are removing the ng-content element during compilation,
+ // which could skrew up text node indices.
+ testing_internal_1.it('should support text nodes after content tags', testing_internal_1.inject([testing_internal_1.TestComponentBuilder, testing_internal_1.AsyncTestCompleter], function (tcb, async) {
+ tcb.overrideView(MainComp, new core_1.ViewMetadata({ template: '', directives: [Simple] }))
+ .overrideTemplate(Simple, '
P,
{{stringProp}}')
+ .createAsync(MainComp)
+ .then(function (main) {
+ main.detectChanges();
+ testing_internal_1.expect(main.debugElement.nativeElement).toHaveText('P,text');
+ async.done();
+ });
+ }));
+ // important as we are moving style tags around during compilation,
+ // which could skrew up text node indices.
+ testing_internal_1.it('should support text nodes after style tags', testing_internal_1.inject([testing_internal_1.TestComponentBuilder, testing_internal_1.AsyncTestCompleter], function (tcb, async) {
+ tcb.overrideView(MainComp, new core_1.ViewMetadata({ template: '', directives: [Simple] }))
+ .overrideTemplate(Simple, '
P,
{{stringProp}}')
+ .createAsync(MainComp)
+ .then(function (main) {
+ main.detectChanges();
+ testing_internal_1.expect(main.debugElement.nativeElement).toHaveText('P,text');
+ async.done();
+ });
+ }));
+ testing_internal_1.it('should support moving non projected light dom around', testing_internal_1.inject([testing_internal_1.TestComponentBuilder, testing_internal_1.AsyncTestCompleter], function (tcb, async) {
+ tcb.overrideView(MainComp, new core_1.ViewMetadata({
+ template: '' +
+ '
'
+ }),
+ core_1.Injectable(),
+ __param(0, core_1.ViewQuery(TextDirective)),
+ __metadata('design:paramtypes', [core_1.QueryList])
+ ], NeedsViewQueryOrderWithParent);
+ return NeedsViewQueryOrderWithParent;
+})();
+var NeedsTpl = (function () {
+ function NeedsTpl(viewQuery, query) {
+ this.viewQuery = viewQuery;
+ this.query = query;
+ }
+ NeedsTpl = __decorate([
+ core_1.Component({ selector: 'needs-tpl' }),
+ core_1.View({ template: '' }),
+ __param(0, core_1.ViewQuery(core_1.TemplateRef)),
+ __param(1, core_1.Query(core_1.TemplateRef)),
+ __metadata('design:paramtypes', [core_1.QueryList, core_1.QueryList])
+ ], NeedsTpl);
+ return NeedsTpl;
+})();
+var MyComp = (function () {
+ function MyComp() {
+ this.shouldShow = false;
+ this.list = ['1d', '2d', '3d'];
+ }
+ MyComp = __decorate([
+ core_1.Component({ selector: 'my-comp' }),
+ core_1.View({
+ directives: [
+ NeedsQuery,
+ NeedsQueryDesc,
+ NeedsQueryByLabel,
+ NeedsQueryByTwoLabels,
+ NeedsQueryAndProject,
+ NeedsViewQuery,
+ NeedsViewQueryIf,
+ NeedsViewQueryNestedIf,
+ NeedsViewQueryOrder,
+ NeedsViewQueryByLabel,
+ NeedsViewQueryOrderWithParent,
+ NeedsContentChildren,
+ NeedsViewChildren,
+ NeedsViewChild,
+ NeedsContentChild,
+ NeedsTpl,
+ TextDirective,
+ InertDirective,
+ core_1.NgIf,
+ core_1.NgFor,
+ NeedsFourQueries
+ ]
+ }),
+ core_1.Injectable(),
+ __metadata('design:paramtypes', [])
+ ], MyComp);
+ return MyComp;
+})();
+//# sourceMappingURL=query_integration_spec.js.map
\ No newline at end of file
diff --git a/test/core/linker/query_list_spec.js b/test/core/linker/query_list_spec.js
new file mode 100644
index 00000000000..d5ed2646bba
--- /dev/null
+++ b/test/core/linker/query_list_spec.js
@@ -0,0 +1,84 @@
+var testing_internal_1 = require('angular2/testing_internal');
+var collection_1 = require('angular2/src/facade/collection');
+var lang_1 = require('angular2/src/facade/lang');
+var async_1 = require('angular2/src/facade/async');
+var query_list_1 = require('angular2/src/core/linker/query_list');
+var dom_adapter_1 = require('angular2/src/core/dom/dom_adapter');
+function main() {
+ testing_internal_1.describe('QueryList', function () {
+ var queryList;
+ var log;
+ testing_internal_1.beforeEach(function () {
+ queryList = new query_list_1.QueryList();
+ log = '';
+ });
+ function logAppend(item) { log += (log.length == 0 ? '' : ', ') + item; }
+ testing_internal_1.it('should support resetting and iterating over the new objects', function () {
+ queryList.reset(['one']);
+ queryList.reset(['two']);
+ collection_1.iterateListLike(queryList, logAppend);
+ testing_internal_1.expect(log).toEqual('two');
+ });
+ testing_internal_1.it('should support length', function () {
+ queryList.reset(['one', 'two']);
+ testing_internal_1.expect(queryList.length).toEqual(2);
+ });
+ testing_internal_1.it('should support map', function () {
+ queryList.reset(['one', 'two']);
+ testing_internal_1.expect(queryList.map(function (x) { return x; })).toEqual(['one', 'two']);
+ });
+ if (!lang_1.IS_DART) {
+ testing_internal_1.it('should support filter', function () {
+ queryList.reset(['one', 'two']);
+ testing_internal_1.expect(queryList.filter(function (x) { return x == "one"; })).toEqual(['one']);
+ });
+ testing_internal_1.it('should support reduce', function () {
+ queryList.reset(["one", "two"]);
+ testing_internal_1.expect(queryList.reduce(function (a, x) { return a + x; }, "start:")).toEqual("start:onetwo");
+ });
+ testing_internal_1.it('should support toArray', function () {
+ queryList.reset(["one", "two"]);
+ testing_internal_1.expect(queryList.reduce(function (a, x) { return a + x; }, "start:")).toEqual("start:onetwo");
+ });
+ testing_internal_1.it('should support toArray', function () {
+ queryList.reset(["one", "two"]);
+ testing_internal_1.expect(queryList.toArray()).toEqual(["one", "two"]);
+ });
+ }
+ testing_internal_1.it('should support toString', function () {
+ queryList.reset(['one', 'two']);
+ var listString = queryList.toString();
+ testing_internal_1.expect(lang_1.StringWrapper.contains(listString, 'one')).toBeTruthy();
+ testing_internal_1.expect(lang_1.StringWrapper.contains(listString, 'two')).toBeTruthy();
+ });
+ testing_internal_1.it('should support first and last', function () {
+ queryList.reset(['one', 'two', 'three']);
+ testing_internal_1.expect(queryList.first).toEqual('one');
+ testing_internal_1.expect(queryList.last).toEqual('three');
+ });
+ if (dom_adapter_1.DOM.supportsDOMEvents()) {
+ testing_internal_1.describe('simple observable interface', function () {
+ testing_internal_1.it('should fire callbacks on change', testing_internal_1.fakeAsync(function () {
+ var fires = 0;
+ async_1.ObservableWrapper.subscribe(queryList.changes, function (_) { fires += 1; });
+ queryList.notifyOnChanges();
+ testing_internal_1.tick();
+ testing_internal_1.expect(fires).toEqual(1);
+ queryList.notifyOnChanges();
+ testing_internal_1.tick();
+ testing_internal_1.expect(fires).toEqual(2);
+ }));
+ testing_internal_1.it('should provides query list as an argument', testing_internal_1.fakeAsync(function () {
+ var recorded;
+ async_1.ObservableWrapper.subscribe(queryList.changes, function (v) { recorded = v; });
+ queryList.reset(["one"]);
+ queryList.notifyOnChanges();
+ testing_internal_1.tick();
+ testing_internal_1.expect(recorded).toBe(queryList);
+ }));
+ });
+ }
+ });
+}
+exports.main = main;
+//# sourceMappingURL=query_list_spec.js.map
\ No newline at end of file
diff --git a/test/core/linker/view_container_ref_spec.js b/test/core/linker/view_container_ref_spec.js
new file mode 100644
index 00000000000..7187e59b14f
--- /dev/null
+++ b/test/core/linker/view_container_ref_spec.js
@@ -0,0 +1,37 @@
+var testing_internal_1 = require('angular2/testing_internal');
+var spies_1 = require('../spies');
+var view_1 = require('angular2/src/core/linker/view');
+var view_container_ref_1 = require('angular2/src/core/linker/view_container_ref');
+var element_ref_1 = require('angular2/src/core/linker/element_ref');
+var view_ref_1 = require('angular2/src/core/linker/view_ref');
+function main() {
+ // TODO(tbosch): add missing tests
+ testing_internal_1.describe('ViewContainerRef', function () {
+ var location;
+ var view;
+ var viewManager;
+ function createViewContainer() { return new view_container_ref_1.ViewContainerRef_(viewManager, location); }
+ testing_internal_1.beforeEach(function () {
+ viewManager = new spies_1.SpyAppViewManager();
+ view = new spies_1.SpyView();
+ view.prop("viewContainers", [null]);
+ location = new element_ref_1.ElementRef_(new view_ref_1.ViewRef_(view), 0, null);
+ });
+ testing_internal_1.describe('length', function () {
+ testing_internal_1.it('should return a 0 length if there is no underlying AppViewContainer', function () {
+ var vc = createViewContainer();
+ testing_internal_1.expect(vc.length).toBe(0);
+ });
+ testing_internal_1.it('should return the size of the underlying AppViewContainer', function () {
+ var vc = createViewContainer();
+ var appVc = new view_1.AppViewContainer();
+ view.prop("viewContainers", [appVc]);
+ appVc.views = [new spies_1.SpyView()];
+ testing_internal_1.expect(vc.length).toBe(1);
+ });
+ });
+ // TODO: add missing tests here!
+ });
+}
+exports.main = main;
+//# sourceMappingURL=view_container_ref_spec.js.map
\ No newline at end of file
diff --git a/test/core/linker/view_manager_spec.js b/test/core/linker/view_manager_spec.js
new file mode 100644
index 00000000000..33033eee841
--- /dev/null
+++ b/test/core/linker/view_manager_spec.js
@@ -0,0 +1,388 @@
+var testing_internal_1 = require('angular2/testing_internal');
+var spies_1 = require('../spies');
+var core_1 = require('angular2/core');
+var view_ref_1 = require('angular2/src/core/linker/view_ref');
+var template_ref_1 = require('angular2/src/core/linker/template_ref');
+var api_1 = require('angular2/src/core/render/api');
+var view_manager_1 = require('angular2/src/core/linker/view_manager');
+var view_manager_utils_1 = require('angular2/src/core/linker/view_manager_utils');
+var view_manager_utils_spec_1 = require('./view_manager_utils_spec');
+function main() {
+ // TODO(tbosch): add missing tests
+ testing_internal_1.describe('AppViewManager', function () {
+ var renderer;
+ var utils;
+ var viewListener;
+ var viewPool;
+ var linker;
+ var manager;
+ var createdRenderViews;
+ function wrapPv(protoView) { return new view_ref_1.ProtoViewRef_(protoView); }
+ function wrapView(view) { return new view_ref_1.ViewRef_(view); }
+ function resetSpies() {
+ viewListener.spy('onViewCreated').reset();
+ viewListener.spy('onViewDestroyed').reset();
+ renderer.spy('createView').reset();
+ renderer.spy('destroyView').reset();
+ renderer.spy('createRootHostView').reset();
+ renderer.spy('setEventDispatcher').reset();
+ renderer.spy('hydrateView').reset();
+ renderer.spy('dehydrateView').reset();
+ viewPool.spy('returnView').reset();
+ }
+ testing_internal_1.beforeEach(function () {
+ renderer = new spies_1.SpyRenderer();
+ utils = new view_manager_utils_1.AppViewManagerUtils();
+ viewListener = new spies_1.SpyAppViewListener();
+ viewPool = new spies_1.SpyAppViewPool();
+ linker = new spies_1.SpyProtoViewFactory();
+ manager = new view_manager_1.AppViewManager_(viewPool, viewListener, utils, renderer, linker);
+ createdRenderViews = [];
+ renderer.spy('createRootHostView')
+ .andCallFake(function (_a, renderFragmentCount, _b) {
+ var fragments = [];
+ for (var i = 0; i < renderFragmentCount; i++) {
+ fragments.push(new api_1.RenderFragmentRef());
+ }
+ var rv = new api_1.RenderViewWithFragments(new api_1.RenderViewRef(), fragments);
+ createdRenderViews.push(rv);
+ return rv;
+ });
+ renderer.spy('createView')
+ .andCallFake(function (_a, renderFragmentCount) {
+ var fragments = [];
+ for (var i = 0; i < renderFragmentCount; i++) {
+ fragments.push(new api_1.RenderFragmentRef());
+ }
+ var rv = new api_1.RenderViewWithFragments(new api_1.RenderViewRef(), fragments);
+ createdRenderViews.push(rv);
+ return rv;
+ });
+ viewPool.spy('returnView').andReturn(true);
+ });
+ testing_internal_1.describe('createRootHostView', function () {
+ var hostProtoView;
+ testing_internal_1.beforeEach(function () { hostProtoView = view_manager_utils_spec_1.createHostPv([view_manager_utils_spec_1.createNestedElBinder(view_manager_utils_spec_1.createComponentPv())]); });
+ testing_internal_1.it('should initialize the ProtoView', function () {
+ manager.createRootHostView(wrapPv(hostProtoView), null, null);
+ testing_internal_1.expect(linker.spy('initializeProtoViewIfNeeded')).toHaveBeenCalledWith(hostProtoView);
+ });
+ testing_internal_1.it('should create the view', function () {
+ var rootView = view_ref_1.internalView(manager.createRootHostView(wrapPv(hostProtoView), null, null));
+ testing_internal_1.expect(rootView.proto).toBe(hostProtoView);
+ testing_internal_1.expect(viewListener.spy('onViewCreated')).toHaveBeenCalledWith(rootView);
+ });
+ testing_internal_1.it('should hydrate the view', function () {
+ var injector = core_1.Injector.resolveAndCreate([]);
+ var rootView = view_ref_1.internalView(manager.createRootHostView(wrapPv(hostProtoView), null, injector));
+ testing_internal_1.expect(rootView.hydrated()).toBe(true);
+ testing_internal_1.expect(renderer.spy('hydrateView')).toHaveBeenCalledWith(rootView.render);
+ });
+ testing_internal_1.it('should create and set the render view using the component selector', function () {
+ var rootView = view_ref_1.internalView(manager.createRootHostView(wrapPv(hostProtoView), null, null));
+ testing_internal_1.expect(renderer.spy('createRootHostView'))
+ .toHaveBeenCalledWith(hostProtoView.render, hostProtoView.mergeInfo.embeddedViewCount + 1, 'someComponent');
+ testing_internal_1.expect(rootView.render).toBe(createdRenderViews[0].viewRef);
+ testing_internal_1.expect(rootView.renderFragment).toBe(createdRenderViews[0].fragmentRefs[0]);
+ });
+ testing_internal_1.it('should allow to override the selector', function () {
+ var selector = 'someOtherSelector';
+ view_ref_1.internalView(manager.createRootHostView(wrapPv(hostProtoView), selector, null));
+ testing_internal_1.expect(renderer.spy('createRootHostView'))
+ .toHaveBeenCalledWith(hostProtoView.render, hostProtoView.mergeInfo.embeddedViewCount + 1, selector);
+ });
+ testing_internal_1.it('should set the event dispatcher', function () {
+ var rootView = view_ref_1.internalView(manager.createRootHostView(wrapPv(hostProtoView), null, null));
+ testing_internal_1.expect(renderer.spy('setEventDispatcher')).toHaveBeenCalledWith(rootView.render, rootView);
+ });
+ });
+ testing_internal_1.describe('destroyRootHostView', function () {
+ var hostProtoView;
+ var hostView;
+ var hostRenderViewRef;
+ testing_internal_1.beforeEach(function () {
+ hostProtoView = view_manager_utils_spec_1.createHostPv([view_manager_utils_spec_1.createNestedElBinder(view_manager_utils_spec_1.createComponentPv())]);
+ hostView =
+ view_ref_1.internalView(manager.createRootHostView(wrapPv(hostProtoView), null, null));
+ hostRenderViewRef = hostView.render;
+ });
+ testing_internal_1.it('should dehydrate', function () {
+ manager.destroyRootHostView(wrapView(hostView));
+ testing_internal_1.expect(hostView.hydrated()).toBe(false);
+ testing_internal_1.expect(renderer.spy('dehydrateView')).toHaveBeenCalledWith(hostView.render);
+ });
+ testing_internal_1.it('should destroy the render view', function () {
+ manager.destroyRootHostView(wrapView(hostView));
+ testing_internal_1.expect(renderer.spy('destroyView')).toHaveBeenCalledWith(hostRenderViewRef);
+ testing_internal_1.expect(viewListener.spy('onViewDestroyed')).toHaveBeenCalledWith(hostView);
+ });
+ testing_internal_1.it('should not return the view to the pool', function () {
+ manager.destroyRootHostView(wrapView(hostView));
+ testing_internal_1.expect(viewPool.spy('returnView')).not.toHaveBeenCalled();
+ });
+ });
+ testing_internal_1.describe('createEmbeddedViewInContainer', function () {
+ testing_internal_1.describe('basic functionality', function () {
+ var hostView;
+ var childProtoView;
+ var vcRef;
+ var templateRef;
+ testing_internal_1.beforeEach(function () {
+ childProtoView = view_manager_utils_spec_1.createEmbeddedPv();
+ var hostProtoView = view_manager_utils_spec_1.createHostPv([view_manager_utils_spec_1.createNestedElBinder(view_manager_utils_spec_1.createComponentPv([view_manager_utils_spec_1.createNestedElBinder(childProtoView)]))]);
+ hostView =
+ view_ref_1.internalView(manager.createRootHostView(wrapPv(hostProtoView), null, null));
+ vcRef = hostView.elementRefs[1];
+ templateRef = new template_ref_1.TemplateRef_(hostView.elementRefs[1]);
+ resetSpies();
+ });
+ testing_internal_1.it('should initialize the ProtoView', function () {
+ manager.createEmbeddedViewInContainer(vcRef, 0, templateRef);
+ testing_internal_1.expect(linker.spy('initializeProtoViewIfNeeded')).toHaveBeenCalledWith(childProtoView);
+ });
+ testing_internal_1.describe('create the first view', function () {
+ testing_internal_1.it('should create an AppViewContainer if not yet existing', function () {
+ manager.createEmbeddedViewInContainer(vcRef, 0, templateRef);
+ testing_internal_1.expect(hostView.viewContainers[1]).toBeTruthy();
+ });
+ testing_internal_1.it('should use an existing nested view', function () {
+ var childView = view_ref_1.internalView(manager.createEmbeddedViewInContainer(vcRef, 0, templateRef));
+ testing_internal_1.expect(childView.proto).toBe(childProtoView);
+ testing_internal_1.expect(childView).toBe(hostView.views[2]);
+ testing_internal_1.expect(viewListener.spy('onViewCreated')).not.toHaveBeenCalled();
+ testing_internal_1.expect(renderer.spy('createView')).not.toHaveBeenCalled();
+ });
+ testing_internal_1.it('should attach the fragment', function () {
+ var childView = view_ref_1.internalView(manager.createEmbeddedViewInContainer(vcRef, 0, templateRef));
+ testing_internal_1.expect(childView.proto).toBe(childProtoView);
+ testing_internal_1.expect(hostView.viewContainers[1].views.length).toBe(1);
+ testing_internal_1.expect(hostView.viewContainers[1].views[0]).toBe(childView);
+ testing_internal_1.expect(renderer.spy('attachFragmentAfterElement'))
+ .toHaveBeenCalledWith(vcRef, childView.renderFragment);
+ });
+ testing_internal_1.it('should hydrate the view but not the render view', function () {
+ var childView = view_ref_1.internalView(manager.createEmbeddedViewInContainer(vcRef, 0, templateRef));
+ testing_internal_1.expect(childView.hydrated()).toBe(true);
+ testing_internal_1.expect(renderer.spy('hydrateView')).not.toHaveBeenCalled();
+ });
+ testing_internal_1.it('should not set the EventDispatcher', function () {
+ view_ref_1.internalView(manager.createEmbeddedViewInContainer(vcRef, 0, templateRef));
+ testing_internal_1.expect(renderer.spy('setEventDispatcher')).not.toHaveBeenCalled();
+ });
+ });
+ testing_internal_1.describe('create the second view', function () {
+ var firstChildView;
+ testing_internal_1.beforeEach(function () {
+ firstChildView =
+ view_ref_1.internalView(manager.createEmbeddedViewInContainer(vcRef, 0, templateRef));
+ resetSpies();
+ });
+ testing_internal_1.it('should create a new view', function () {
+ var childView = view_ref_1.internalView(manager.createEmbeddedViewInContainer(vcRef, 1, templateRef));
+ testing_internal_1.expect(childView.proto).toBe(childProtoView);
+ testing_internal_1.expect(childView).not.toBe(firstChildView);
+ testing_internal_1.expect(viewListener.spy('onViewCreated')).toHaveBeenCalledWith(childView);
+ testing_internal_1.expect(renderer.spy('createView'))
+ .toHaveBeenCalledWith(childProtoView.render, childProtoView.mergeInfo.embeddedViewCount + 1);
+ testing_internal_1.expect(childView.render).toBe(createdRenderViews[1].viewRef);
+ testing_internal_1.expect(childView.renderFragment).toBe(createdRenderViews[1].fragmentRefs[0]);
+ });
+ testing_internal_1.it('should attach the fragment', function () {
+ var childView = view_ref_1.internalView(manager.createEmbeddedViewInContainer(vcRef, 1, templateRef));
+ testing_internal_1.expect(childView.proto).toBe(childProtoView);
+ testing_internal_1.expect(hostView.viewContainers[1].views[1]).toBe(childView);
+ testing_internal_1.expect(renderer.spy('attachFragmentAfterFragment'))
+ .toHaveBeenCalledWith(firstChildView.renderFragment, childView.renderFragment);
+ });
+ testing_internal_1.it('should hydrate the view', function () {
+ var childView = view_ref_1.internalView(manager.createEmbeddedViewInContainer(vcRef, 1, templateRef));
+ testing_internal_1.expect(childView.hydrated()).toBe(true);
+ testing_internal_1.expect(renderer.spy('hydrateView')).toHaveBeenCalledWith(childView.render);
+ });
+ testing_internal_1.it('should set the EventDispatcher', function () {
+ var childView = view_ref_1.internalView(manager.createEmbeddedViewInContainer(vcRef, 1, templateRef));
+ testing_internal_1.expect(renderer.spy('setEventDispatcher'))
+ .toHaveBeenCalledWith(childView.render, childView);
+ });
+ });
+ testing_internal_1.describe('create another view when the first view has been returned', function () {
+ testing_internal_1.beforeEach(function () {
+ view_ref_1.internalView(manager.createEmbeddedViewInContainer(vcRef, 0, templateRef));
+ manager.destroyViewInContainer(vcRef, 0);
+ resetSpies();
+ });
+ testing_internal_1.it('should use an existing nested view', function () {
+ var childView = view_ref_1.internalView(manager.createEmbeddedViewInContainer(vcRef, 0, templateRef));
+ testing_internal_1.expect(childView.proto).toBe(childProtoView);
+ testing_internal_1.expect(childView).toBe(hostView.views[2]);
+ testing_internal_1.expect(viewListener.spy('onViewCreated')).not.toHaveBeenCalled();
+ testing_internal_1.expect(renderer.spy('createView')).not.toHaveBeenCalled();
+ });
+ });
+ testing_internal_1.describe('create a host view', function () {
+ testing_internal_1.it('should initialize the ProtoView', function () {
+ var newHostPv = view_manager_utils_spec_1.createHostPv([view_manager_utils_spec_1.createNestedElBinder(view_manager_utils_spec_1.createComponentPv())]);
+ manager.createHostViewInContainer(vcRef, 0, wrapPv(newHostPv), null);
+ testing_internal_1.expect(linker.spy('initializeProtoViewIfNeeded')).toHaveBeenCalledWith(newHostPv);
+ });
+ testing_internal_1.it('should always create a new view and not use the embedded view', function () {
+ var newHostPv = view_manager_utils_spec_1.createHostPv([view_manager_utils_spec_1.createNestedElBinder(view_manager_utils_spec_1.createComponentPv())]);
+ var newHostView = view_ref_1.internalView(manager.createHostViewInContainer(vcRef, 0, wrapPv(newHostPv), null));
+ testing_internal_1.expect(newHostView.proto).toBe(newHostPv);
+ testing_internal_1.expect(newHostView).not.toBe(hostView.views[2]);
+ testing_internal_1.expect(viewListener.spy('onViewCreated')).toHaveBeenCalledWith(newHostView);
+ testing_internal_1.expect(renderer.spy('createView'))
+ .toHaveBeenCalledWith(newHostPv.render, newHostPv.mergeInfo.embeddedViewCount + 1);
+ });
+ });
+ });
+ });
+ testing_internal_1.describe('destroyViewInContainer', function () {
+ testing_internal_1.describe('basic functionality', function () {
+ var hostView;
+ var childProtoView;
+ var vcRef;
+ var templateRef;
+ var firstChildView;
+ testing_internal_1.beforeEach(function () {
+ childProtoView = view_manager_utils_spec_1.createEmbeddedPv();
+ var hostProtoView = view_manager_utils_spec_1.createHostPv([view_manager_utils_spec_1.createNestedElBinder(view_manager_utils_spec_1.createComponentPv([view_manager_utils_spec_1.createNestedElBinder(childProtoView)]))]);
+ hostView =
+ view_ref_1.internalView(manager.createRootHostView(wrapPv(hostProtoView), null, null));
+ vcRef = hostView.elementRefs[1];
+ templateRef = new template_ref_1.TemplateRef_(hostView.elementRefs[1]);
+ firstChildView =
+ view_ref_1.internalView(manager.createEmbeddedViewInContainer(vcRef, 0, templateRef));
+ resetSpies();
+ });
+ testing_internal_1.describe('destroy the first view', function () {
+ testing_internal_1.it('should dehydrate the app view but not the render view', function () {
+ manager.destroyViewInContainer(vcRef, 0);
+ testing_internal_1.expect(firstChildView.hydrated()).toBe(false);
+ testing_internal_1.expect(renderer.spy('dehydrateView')).not.toHaveBeenCalled();
+ });
+ testing_internal_1.it('should detach', function () {
+ manager.destroyViewInContainer(vcRef, 0);
+ testing_internal_1.expect(hostView.viewContainers[1].views).toEqual([]);
+ testing_internal_1.expect(renderer.spy('detachFragment'))
+ .toHaveBeenCalledWith(firstChildView.renderFragment);
+ });
+ testing_internal_1.it('should not return the view to the pool', function () {
+ manager.destroyViewInContainer(vcRef, 0);
+ testing_internal_1.expect(viewPool.spy('returnView')).not.toHaveBeenCalled();
+ });
+ });
+ testing_internal_1.describe('destroy another view', function () {
+ var secondChildView;
+ testing_internal_1.beforeEach(function () {
+ secondChildView =
+ view_ref_1.internalView(manager.createEmbeddedViewInContainer(vcRef, 1, templateRef));
+ resetSpies();
+ });
+ testing_internal_1.it('should dehydrate', function () {
+ manager.destroyViewInContainer(vcRef, 1);
+ testing_internal_1.expect(secondChildView.hydrated()).toBe(false);
+ testing_internal_1.expect(renderer.spy('dehydrateView')).toHaveBeenCalledWith(secondChildView.render);
+ });
+ testing_internal_1.it('should detach', function () {
+ manager.destroyViewInContainer(vcRef, 1);
+ testing_internal_1.expect(hostView.viewContainers[1].views[0]).toBe(firstChildView);
+ testing_internal_1.expect(renderer.spy('detachFragment'))
+ .toHaveBeenCalledWith(secondChildView.renderFragment);
+ });
+ testing_internal_1.it('should return the view to the pool', function () {
+ manager.destroyViewInContainer(vcRef, 1);
+ testing_internal_1.expect(viewPool.spy('returnView')).toHaveBeenCalledWith(secondChildView);
+ });
+ });
+ });
+ testing_internal_1.describe('recursively destroy views in ViewContainers', function () {
+ testing_internal_1.describe('destroy child views when a component is destroyed', function () {
+ var hostView;
+ var childProtoView;
+ var vcRef;
+ var templateRef;
+ var firstChildView;
+ var secondChildView;
+ testing_internal_1.beforeEach(function () {
+ childProtoView = view_manager_utils_spec_1.createEmbeddedPv();
+ var hostProtoView = view_manager_utils_spec_1.createHostPv([view_manager_utils_spec_1.createNestedElBinder(view_manager_utils_spec_1.createComponentPv([view_manager_utils_spec_1.createNestedElBinder(childProtoView)]))]);
+ hostView = view_ref_1.internalView(manager.createRootHostView(wrapPv(hostProtoView), null, null));
+ vcRef = hostView.elementRefs[1];
+ templateRef = new template_ref_1.TemplateRef_(hostView.elementRefs[1]);
+ firstChildView =
+ view_ref_1.internalView(manager.createEmbeddedViewInContainer(vcRef, 0, templateRef));
+ secondChildView =
+ view_ref_1.internalView(manager.createEmbeddedViewInContainer(vcRef, 1, templateRef));
+ resetSpies();
+ });
+ testing_internal_1.it('should dehydrate', function () {
+ manager.destroyRootHostView(wrapView(hostView));
+ testing_internal_1.expect(firstChildView.hydrated()).toBe(false);
+ testing_internal_1.expect(secondChildView.hydrated()).toBe(false);
+ testing_internal_1.expect(renderer.spy('dehydrateView')).toHaveBeenCalledWith(hostView.render);
+ testing_internal_1.expect(renderer.spy('dehydrateView')).toHaveBeenCalledWith(secondChildView.render);
+ });
+ testing_internal_1.it('should detach', function () {
+ manager.destroyRootHostView(wrapView(hostView));
+ testing_internal_1.expect(hostView.viewContainers[1].views).toEqual([]);
+ testing_internal_1.expect(renderer.spy('detachFragment'))
+ .toHaveBeenCalledWith(firstChildView.renderFragment);
+ testing_internal_1.expect(renderer.spy('detachFragment'))
+ .toHaveBeenCalledWith(secondChildView.renderFragment);
+ });
+ testing_internal_1.it('should return the view to the pool', function () {
+ manager.destroyRootHostView(wrapView(hostView));
+ testing_internal_1.expect(viewPool.spy('returnView')).not.toHaveBeenCalledWith(firstChildView);
+ testing_internal_1.expect(viewPool.spy('returnView')).toHaveBeenCalledWith(secondChildView);
+ });
+ });
+ testing_internal_1.describe('destroy child views over multiple levels', function () {
+ var hostView;
+ var childProtoView;
+ var nestedChildProtoView;
+ var vcRef;
+ var templateRef;
+ var nestedVcRefs;
+ var childViews;
+ var nestedChildViews;
+ testing_internal_1.beforeEach(function () {
+ nestedChildProtoView = view_manager_utils_spec_1.createEmbeddedPv();
+ childProtoView = view_manager_utils_spec_1.createEmbeddedPv([
+ view_manager_utils_spec_1.createNestedElBinder(view_manager_utils_spec_1.createComponentPv([view_manager_utils_spec_1.createNestedElBinder(nestedChildProtoView)]))
+ ]);
+ var hostProtoView = view_manager_utils_spec_1.createHostPv([view_manager_utils_spec_1.createNestedElBinder(view_manager_utils_spec_1.createComponentPv([view_manager_utils_spec_1.createNestedElBinder(childProtoView)]))]);
+ hostView = view_ref_1.internalView(manager.createRootHostView(wrapPv(hostProtoView), null, null));
+ vcRef = hostView.elementRefs[1];
+ templateRef = new template_ref_1.TemplateRef_(hostView.elementRefs[1]);
+ nestedChildViews = [];
+ childViews = [];
+ nestedVcRefs = [];
+ for (var i = 0; i < 2; i++) {
+ var view = view_ref_1.internalView(manager.createEmbeddedViewInContainer(vcRef, i, templateRef));
+ childViews.push(view);
+ var nestedVcRef = view.elementRefs[view.elementOffset];
+ nestedVcRefs.push(nestedVcRef);
+ for (var j = 0; j < 2; j++) {
+ var nestedView = view_ref_1.internalView(manager.createEmbeddedViewInContainer(nestedVcRef, j, templateRef));
+ nestedChildViews.push(nestedView);
+ }
+ }
+ resetSpies();
+ });
+ testing_internal_1.it('should dehydrate all child views', function () {
+ manager.destroyRootHostView(wrapView(hostView));
+ childViews.forEach(function (childView) { return testing_internal_1.expect(childView.hydrated()).toBe(false); });
+ nestedChildViews.forEach(function (childView) { return testing_internal_1.expect(childView.hydrated()).toBe(false); });
+ });
+ });
+ });
+ });
+ testing_internal_1.describe('attachViewInContainer', function () {
+ });
+ testing_internal_1.describe('detachViewInContainer', function () {
+ });
+ });
+}
+exports.main = main;
+//# sourceMappingURL=view_manager_spec.js.map
\ No newline at end of file
diff --git a/test/core/linker/view_manager_utils_spec.js b/test/core/linker/view_manager_utils_spec.js
new file mode 100644
index 00000000000..85eed77876b
--- /dev/null
+++ b/test/core/linker/view_manager_utils_spec.js
@@ -0,0 +1,228 @@
+var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") return Reflect.decorate(decorators, target, key, desc);
+ switch (arguments.length) {
+ case 2: return decorators.reduceRight(function(o, d) { return (d && d(o)) || o; }, target);
+ case 3: return decorators.reduceRight(function(o, d) { return (d && d(target, key)), void 0; }, void 0);
+ case 4: return decorators.reduceRight(function(o, d) { return (d && d(target, key, o)) || o; }, desc);
+ }
+};
+var __metadata = (this && this.__metadata) || function (k, v) {
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
+};
+var testing_internal_1 = require('angular2/testing_internal');
+var spies_1 = require('../spies');
+var core_1 = require('angular2/core');
+var lang_1 = require('angular2/src/facade/lang');
+var view_1 = require('angular2/src/core/linker/view');
+var element_binder_1 = require('angular2/src/core/linker/element_binder');
+var element_injector_1 = require('angular2/src/core/linker/element_injector');
+var directive_resolver_1 = require('angular2/src/core/linker/directive_resolver');
+var metadata_1 = require('angular2/src/core/metadata');
+var view_manager_utils_1 = require('angular2/src/core/linker/view_manager_utils');
+var render_1 = require('angular2/src/core/render/render');
+function main() {
+ // TODO(tbosch): add more tests here!
+ testing_internal_1.describe('AppViewManagerUtils', function () {
+ var utils;
+ testing_internal_1.beforeEach(function () { utils = new view_manager_utils_1.AppViewManagerUtils(); });
+ function createViewWithChildren(pv) {
+ var renderViewWithFragments = new render_1.RenderViewWithFragments(null, [null, null]);
+ return utils.createView(pv, renderViewWithFragments, null, null);
+ }
+ testing_internal_1.describe('shared hydrate functionality', function () {
+ testing_internal_1.it("should hydrate the change detector after hydrating element injectors", function () {
+ var log = new testing_internal_1.Log();
+ var componentProtoView = createComponentPv([createEmptyElBinder()]);
+ var hostView = createViewWithChildren(createHostPv([createNestedElBinder(componentProtoView)]));
+ var componentView = hostView.views[1];
+ var spyEi = componentView.elementInjectors[0];
+ spyEi.spy('hydrate').andCallFake(log.fn('hydrate'));
+ var spyCd = componentView.changeDetector;
+ spyCd.spy('hydrate').andCallFake(log.fn('hydrateCD'));
+ utils.hydrateRootHostView(hostView, createInjector());
+ testing_internal_1.expect(log.result()).toEqual('hydrate; hydrateCD');
+ });
+ testing_internal_1.it("should set up event listeners", function () {
+ var dir = new Object();
+ var hostPv = createHostPv([createNestedElBinder(createComponentPv()), createEmptyElBinder()]);
+ var hostView = createViewWithChildren(hostPv);
+ var spyEventAccessor1 = testing_internal_1.SpyObject.stub({ "subscribe": null });
+ testing_internal_1.SpyObject.stub(hostView.elementInjectors[0], { 'getEventEmitterAccessors': [[spyEventAccessor1]], 'getDirectiveAtIndex': dir });
+ var spyEventAccessor2 = testing_internal_1.SpyObject.stub({ "subscribe": null });
+ testing_internal_1.SpyObject.stub(hostView.elementInjectors[1], { 'getEventEmitterAccessors': [[spyEventAccessor2]], 'getDirectiveAtIndex': dir });
+ utils.hydrateRootHostView(hostView, createInjector());
+ testing_internal_1.expect(spyEventAccessor1.spy('subscribe')).toHaveBeenCalledWith(hostView, 0, dir);
+ testing_internal_1.expect(spyEventAccessor2.spy('subscribe')).toHaveBeenCalledWith(hostView, 1, dir);
+ });
+ testing_internal_1.it("should not hydrate element injectors of component views inside of embedded fragments", function () {
+ var hostView = createViewWithChildren(createHostPv([
+ createNestedElBinder(createComponentPv([
+ createNestedElBinder(createEmbeddedPv([createNestedElBinder(createComponentPv([createEmptyElBinder()]))]))
+ ]))
+ ]));
+ utils.hydrateRootHostView(hostView, createInjector());
+ testing_internal_1.expect(hostView.elementInjectors.length).toBe(4);
+ testing_internal_1.expect(hostView.elementInjectors[3].spy('hydrate')).not.toHaveBeenCalled();
+ });
+ });
+ testing_internal_1.describe('attachViewInContainer', function () {
+ var parentView, contextView, childView;
+ function createViews(numInj) {
+ if (numInj === void 0) { numInj = 1; }
+ var childPv = createEmbeddedPv([createEmptyElBinder()]);
+ childView = createViewWithChildren(childPv);
+ var parentPv = createHostPv([createEmptyElBinder()]);
+ parentView = createViewWithChildren(parentPv);
+ var binders = [];
+ for (var i = 0; i < numInj; i++) {
+ binders.push(createEmptyElBinder(i > 0 ? binders[i - 1] : null));
+ }
+ var contextPv = createHostPv(binders);
+ contextView = createViewWithChildren(contextPv);
+ }
+ testing_internal_1.it('should not modify the rootElementInjectors at the given context view', function () {
+ createViews();
+ utils.attachViewInContainer(parentView, 0, contextView, 0, 0, childView);
+ testing_internal_1.expect(contextView.rootElementInjectors.length).toEqual(1);
+ });
+ testing_internal_1.it('should link the views rootElementInjectors after the elementInjector at the given context', function () {
+ createViews(2);
+ utils.attachViewInContainer(parentView, 0, contextView, 1, 0, childView);
+ testing_internal_1.expect(childView.rootElementInjectors[0].spy('link'))
+ .toHaveBeenCalledWith(contextView.elementInjectors[0]);
+ });
+ });
+ testing_internal_1.describe('hydrateViewInContainer', function () {
+ var parentView, contextView, childView;
+ function createViews() {
+ var parentPv = createHostPv([createEmptyElBinder()]);
+ parentView = createViewWithChildren(parentPv);
+ var contextPv = createHostPv([createEmptyElBinder()]);
+ contextView = createViewWithChildren(contextPv);
+ var childPv = createEmbeddedPv([createEmptyElBinder()]);
+ childView = createViewWithChildren(childPv);
+ utils.attachViewInContainer(parentView, 0, contextView, 0, 0, childView);
+ }
+ testing_internal_1.it("should instantiate the elementInjectors with the host of the context's elementInjector", function () {
+ createViews();
+ utils.hydrateViewInContainer(parentView, 0, contextView, 0, 0, null);
+ testing_internal_1.expect(childView.rootElementInjectors[0].spy('hydrate'))
+ .toHaveBeenCalledWith(null, contextView.elementInjectors[0].getHost(), childView.preBuiltObjects[0]);
+ });
+ });
+ testing_internal_1.describe('hydrateRootHostView', function () {
+ var hostView;
+ function createViews() {
+ var hostPv = createHostPv([createNestedElBinder(createComponentPv())]);
+ hostView = createViewWithChildren(hostPv);
+ }
+ testing_internal_1.it("should instantiate the elementInjectors with the given injector and an empty host element injector", function () {
+ var injector = createInjector();
+ createViews();
+ utils.hydrateRootHostView(hostView, injector);
+ testing_internal_1.expect(hostView.rootElementInjectors[0].spy('hydrate'))
+ .toHaveBeenCalledWith(injector, null, hostView.preBuiltObjects[0]);
+ });
+ });
+ });
+}
+exports.main = main;
+function createInjector() {
+ return core_1.Injector.resolveAndCreate([]);
+}
+exports.createInjector = createInjector;
+function createElementInjector(parent) {
+ if (parent === void 0) { parent = null; }
+ var host = new spies_1.SpyElementInjector();
+ var elementInjector = new spies_1.SpyElementInjector();
+ var _preBuiltObjects = null;
+ var res = testing_internal_1.SpyObject.stub(elementInjector, {
+ 'isExportingComponent': false,
+ 'isExportingElement': false,
+ 'getEventEmitterAccessors': [],
+ 'getHostActionAccessors': [],
+ 'getComponent': new Object(),
+ 'getHost': host
+ });
+ res.spy('getNestedView').andCallFake(function () { return _preBuiltObjects.nestedView; });
+ res.spy('hydrate')
+ .andCallFake(function (mperativelyCreatedInjector, host, preBuiltObjects) { _preBuiltObjects = preBuiltObjects; });
+ res.prop('parent', parent);
+ return res;
+}
+function createProtoElInjector(parent) {
+ if (parent === void 0) { parent = null; }
+ var pei = new spies_1.SpyProtoElementInjector();
+ pei.prop("parent", parent);
+ pei.prop("index", 0);
+ pei.spy('instantiate').andCallFake(function (parentEli) { return createElementInjector(parentEli); });
+ return pei;
+}
+exports.createProtoElInjector = createProtoElInjector;
+function createEmptyElBinder(parent) {
+ if (parent === void 0) { parent = null; }
+ var parentPeli = lang_1.isPresent(parent) ? parent.protoElementInjector : null;
+ return new element_binder_1.ElementBinder(0, null, 0, createProtoElInjector(parentPeli), null, null);
+}
+exports.createEmptyElBinder = createEmptyElBinder;
+function createNestedElBinder(nestedProtoView) {
+ var componentProvider = null;
+ if (nestedProtoView.type === view_1.ViewType.COMPONENT) {
+ var annotation = new directive_resolver_1.DirectiveResolver().resolve(SomeComponent);
+ componentProvider = element_injector_1.DirectiveProvider.createFromType(SomeComponent, annotation);
+ }
+ return new element_binder_1.ElementBinder(0, null, 0, createProtoElInjector(), componentProvider, nestedProtoView);
+}
+exports.createNestedElBinder = createNestedElBinder;
+function _createProtoView(type, binders) {
+ if (binders === void 0) { binders = null; }
+ if (lang_1.isBlank(binders)) {
+ binders = [];
+ }
+ var res = new view_1.AppProtoView(null, [], type, true, function (_) { return new spies_1.SpyChangeDetector(); }, new Map(), null);
+ var mergedElementCount = 0;
+ var mergedEmbeddedViewCount = 0;
+ var mergedViewCount = 1;
+ for (var i = 0; i < binders.length; i++) {
+ var binder = binders[i];
+ binder.protoElementInjector.index = i;
+ mergedElementCount++;
+ var nestedPv = binder.nestedProtoView;
+ if (lang_1.isPresent(nestedPv)) {
+ mergedElementCount += nestedPv.mergeInfo.elementCount;
+ mergedEmbeddedViewCount += nestedPv.mergeInfo.embeddedViewCount;
+ mergedViewCount += nestedPv.mergeInfo.viewCount;
+ if (nestedPv.type === view_1.ViewType.EMBEDDED) {
+ mergedEmbeddedViewCount++;
+ }
+ }
+ }
+ var mergeInfo = new view_1.AppProtoViewMergeInfo(mergedEmbeddedViewCount, mergedElementCount, mergedViewCount);
+ res.init(null, binders, 0, mergeInfo, new Map());
+ return res;
+}
+function createHostPv(binders) {
+ if (binders === void 0) { binders = null; }
+ return _createProtoView(view_1.ViewType.HOST, binders);
+}
+exports.createHostPv = createHostPv;
+function createComponentPv(binders) {
+ if (binders === void 0) { binders = null; }
+ return _createProtoView(view_1.ViewType.COMPONENT, binders);
+}
+exports.createComponentPv = createComponentPv;
+function createEmbeddedPv(binders) {
+ if (binders === void 0) { binders = null; }
+ return _createProtoView(view_1.ViewType.EMBEDDED, binders);
+}
+exports.createEmbeddedPv = createEmbeddedPv;
+var SomeComponent = (function () {
+ function SomeComponent() {
+ }
+ SomeComponent = __decorate([
+ metadata_1.Component({ selector: 'someComponent' }),
+ __metadata('design:paramtypes', [])
+ ], SomeComponent);
+ return SomeComponent;
+})();
+//# sourceMappingURL=view_manager_utils_spec.js.map
\ No newline at end of file
diff --git a/test/core/linker/view_pool_spec.js b/test/core/linker/view_pool_spec.js
new file mode 100644
index 00000000000..aad52c5f29d
--- /dev/null
+++ b/test/core/linker/view_pool_spec.js
@@ -0,0 +1,52 @@
+var testing_internal_1 = require('angular2/testing_internal');
+var view_pool_1 = require('angular2/src/core/linker/view_pool');
+var view_1 = require('angular2/src/core/linker/view');
+var collection_1 = require('angular2/src/facade/collection');
+function main() {
+ testing_internal_1.describe('AppViewPool', function () {
+ function createViewPool(_a) {
+ var capacity = _a.capacity;
+ return new view_pool_1.AppViewPool(capacity);
+ }
+ function createProtoView() {
+ return new view_1.AppProtoView(null, null, null, null, null, null, null);
+ }
+ function createView(pv) {
+ return new view_1.AppView(null, pv, null, null, null, new collection_1.Map(), null, null, null);
+ }
+ testing_internal_1.it('should support multiple AppProtoViews', function () {
+ var vf = createViewPool({ capacity: 2 });
+ var pv1 = createProtoView();
+ var pv2 = createProtoView();
+ var view1 = createView(pv1);
+ var view2 = createView(pv2);
+ vf.returnView(view1);
+ vf.returnView(view2);
+ testing_internal_1.expect(vf.getView(pv1)).toBe(view1);
+ testing_internal_1.expect(vf.getView(pv2)).toBe(view2);
+ });
+ testing_internal_1.it('should reuse the newest view that has been returned', function () {
+ var pv = createProtoView();
+ var vf = createViewPool({ capacity: 2 });
+ var view1 = createView(pv);
+ var view2 = createView(pv);
+ vf.returnView(view1);
+ vf.returnView(view2);
+ testing_internal_1.expect(vf.getView(pv)).toBe(view2);
+ });
+ testing_internal_1.it('should not add views when the capacity has been reached', function () {
+ var pv = createProtoView();
+ var vf = createViewPool({ capacity: 2 });
+ var view1 = createView(pv);
+ var view2 = createView(pv);
+ var view3 = createView(pv);
+ testing_internal_1.expect(vf.returnView(view1)).toBe(true);
+ testing_internal_1.expect(vf.returnView(view2)).toBe(true);
+ testing_internal_1.expect(vf.returnView(view3)).toBe(false);
+ testing_internal_1.expect(vf.getView(pv)).toBe(view2);
+ testing_internal_1.expect(vf.getView(pv)).toBe(view1);
+ });
+ });
+}
+exports.main = main;
+//# sourceMappingURL=view_pool_spec.js.map
\ No newline at end of file
diff --git a/test/core/linker/view_resolver_spec.js b/test/core/linker/view_resolver_spec.js
new file mode 100644
index 00000000000..a0452b8b773
--- /dev/null
+++ b/test/core/linker/view_resolver_spec.js
@@ -0,0 +1,140 @@
+var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") return Reflect.decorate(decorators, target, key, desc);
+ switch (arguments.length) {
+ case 2: return decorators.reduceRight(function(o, d) { return (d && d(o)) || o; }, target);
+ case 3: return decorators.reduceRight(function(o, d) { return (d && d(target, key)), void 0; }, void 0);
+ case 4: return decorators.reduceRight(function(o, d) { return (d && d(target, key, o)) || o; }, desc);
+ }
+};
+var __metadata = (this && this.__metadata) || function (k, v) {
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
+};
+var testing_internal_1 = require('angular2/testing_internal');
+var view_resolver_1 = require('angular2/src/core/linker/view_resolver');
+var metadata_1 = require('angular2/src/core/metadata');
+var SomeDir = (function () {
+ function SomeDir() {
+ }
+ return SomeDir;
+})();
+var SomePipe = (function () {
+ function SomePipe() {
+ }
+ return SomePipe;
+})();
+var ComponentWithView = (function () {
+ function ComponentWithView() {
+ }
+ ComponentWithView = __decorate([
+ metadata_1.Component({ selector: 'sample' }),
+ metadata_1.View({ template: "some template", directives: [SomeDir], pipes: [SomePipe], styles: ["some styles"] }),
+ __metadata('design:paramtypes', [])
+ ], ComponentWithView);
+ return ComponentWithView;
+})();
+var ComponentWithTemplate = (function () {
+ function ComponentWithTemplate() {
+ }
+ ComponentWithTemplate = __decorate([
+ metadata_1.Component({
+ selector: 'sample',
+ template: "some template",
+ directives: [SomeDir],
+ pipes: [SomePipe],
+ styles: ["some styles"]
+ }),
+ __metadata('design:paramtypes', [])
+ ], ComponentWithTemplate);
+ return ComponentWithTemplate;
+})();
+var ComponentWithViewTemplate = (function () {
+ function ComponentWithViewTemplate() {
+ }
+ ComponentWithViewTemplate = __decorate([
+ metadata_1.Component({ selector: 'sample', template: "some template" }),
+ metadata_1.View({ template: "some template" }),
+ __metadata('design:paramtypes', [])
+ ], ComponentWithViewTemplate);
+ return ComponentWithViewTemplate;
+})();
+var ComponentWithViewTemplateUrl = (function () {
+ function ComponentWithViewTemplateUrl() {
+ }
+ ComponentWithViewTemplateUrl = __decorate([
+ metadata_1.Component({ selector: 'sample', templateUrl: "some template url" }),
+ metadata_1.View({ template: "some template" }),
+ __metadata('design:paramtypes', [])
+ ], ComponentWithViewTemplateUrl);
+ return ComponentWithViewTemplateUrl;
+})();
+var ComponentWithoutView = (function () {
+ function ComponentWithoutView() {
+ }
+ ComponentWithoutView = __decorate([
+ metadata_1.Component({ selector: 'sample' }),
+ __metadata('design:paramtypes', [])
+ ], ComponentWithoutView);
+ return ComponentWithoutView;
+})();
+var ClassWithView = (function () {
+ function ClassWithView() {
+ }
+ ClassWithView = __decorate([
+ metadata_1.View({ template: "some template" }),
+ __metadata('design:paramtypes', [])
+ ], ClassWithView);
+ return ClassWithView;
+})();
+var SimpleClass = (function () {
+ function SimpleClass() {
+ }
+ return SimpleClass;
+})();
+function main() {
+ testing_internal_1.describe("ViewResolver", function () {
+ var resolver;
+ testing_internal_1.beforeEach(function () { resolver = new view_resolver_1.ViewResolver(); });
+ testing_internal_1.it('should read out the View metadata', function () {
+ var viewMetadata = resolver.resolve(ComponentWithView);
+ testing_internal_1.expect(viewMetadata)
+ .toEqual(new metadata_1.View({
+ template: "some template",
+ directives: [SomeDir],
+ pipes: [SomePipe],
+ styles: ["some styles"]
+ }));
+ });
+ testing_internal_1.it('should read out the View metadata from the Component metadata', function () {
+ var viewMetadata = resolver.resolve(ComponentWithTemplate);
+ testing_internal_1.expect(viewMetadata)
+ .toEqual(new metadata_1.ViewMetadata({
+ template: "some template",
+ directives: [SomeDir],
+ pipes: [SomePipe],
+ styles: ["some styles"]
+ }));
+ });
+ testing_internal_1.it('should read out the View metadata from a simple class', function () {
+ var viewMetadata = resolver.resolve(ClassWithView);
+ testing_internal_1.expect(viewMetadata).toEqual(new metadata_1.View({ template: "some template" }));
+ });
+ testing_internal_1.it('should throw when Component.template is specified together with the View metadata', function () {
+ testing_internal_1.expect(function () { return resolver.resolve(ComponentWithViewTemplate); })
+ .toThrowErrorWith("Component 'ComponentWithViewTemplate' cannot have both 'template' and '@View' set at the same time");
+ });
+ testing_internal_1.it('should throw when Component.template is specified together with the View metadata', function () {
+ testing_internal_1.expect(function () { return resolver.resolve(ComponentWithViewTemplateUrl); })
+ .toThrowErrorWith("Component 'ComponentWithViewTemplateUrl' cannot have both 'templateUrl' and '@View' set at the same time");
+ });
+ testing_internal_1.it('should throw when Component has no View decorator and no template is set', function () {
+ testing_internal_1.expect(function () { return resolver.resolve(ComponentWithoutView); })
+ .toThrowErrorWith("Component 'ComponentWithoutView' must have either 'template', 'templateUrl', or '@View' set");
+ });
+ testing_internal_1.it('should throw when simple class has no View decorator and no template is set', function () {
+ testing_internal_1.expect(function () { return resolver.resolve(SimpleClass); })
+ .toThrowErrorWith("No View decorator found on component 'SimpleClass'");
+ });
+ });
+}
+exports.main = main;
+//# sourceMappingURL=view_resolver_spec.js.map
\ No newline at end of file
diff --git a/test/core/metadata/decorators_spec.js b/test/core/metadata/decorators_spec.js
new file mode 100644
index 00000000000..8d4afc882db
--- /dev/null
+++ b/test/core/metadata/decorators_spec.js
@@ -0,0 +1,24 @@
+var testing_internal_1 = require('angular2/testing_internal');
+var angular2_1 = require('angular2/angular2');
+var reflection_1 = require('angular2/src/core/reflection/reflection');
+function main() {
+ testing_internal_1.describe('es5 decorators', function () {
+ testing_internal_1.it('should declare directive class', function () {
+ var MyDirective = angular2_1.Directive({}).Class({ constructor: function () { this.works = true; } });
+ testing_internal_1.expect(new MyDirective().works).toEqual(true);
+ });
+ testing_internal_1.it('should declare Component class', function () {
+ var MyComponent = angular2_1.Component({}).View({}).View({}).Class({ constructor: function () { this.works = true; } });
+ testing_internal_1.expect(new MyComponent().works).toEqual(true);
+ });
+ testing_internal_1.it('should create type in ES5', function () {
+ function MyComponent() { }
+ ;
+ var as;
+ MyComponent.annotations = as = angular2_1.Component({}).View({});
+ testing_internal_1.expect(reflection_1.reflector.annotations(MyComponent)).toEqual(as.annotations);
+ });
+ });
+}
+exports.main = main;
+//# sourceMappingURL=decorators_spec.js.map
\ No newline at end of file
diff --git a/test/core/reflection/reflector_common.js b/test/core/reflection/reflector_common.js
new file mode 100644
index 00000000000..8b2cd77a655
--- /dev/null
+++ b/test/core/reflection/reflector_common.js
@@ -0,0 +1,45 @@
+var decorators_1 = require('angular2/src/core/util/decorators');
+var ClassDecoratorMeta = (function () {
+ function ClassDecoratorMeta(value) {
+ this.value = value;
+ }
+ return ClassDecoratorMeta;
+})();
+exports.ClassDecoratorMeta = ClassDecoratorMeta;
+var ParamDecoratorMeta = (function () {
+ function ParamDecoratorMeta(value) {
+ this.value = value;
+ }
+ return ParamDecoratorMeta;
+})();
+exports.ParamDecoratorMeta = ParamDecoratorMeta;
+var PropDecoratorMeta = (function () {
+ function PropDecoratorMeta(value) {
+ this.value = value;
+ }
+ return PropDecoratorMeta;
+})();
+exports.PropDecoratorMeta = PropDecoratorMeta;
+function classDecorator(value) {
+ return new ClassDecoratorMeta(value);
+}
+exports.classDecorator = classDecorator;
+function paramDecorator(value) {
+ return new ParamDecoratorMeta(value);
+}
+exports.paramDecorator = paramDecorator;
+function propDecorator(value) {
+ return new PropDecoratorMeta(value);
+}
+exports.propDecorator = propDecorator;
+exports.ClassDecorator = decorators_1.makeDecorator(ClassDecoratorMeta);
+exports.ParamDecorator = decorators_1.makeParamDecorator(ParamDecoratorMeta);
+exports.PropDecorator = decorators_1.makePropDecorator(PropDecoratorMeta);
+// used only in Dart
+var HasGetterAndSetterDecorators = (function () {
+ function HasGetterAndSetterDecorators() {
+ }
+ return HasGetterAndSetterDecorators;
+})();
+exports.HasGetterAndSetterDecorators = HasGetterAndSetterDecorators;
+//# sourceMappingURL=reflector_common.js.map
\ No newline at end of file
diff --git a/test/core/reflection/reflector_spec.js b/test/core/reflection/reflector_spec.js
new file mode 100644
index 00000000000..8c8cb330a51
--- /dev/null
+++ b/test/core/reflection/reflector_spec.js
@@ -0,0 +1,424 @@
+var __extends = (this && this.__extends) || function (d, b) {
+ for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
+ function __() { this.constructor = d; }
+ d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
+};
+var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") return Reflect.decorate(decorators, target, key, desc);
+ switch (arguments.length) {
+ case 2: return decorators.reduceRight(function(o, d) { return (d && d(o)) || o; }, target);
+ case 3: return decorators.reduceRight(function(o, d) { return (d && d(target, key)), void 0; }, void 0);
+ case 4: return decorators.reduceRight(function(o, d) { return (d && d(target, key, o)) || o; }, desc);
+ }
+};
+var __metadata = (this && this.__metadata) || function (k, v) {
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
+};
+var __param = (this && this.__param) || function (paramIndex, decorator) {
+ return function (target, key) { decorator(target, key, paramIndex); }
+};
+var testing_internal_1 = require('angular2/testing_internal');
+var reflection_1 = require('angular2/src/core/reflection/reflection');
+var reflection_capabilities_1 = require('angular2/src/core/reflection/reflection_capabilities');
+var reflector_common_1 = require('./reflector_common');
+var lang_1 = require('angular2/src/facade/lang');
+var AType = (function () {
+ function AType(value) {
+ this.value = value;
+ }
+ return AType;
+})();
+var ClassWithDecorators = (function () {
+ function ClassWithDecorators(a, b) {
+ this.a = a;
+ this.b = b;
+ }
+ Object.defineProperty(ClassWithDecorators.prototype, "c", {
+ set: function (value) {
+ },
+ enumerable: true,
+ configurable: true
+ });
+ __decorate([
+ reflector_common_1.PropDecorator("p1"),
+ reflector_common_1.PropDecorator("p2"),
+ __metadata('design:type', Object)
+ ], ClassWithDecorators.prototype, "a");
+ Object.defineProperty(ClassWithDecorators.prototype, "c",
+ __decorate([
+ reflector_common_1.PropDecorator("p3"),
+ __metadata('design:type', Object),
+ __metadata('design:paramtypes', [Object])
+ ], ClassWithDecorators.prototype, "c", Object.getOwnPropertyDescriptor(ClassWithDecorators.prototype, "c")));
+ ClassWithDecorators = __decorate([
+ reflector_common_1.ClassDecorator('class'),
+ __param(0, reflector_common_1.ParamDecorator("a")),
+ __param(1, reflector_common_1.ParamDecorator("b")),
+ __metadata('design:paramtypes', [AType, AType])
+ ], ClassWithDecorators);
+ return ClassWithDecorators;
+})();
+var ClassWithoutDecorators = (function () {
+ function ClassWithoutDecorators(a, b) {
+ }
+ return ClassWithoutDecorators;
+})();
+var TestObj = (function () {
+ function TestObj(a, b) {
+ this.a = a;
+ this.b = b;
+ }
+ TestObj.prototype.identity = function (arg) { return arg; };
+ return TestObj;
+})();
+var Interface = (function () {
+ function Interface() {
+ }
+ return Interface;
+})();
+var Interface2 = (function () {
+ function Interface2() {
+ }
+ return Interface2;
+})();
+var SuperClassImplementingInterface = (function () {
+ function SuperClassImplementingInterface() {
+ }
+ return SuperClassImplementingInterface;
+})();
+var ClassImplementingInterface = (function (_super) {
+ __extends(ClassImplementingInterface, _super);
+ function ClassImplementingInterface() {
+ _super.apply(this, arguments);
+ }
+ return ClassImplementingInterface;
+})(SuperClassImplementingInterface);
+function main() {
+ testing_internal_1.describe('Reflector', function () {
+ var reflector;
+ testing_internal_1.beforeEach(function () { reflector = new reflection_1.Reflector(new reflection_capabilities_1.ReflectionCapabilities()); });
+ testing_internal_1.describe("usage tracking", function () {
+ testing_internal_1.beforeEach(function () { reflector = new reflection_1.Reflector(null); });
+ testing_internal_1.it("should be disabled by default", function () {
+ testing_internal_1.expect(function () { return reflector.listUnusedKeys(); }).toThrowError('Usage tracking is disabled');
+ });
+ testing_internal_1.it("should report unused keys", function () {
+ reflector.trackUsage();
+ testing_internal_1.expect(reflector.listUnusedKeys()).toEqual([]);
+ reflector.registerType(AType, new reflection_1.ReflectionInfo(null, null, function () { return "AType"; }));
+ reflector.registerType(TestObj, new reflection_1.ReflectionInfo(null, null, function () { return "TestObj"; }));
+ testing_internal_1.expect(reflector.listUnusedKeys()).toEqual([AType, TestObj]);
+ reflector.factory(AType);
+ testing_internal_1.expect(reflector.listUnusedKeys()).toEqual([TestObj]);
+ reflector.factory(TestObj);
+ testing_internal_1.expect(reflector.listUnusedKeys()).toEqual([]);
+ });
+ });
+ testing_internal_1.describe("factory", function () {
+ testing_internal_1.it("should create a factory for the given type", function () {
+ var obj = reflector.factory(TestObj)(1, 2);
+ testing_internal_1.expect(obj.a).toEqual(1);
+ testing_internal_1.expect(obj.b).toEqual(2);
+ });
+ // Makes Edge to disconnect when running the full unit test campaign
+ // TODO: remove when issue is solved: https://github.com/angular/angular/issues/4756
+ if (!testing_internal_1.browserDetection.isEdge) {
+ testing_internal_1.it("should check args from no to max", function () {
+ var f = function (t) { return reflector.factory(t); };
+ var checkArgs = function (obj, args) { return testing_internal_1.expect(obj.args).toEqual(args); };
+ // clang-format off
+ checkArgs(f(TestObjWith00Args)(), []);
+ checkArgs(f(TestObjWith01Args)(1), [1]);
+ checkArgs(f(TestObjWith02Args)(1, 2), [1, 2]);
+ checkArgs(f(TestObjWith03Args)(1, 2, 3), [1, 2, 3]);
+ checkArgs(f(TestObjWith04Args)(1, 2, 3, 4), [1, 2, 3, 4]);
+ checkArgs(f(TestObjWith05Args)(1, 2, 3, 4, 5), [1, 2, 3, 4, 5]);
+ checkArgs(f(TestObjWith06Args)(1, 2, 3, 4, 5, 6), [1, 2, 3, 4, 5, 6]);
+ checkArgs(f(TestObjWith07Args)(1, 2, 3, 4, 5, 6, 7), [1, 2, 3, 4, 5, 6, 7]);
+ checkArgs(f(TestObjWith08Args)(1, 2, 3, 4, 5, 6, 7, 8), [1, 2, 3, 4, 5, 6, 7, 8]);
+ checkArgs(f(TestObjWith09Args)(1, 2, 3, 4, 5, 6, 7, 8, 9), [1, 2, 3, 4, 5, 6, 7, 8, 9]);
+ checkArgs(f(TestObjWith10Args)(1, 2, 3, 4, 5, 6, 7, 8, 9, 10), [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
+ checkArgs(f(TestObjWith11Args)(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11), [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]);
+ checkArgs(f(TestObjWith12Args)(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12), [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]);
+ checkArgs(f(TestObjWith13Args)(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13), [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]);
+ checkArgs(f(TestObjWith14Args)(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14), [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]);
+ checkArgs(f(TestObjWith15Args)(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15), [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]);
+ checkArgs(f(TestObjWith16Args)(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16), [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]);
+ checkArgs(f(TestObjWith17Args)(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17), [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17]);
+ checkArgs(f(TestObjWith18Args)(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18), [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18]);
+ checkArgs(f(TestObjWith19Args)(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19), [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]);
+ checkArgs(f(TestObjWith20Args)(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20), [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]);
+ // clang-format on
+ });
+ }
+ testing_internal_1.it("should throw when more than 20 arguments", function () { testing_internal_1.expect(function () { return reflector.factory(TestObjWith21Args); }).toThrowError(); });
+ testing_internal_1.it("should return a registered factory if available", function () {
+ reflector.registerType(TestObj, new reflection_1.ReflectionInfo(null, null, function () { return "fake"; }));
+ testing_internal_1.expect(reflector.factory(TestObj)()).toEqual("fake");
+ });
+ });
+ testing_internal_1.describe("parameters", function () {
+ testing_internal_1.it("should return an array of parameters for a type", function () {
+ var p = reflector.parameters(ClassWithDecorators);
+ testing_internal_1.expect(p).toEqual([[AType, reflector_common_1.paramDecorator('a')], [AType, reflector_common_1.paramDecorator('b')]]);
+ });
+ testing_internal_1.it("should work for a class without annotations", function () {
+ var p = reflector.parameters(ClassWithoutDecorators);
+ testing_internal_1.expect(p.length).toEqual(2);
+ });
+ testing_internal_1.it("should return registered parameters if available", function () {
+ reflector.registerType(TestObj, new reflection_1.ReflectionInfo(null, [[1], [2]]));
+ testing_internal_1.expect(reflector.parameters(TestObj)).toEqual([[1], [2]]);
+ });
+ testing_internal_1.it("should return an empty list when no paramters field in the stored type info", function () {
+ reflector.registerType(TestObj, new reflection_1.ReflectionInfo());
+ testing_internal_1.expect(reflector.parameters(TestObj)).toEqual([]);
+ });
+ });
+ testing_internal_1.describe("propMetadata", function () {
+ testing_internal_1.it("should return a string map of prop metadata for the given class", function () {
+ var p = reflector.propMetadata(ClassWithDecorators);
+ testing_internal_1.expect(p["a"]).toEqual([reflector_common_1.propDecorator("p1"), reflector_common_1.propDecorator("p2")]);
+ testing_internal_1.expect(p["c"]).toEqual([reflector_common_1.propDecorator("p3")]);
+ });
+ testing_internal_1.it("should return registered meta if available", function () {
+ reflector.registerType(TestObj, new reflection_1.ReflectionInfo(null, null, null, null, { "a": [1, 2] }));
+ testing_internal_1.expect(reflector.propMetadata(TestObj)).toEqual({ "a": [1, 2] });
+ });
+ if (lang_1.IS_DART) {
+ testing_internal_1.it("should merge metadata from getters and setters", function () {
+ var p = reflector.propMetadata(reflector_common_1.HasGetterAndSetterDecorators);
+ testing_internal_1.expect(p["a"]).toEqual([reflector_common_1.propDecorator("get"), reflector_common_1.propDecorator("set")]);
+ });
+ }
+ });
+ testing_internal_1.describe("annotations", function () {
+ testing_internal_1.it("should return an array of annotations for a type", function () {
+ var p = reflector.annotations(ClassWithDecorators);
+ testing_internal_1.expect(p).toEqual([reflector_common_1.classDecorator('class')]);
+ });
+ testing_internal_1.it("should return registered annotations if available", function () {
+ reflector.registerType(TestObj, new reflection_1.ReflectionInfo([1, 2]));
+ testing_internal_1.expect(reflector.annotations(TestObj)).toEqual([1, 2]);
+ });
+ testing_internal_1.it("should work for a class without annotations", function () {
+ var p = reflector.annotations(ClassWithoutDecorators);
+ testing_internal_1.expect(p).toEqual([]);
+ });
+ });
+ if (lang_1.IS_DART) {
+ testing_internal_1.describe("interfaces", function () {
+ testing_internal_1.it("should return an array of interfaces for a type", function () {
+ var p = reflector.interfaces(ClassImplementingInterface);
+ testing_internal_1.expect(p).toEqual([Interface, Interface2]);
+ });
+ testing_internal_1.it("should return an empty array otherwise", function () {
+ var p = reflector.interfaces(ClassWithDecorators);
+ testing_internal_1.expect(p).toEqual([]);
+ });
+ });
+ }
+ testing_internal_1.describe("getter", function () {
+ testing_internal_1.it("returns a function reading a property", function () {
+ var getA = reflector.getter('a');
+ testing_internal_1.expect(getA(new TestObj(1, 2))).toEqual(1);
+ });
+ testing_internal_1.it("should return a registered getter if available", function () {
+ reflector.registerGetters({ "abc": function (obj) { return "fake"; } });
+ testing_internal_1.expect(reflector.getter("abc")("anything")).toEqual("fake");
+ });
+ });
+ testing_internal_1.describe("setter", function () {
+ testing_internal_1.it("returns a function setting a property", function () {
+ var setA = reflector.setter('a');
+ var obj = new TestObj(1, 2);
+ setA(obj, 100);
+ testing_internal_1.expect(obj.a).toEqual(100);
+ });
+ testing_internal_1.it("should return a registered setter if available", function () {
+ var updateMe;
+ reflector.registerSetters({ "abc": function (obj, value) { updateMe = value; } });
+ reflector.setter("abc")("anything", "fake");
+ testing_internal_1.expect(updateMe).toEqual("fake");
+ });
+ });
+ testing_internal_1.describe("method", function () {
+ testing_internal_1.it("returns a function invoking a method", function () {
+ var func = reflector.method('identity');
+ var obj = new TestObj(1, 2);
+ testing_internal_1.expect(func(obj, ['value'])).toEqual('value');
+ });
+ testing_internal_1.it("should return a registered method if available", function () {
+ reflector.registerMethods({ "abc": function (obj, args) { return args; } });
+ testing_internal_1.expect(reflector.method("abc")("anything", ["fake"])).toEqual(['fake']);
+ });
+ });
+ if (lang_1.IS_DART) {
+ testing_internal_1.describe("importUri", function () {
+ testing_internal_1.it("should return the importUri for a type", function () {
+ testing_internal_1.expect(reflector.importUri(TestObjWith00Args)
+ .endsWith('base/dist/dart/angular2/test/core/reflection/reflector_spec.dart'))
+ .toBe(true);
+ });
+ });
+ }
+ });
+}
+exports.main = main;
+var TestObjWith00Args = (function () {
+ function TestObjWith00Args() {
+ this.args = [];
+ }
+ return TestObjWith00Args;
+})();
+var TestObjWith01Args = (function () {
+ function TestObjWith01Args(a1) {
+ this.args = [a1];
+ }
+ return TestObjWith01Args;
+})();
+var TestObjWith02Args = (function () {
+ function TestObjWith02Args(a1, a2) {
+ this.args = [a1, a2];
+ }
+ return TestObjWith02Args;
+})();
+var TestObjWith03Args = (function () {
+ function TestObjWith03Args(a1, a2, a3) {
+ this.args = [a1, a2, a3];
+ }
+ return TestObjWith03Args;
+})();
+var TestObjWith04Args = (function () {
+ function TestObjWith04Args(a1, a2, a3, a4) {
+ this.args = [a1, a2, a3, a4];
+ }
+ return TestObjWith04Args;
+})();
+var TestObjWith05Args = (function () {
+ function TestObjWith05Args(a1, a2, a3, a4, a5) {
+ this.args = [a1, a2, a3, a4, a5];
+ }
+ return TestObjWith05Args;
+})();
+var TestObjWith06Args = (function () {
+ function TestObjWith06Args(a1, a2, a3, a4, a5, a6) {
+ this.args = [a1, a2, a3, a4, a5, a6];
+ }
+ return TestObjWith06Args;
+})();
+var TestObjWith07Args = (function () {
+ function TestObjWith07Args(a1, a2, a3, a4, a5, a6, a7) {
+ this.args = [a1, a2, a3, a4, a5, a6, a7];
+ }
+ return TestObjWith07Args;
+})();
+var TestObjWith08Args = (function () {
+ function TestObjWith08Args(a1, a2, a3, a4, a5, a6, a7, a8) {
+ this.args = [a1, a2, a3, a4, a5, a6, a7, a8];
+ }
+ return TestObjWith08Args;
+})();
+var TestObjWith09Args = (function () {
+ function TestObjWith09Args(a1, a2, a3, a4, a5, a6, a7, a8, a9) {
+ this.args = [a1, a2, a3, a4, a5, a6, a7, a8, a9];
+ }
+ return TestObjWith09Args;
+})();
+var TestObjWith10Args = (function () {
+ function TestObjWith10Args(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10) {
+ this.args = [a1, a2, a3, a4, a5, a6, a7, a8, a9, a10];
+ }
+ return TestObjWith10Args;
+})();
+var TestObjWith11Args = (function () {
+ function TestObjWith11Args(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11) {
+ this.args = [a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11];
+ }
+ return TestObjWith11Args;
+})();
+var TestObjWith12Args = (function () {
+ function TestObjWith12Args(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12) {
+ this.args = [a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12];
+ }
+ return TestObjWith12Args;
+})();
+var TestObjWith13Args = (function () {
+ function TestObjWith13Args(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13) {
+ this.args = [a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13];
+ }
+ return TestObjWith13Args;
+})();
+var TestObjWith14Args = (function () {
+ function TestObjWith14Args(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14) {
+ this.args = [a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14];
+ }
+ return TestObjWith14Args;
+})();
+var TestObjWith15Args = (function () {
+ function TestObjWith15Args(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15) {
+ this.args = [a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15];
+ }
+ return TestObjWith15Args;
+})();
+var TestObjWith16Args = (function () {
+ function TestObjWith16Args(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16) {
+ this.args = [a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16];
+ }
+ return TestObjWith16Args;
+})();
+var TestObjWith17Args = (function () {
+ function TestObjWith17Args(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17) {
+ this.args = [a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17];
+ }
+ return TestObjWith17Args;
+})();
+var TestObjWith18Args = (function () {
+ function TestObjWith18Args(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18) {
+ this.args = [a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18];
+ }
+ return TestObjWith18Args;
+})();
+var TestObjWith19Args = (function () {
+ function TestObjWith19Args(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19) {
+ this.args =
+ [a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19];
+ }
+ return TestObjWith19Args;
+})();
+var TestObjWith20Args = (function () {
+ function TestObjWith20Args(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20) {
+ this.args =
+ [a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20];
+ }
+ return TestObjWith20Args;
+})();
+var TestObjWith21Args = (function () {
+ function TestObjWith21Args(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21) {
+ this.args = [
+ a1,
+ a2,
+ a3,
+ a4,
+ a5,
+ a6,
+ a7,
+ a8,
+ a9,
+ a10,
+ a11,
+ a12,
+ a13,
+ a14,
+ a15,
+ a16,
+ a17,
+ a18,
+ a19,
+ a20,
+ a21
+ ];
+ }
+ return TestObjWith21Args;
+})();
+//# sourceMappingURL=reflector_spec.js.map
\ No newline at end of file
diff --git a/test/core/render/dom/dom_renderer_integration_spec.js b/test/core/render/dom/dom_renderer_integration_spec.js
new file mode 100644
index 00000000000..30f14e2d52e
--- /dev/null
+++ b/test/core/render/dom/dom_renderer_integration_spec.js
@@ -0,0 +1,19 @@
+var testing_internal_1 = require('angular2/testing_internal');
+// import {MapWrapper} from 'angular2/src/facade/collection';
+// import {DOM} from 'angular2/src/core/dom/dom_adapter';
+// import {DomTestbed, TestRootView, elRef} from './dom_testbed';
+// import {
+// ViewDefinition,
+// RenderDirectiveMetadata,
+// RenderViewRef,
+// ViewEncapsulation
+// } from 'angular2/src/core/render/api';
+function main() {
+ testing_internal_1.describe('DomRenderer integration', function () {
+ testing_internal_1.it('should work', function () {
+ // TODO
+ });
+ });
+}
+exports.main = main;
+//# sourceMappingURL=dom_renderer_integration_spec.js.map
\ No newline at end of file
diff --git a/test/core/render/dom/events/event_manager_spec.js b/test/core/render/dom/events/event_manager_spec.js
new file mode 100644
index 00000000000..495c589513e
--- /dev/null
+++ b/test/core/render/dom/events/event_manager_spec.js
@@ -0,0 +1,99 @@
+var __extends = (this && this.__extends) || function (d, b) {
+ for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
+ function __() { this.constructor = d; }
+ d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
+};
+var testing_internal_1 = require('angular2/testing_internal');
+var event_manager_1 = require('angular2/src/core/render/dom/events/event_manager');
+var ng_zone_1 = require('angular2/src/core/zone/ng_zone');
+var collection_1 = require('angular2/src/facade/collection');
+var dom_adapter_1 = require('angular2/src/core/dom/dom_adapter');
+function main() {
+ var domEventPlugin;
+ testing_internal_1.beforeEach(function () { domEventPlugin = new event_manager_1.DomEventsPlugin(); });
+ testing_internal_1.describe('EventManager', function () {
+ testing_internal_1.it('should delegate event bindings to plugins that are passed in from the most generic one to the most specific one', function () {
+ var element = testing_internal_1.el('');
+ var handler = function (e) { return e; };
+ var plugin = new FakeEventManagerPlugin(['click']);
+ var manager = new event_manager_1.EventManager([domEventPlugin, plugin], new FakeNgZone());
+ manager.addEventListener(element, 'click', handler);
+ testing_internal_1.expect(plugin._eventHandler.get('click')).toBe(handler);
+ });
+ testing_internal_1.it('should delegate event bindings to the first plugin supporting the event', function () {
+ var element = testing_internal_1.el('');
+ var clickHandler = function (e) { return e; };
+ var dblClickHandler = function (e) { return e; };
+ var plugin1 = new FakeEventManagerPlugin(['dblclick']);
+ var plugin2 = new FakeEventManagerPlugin(['click', 'dblclick']);
+ var manager = new event_manager_1.EventManager([plugin2, plugin1], new FakeNgZone());
+ manager.addEventListener(element, 'click', clickHandler);
+ manager.addEventListener(element, 'dblclick', dblClickHandler);
+ testing_internal_1.expect(plugin1._eventHandler.has('click')).toBe(false);
+ testing_internal_1.expect(plugin2._eventHandler.get('click')).toBe(clickHandler);
+ testing_internal_1.expect(plugin2._eventHandler.has('dblclick')).toBe(false);
+ testing_internal_1.expect(plugin1._eventHandler.get('dblclick')).toBe(dblClickHandler);
+ });
+ testing_internal_1.it('should throw when no plugin can handle the event', function () {
+ var element = testing_internal_1.el('');
+ var plugin = new FakeEventManagerPlugin(['dblclick']);
+ var manager = new event_manager_1.EventManager([plugin], new FakeNgZone());
+ testing_internal_1.expect(function () { return manager.addEventListener(element, 'click', null); })
+ .toThrowError('No event manager plugin found for event click');
+ });
+ testing_internal_1.it('events are caught when fired from a child', function () {
+ var element = testing_internal_1.el('
');
+ // Workaround for https://bugs.webkit.org/show_bug.cgi?id=122755
+ dom_adapter_1.DOM.appendChild(dom_adapter_1.DOM.defaultDoc().body, element);
+ var child = dom_adapter_1.DOM.firstChild(element);
+ var dispatchedEvent = dom_adapter_1.DOM.createMouseEvent('click');
+ var receivedEvent = null;
+ var handler = function (e) { receivedEvent = e; };
+ var manager = new event_manager_1.EventManager([domEventPlugin], new FakeNgZone());
+ manager.addEventListener(element, 'click', handler);
+ dom_adapter_1.DOM.dispatchEvent(child, dispatchedEvent);
+ testing_internal_1.expect(receivedEvent).toBe(dispatchedEvent);
+ });
+ testing_internal_1.it('should add and remove global event listeners', function () {
+ var element = testing_internal_1.el('
');
+ dom_adapter_1.DOM.appendChild(dom_adapter_1.DOM.defaultDoc().body, element);
+ var dispatchedEvent = dom_adapter_1.DOM.createMouseEvent('click');
+ var receivedEvent = null;
+ var handler = function (e) { receivedEvent = e; };
+ var manager = new event_manager_1.EventManager([domEventPlugin], new FakeNgZone());
+ var remover = manager.addGlobalEventListener("document", 'click', handler);
+ dom_adapter_1.DOM.dispatchEvent(element, dispatchedEvent);
+ testing_internal_1.expect(receivedEvent).toBe(dispatchedEvent);
+ receivedEvent = null;
+ remover();
+ dom_adapter_1.DOM.dispatchEvent(element, dispatchedEvent);
+ testing_internal_1.expect(receivedEvent).toBe(null);
+ });
+ });
+}
+exports.main = main;
+var FakeEventManagerPlugin = (function (_super) {
+ __extends(FakeEventManagerPlugin, _super);
+ function FakeEventManagerPlugin(_supports) {
+ _super.call(this);
+ this._supports = _supports;
+ this._eventHandler = new collection_1.Map();
+ }
+ FakeEventManagerPlugin.prototype.supports = function (eventName) { return collection_1.ListWrapper.contains(this._supports, eventName); };
+ FakeEventManagerPlugin.prototype.addEventListener = function (element, eventName, handler) {
+ var _this = this;
+ this._eventHandler.set(eventName, handler);
+ return function () { _this._eventHandler.delete(eventName); };
+ };
+ return FakeEventManagerPlugin;
+})(event_manager_1.EventManagerPlugin);
+var FakeNgZone = (function (_super) {
+ __extends(FakeNgZone, _super);
+ function FakeNgZone() {
+ _super.call(this, { enableLongStackTrace: false });
+ }
+ FakeNgZone.prototype.run = function (fn) { fn(); };
+ FakeNgZone.prototype.runOutsideAngular = function (fn) { return fn(); };
+ return FakeNgZone;
+})(ng_zone_1.NgZone);
+//# sourceMappingURL=event_manager_spec.js.map
\ No newline at end of file
diff --git a/test/core/render/dom/events/key_events_spec.js b/test/core/render/dom/events/key_events_spec.js
new file mode 100644
index 00000000000..150e4ebab55
--- /dev/null
+++ b/test/core/render/dom/events/key_events_spec.js
@@ -0,0 +1,46 @@
+var testing_internal_1 = require('angular2/testing_internal');
+var key_events_1 = require('angular2/src/core/render/dom/events/key_events');
+function main() {
+ testing_internal_1.describe('KeyEvents', function () {
+ testing_internal_1.it('should ignore unrecognized events', function () {
+ testing_internal_1.expect(key_events_1.KeyEventsPlugin.parseEventName('keydown')).toEqual(null);
+ testing_internal_1.expect(key_events_1.KeyEventsPlugin.parseEventName('keyup')).toEqual(null);
+ testing_internal_1.expect(key_events_1.KeyEventsPlugin.parseEventName('keydown.unknownmodifier.enter')).toEqual(null);
+ testing_internal_1.expect(key_events_1.KeyEventsPlugin.parseEventName('keyup.unknownmodifier.enter')).toEqual(null);
+ testing_internal_1.expect(key_events_1.KeyEventsPlugin.parseEventName('unknownevent.control.shift.enter')).toEqual(null);
+ testing_internal_1.expect(key_events_1.KeyEventsPlugin.parseEventName('unknownevent.enter')).toEqual(null);
+ });
+ testing_internal_1.it('should correctly parse event names', function () {
+ // key with no modifier
+ testing_internal_1.expect(key_events_1.KeyEventsPlugin.parseEventName('keydown.enter'))
+ .toEqual({ 'domEventName': 'keydown', 'fullKey': 'enter' });
+ testing_internal_1.expect(key_events_1.KeyEventsPlugin.parseEventName('keyup.enter'))
+ .toEqual({ 'domEventName': 'keyup', 'fullKey': 'enter' });
+ // key with modifiers:
+ testing_internal_1.expect(key_events_1.KeyEventsPlugin.parseEventName('keydown.control.shift.enter'))
+ .toEqual({ 'domEventName': 'keydown', 'fullKey': 'control.shift.enter' });
+ testing_internal_1.expect(key_events_1.KeyEventsPlugin.parseEventName('keyup.control.shift.enter'))
+ .toEqual({ 'domEventName': 'keyup', 'fullKey': 'control.shift.enter' });
+ // key with modifiers in a different order:
+ testing_internal_1.expect(key_events_1.KeyEventsPlugin.parseEventName('keydown.shift.control.enter'))
+ .toEqual({ 'domEventName': 'keydown', 'fullKey': 'control.shift.enter' });
+ testing_internal_1.expect(key_events_1.KeyEventsPlugin.parseEventName('keyup.shift.control.enter'))
+ .toEqual({ 'domEventName': 'keyup', 'fullKey': 'control.shift.enter' });
+ // key that is also a modifier:
+ testing_internal_1.expect(key_events_1.KeyEventsPlugin.parseEventName('keydown.shift.control'))
+ .toEqual({ 'domEventName': 'keydown', 'fullKey': 'shift.control' });
+ testing_internal_1.expect(key_events_1.KeyEventsPlugin.parseEventName('keyup.shift.control'))
+ .toEqual({ 'domEventName': 'keyup', 'fullKey': 'shift.control' });
+ testing_internal_1.expect(key_events_1.KeyEventsPlugin.parseEventName('keydown.control.shift'))
+ .toEqual({ 'domEventName': 'keydown', 'fullKey': 'control.shift' });
+ testing_internal_1.expect(key_events_1.KeyEventsPlugin.parseEventName('keyup.control.shift'))
+ .toEqual({ 'domEventName': 'keyup', 'fullKey': 'control.shift' });
+ });
+ testing_internal_1.it('should alias esc to escape', function () {
+ testing_internal_1.expect(key_events_1.KeyEventsPlugin.parseEventName('keyup.control.esc'))
+ .toEqual(key_events_1.KeyEventsPlugin.parseEventName('keyup.control.escape'));
+ });
+ });
+}
+exports.main = main;
+//# sourceMappingURL=key_events_spec.js.map
\ No newline at end of file
diff --git a/test/core/render/dom/shared_styles_host_spec.js b/test/core/render/dom/shared_styles_host_spec.js
new file mode 100644
index 00000000000..17000012107
--- /dev/null
+++ b/test/core/render/dom/shared_styles_host_spec.js
@@ -0,0 +1,38 @@
+var testing_internal_1 = require('angular2/testing_internal');
+var dom_adapter_1 = require('angular2/src/core/dom/dom_adapter');
+var shared_styles_host_1 = require('angular2/src/core/render/dom/shared_styles_host');
+function main() {
+ testing_internal_1.describe('DomSharedStylesHost', function () {
+ var doc;
+ var ssh;
+ var someHost;
+ testing_internal_1.beforeEach(function () {
+ doc = dom_adapter_1.DOM.createHtmlDocument();
+ doc.title = '';
+ ssh = new shared_styles_host_1.DomSharedStylesHost(doc);
+ someHost = dom_adapter_1.DOM.createElement('div');
+ });
+ testing_internal_1.it('should add existing styles to new hosts', function () {
+ ssh.addStyles(['a {};']);
+ ssh.addHost(someHost);
+ testing_internal_1.expect(dom_adapter_1.DOM.getInnerHTML(someHost)).toEqual('');
+ });
+ testing_internal_1.it('should add new styles to hosts', function () {
+ ssh.addHost(someHost);
+ ssh.addStyles(['a {};']);
+ testing_internal_1.expect(dom_adapter_1.DOM.getInnerHTML(someHost)).toEqual('');
+ });
+ testing_internal_1.it('should add styles only once to hosts', function () {
+ ssh.addStyles(['a {};']);
+ ssh.addHost(someHost);
+ ssh.addStyles(['a {};']);
+ testing_internal_1.expect(dom_adapter_1.DOM.getInnerHTML(someHost)).toEqual('');
+ });
+ testing_internal_1.it('should use the document head as default host', function () {
+ ssh.addStyles(['a {};', 'b {};']);
+ testing_internal_1.expect(doc.head).toHaveText('a {};b {};');
+ });
+ });
+}
+exports.main = main;
+//# sourceMappingURL=shared_styles_host_spec.js.map
\ No newline at end of file
diff --git a/test/core/render/view_factory_spec.js b/test/core/render/view_factory_spec.js
new file mode 100644
index 00000000000..05d334fb025
--- /dev/null
+++ b/test/core/render/view_factory_spec.js
@@ -0,0 +1,560 @@
+var testing_internal_1 = require('angular2/testing_internal');
+var lang_1 = require('angular2/src/facade/lang');
+var collection_1 = require('angular2/src/facade/collection');
+var appCmds = require('angular2/src/core/linker/template_commands');
+var view_factory_1 = require('angular2/src/core/render/view_factory');
+var api_1 = require('angular2/src/core/render/api');
+var spies_1 = require('../spies');
+var dom_adapter_1 = require('angular2/src/core/dom/dom_adapter');
+var metadata_1 = require('angular2/src/core/metadata');
+function beginElement(name, attrNameAndValues, eventTargetAndNames, isBound, ngContentIndex) {
+ return new appCmds.BeginElementCmd(name, attrNameAndValues, eventTargetAndNames, [], [], isBound, ngContentIndex);
+}
+function endElement() {
+ return new appCmds.EndElementCmd();
+}
+function text(value, isBound, ngContentIndex) {
+ return new appCmds.TextCmd(value, isBound, ngContentIndex);
+}
+function embeddedTemplate(attrNameAndValues, isMerged, ngContentIndex, children) {
+ return new appCmds.EmbeddedTemplateCmd(attrNameAndValues, [], [], isMerged, ngContentIndex, null, children);
+}
+function beginComponent(name, attrNameAndValues, eventTargetAndNames, ngContentIndex, templateId) {
+ return new appCmds.BeginComponentCmd(name, attrNameAndValues, eventTargetAndNames, [], [], null, ngContentIndex, function () { return new appCmds.CompiledComponentTemplate(templateId, null, null, null); });
+}
+function endComponent() {
+ return new appCmds.EndComponentCmd();
+}
+function ngContent(index, ngContentIndex) {
+ return new appCmds.NgContentCmd(index, ngContentIndex);
+}
+function main() {
+ testing_internal_1.describe('createRenderView', function () {
+ var nodeFactory;
+ var eventDispatcher;
+ var componentTemplates = new Map();
+ var defaultCmpTpl;
+ testing_internal_1.beforeEach(function () {
+ nodeFactory = new DomNodeFactory(componentTemplates);
+ eventDispatcher = new spies_1.SpyRenderEventDispatcher();
+ defaultCmpTpl =
+ new api_1.RenderComponentTemplate('someId', 'shortid', metadata_1.ViewEncapsulation.None, [], []);
+ });
+ testing_internal_1.describe('primitives', function () {
+ testing_internal_1.it('should create elements with attributes', function () {
+ var view = view_factory_1.createRenderView(defaultCmpTpl, [beginElement('div', ['attr1', 'value1'], [], false, null), endElement()], null, nodeFactory);
+ testing_internal_1.expect(stringifyFragment(view.fragments[0].nodes)).toEqual('');
+ });
+ testing_internal_1.it('should create host elements with attributes', function () {
+ componentTemplates.set('0', []);
+ var view = view_factory_1.createRenderView(defaultCmpTpl, [beginComponent('a-comp', ['attr1', 'value1'], [], null, '0'), endElement()], null, nodeFactory);
+ testing_internal_1.expect(stringifyFragment(view.fragments[0].nodes))
+ .toEqual('');
+ });
+ testing_internal_1.it('should create embedded templates with attributes', function () {
+ componentTemplates.set('0', []);
+ var view = view_factory_1.createRenderView(defaultCmpTpl, [embeddedTemplate(['attr1', 'value1'], false, null, [])], null, nodeFactory);
+ testing_internal_1.expect(stringifyFragment(view.fragments[0].nodes))
+ .toEqual('');
+ });
+ testing_internal_1.it('should store bound elements', function () {
+ componentTemplates.set('0', []);
+ var view = view_factory_1.createRenderView(defaultCmpTpl, [
+ beginElement('div', ['id', '1'], [], false, null),
+ endElement(),
+ beginElement('span', ['id', '2'], [], true, null),
+ endElement(),
+ beginComponent('a-comp', ['id', '3'], [], null, '0'),
+ endElement(),
+ embeddedTemplate(['id', '4'], false, null, [])
+ ], null, nodeFactory);
+ testing_internal_1.expect(mapAttrs(view.boundElements, 'id')).toEqual(['2', '3', '4']);
+ });
+ testing_internal_1.it('should use the inplace element for the first create element', function () {
+ var el = dom_adapter_1.DOM.createElement('span');
+ var view = view_factory_1.createRenderView(defaultCmpTpl, [
+ beginElement('div', ['attr1', 'value1'], [], false, null),
+ endElement(),
+ beginElement('div', [], [], false, null),
+ endElement()
+ ], el, nodeFactory);
+ testing_internal_1.expect(stringifyFragment(view.fragments[0].nodes))
+ .toEqual('');
+ });
+ testing_internal_1.it('should create text nodes', function () {
+ var view = view_factory_1.createRenderView(defaultCmpTpl, [text('someText', false, null)], null, nodeFactory);
+ testing_internal_1.expect(stringifyFragment(view.fragments[0].nodes)).toEqual('someText');
+ });
+ testing_internal_1.it('should store bound text nodes', function () {
+ var view = view_factory_1.createRenderView(defaultCmpTpl, [text('1', false, null), text('2', true, null)], null, nodeFactory);
+ testing_internal_1.expect(testing_internal_1.stringifyElement(view.boundTextNodes[0])).toEqual('2');
+ });
+ testing_internal_1.it('should register element event listeners', function () {
+ componentTemplates.set('0', []);
+ var view = view_factory_1.createRenderView(defaultCmpTpl, [
+ beginElement('div', [], [null, 'click'], true, null),
+ endElement(),
+ beginComponent('a-comp', [], [null, 'click'], null, '0'),
+ endElement(),
+ ], null, nodeFactory);
+ view.setEventDispatcher(eventDispatcher);
+ var event = {};
+ nodeFactory.triggerLocalEvent(view.boundElements[0], 'click', event);
+ nodeFactory.triggerLocalEvent(view.boundElements[1], 'click', event);
+ testing_internal_1.expect(eventDispatcher.spy('dispatchRenderEvent'))
+ .toHaveBeenCalledWith(0, 'click', collection_1.MapWrapper.createFromStringMap({ '$event': event }));
+ testing_internal_1.expect(eventDispatcher.spy('dispatchRenderEvent'))
+ .toHaveBeenCalledWith(1, 'click', collection_1.MapWrapper.createFromStringMap({ '$event': event }));
+ });
+ testing_internal_1.it('should register element global event listeners', function () {
+ var view = view_factory_1.createRenderView(defaultCmpTpl, [
+ beginElement('div', [], ['window', 'scroll'], true, null),
+ endElement(),
+ beginComponent('a-comp', [], ['window', 'scroll'], null, '0'),
+ endElement(),
+ ], null, nodeFactory);
+ view.hydrate();
+ view.setEventDispatcher(eventDispatcher);
+ var event = {};
+ nodeFactory.triggerGlobalEvent('window', 'scroll', event);
+ testing_internal_1.expect(eventDispatcher.spy('dispatchRenderEvent'))
+ .toHaveBeenCalledWith(0, 'window:scroll', collection_1.MapWrapper.createFromStringMap({ '$event': event }));
+ testing_internal_1.expect(eventDispatcher.spy('dispatchRenderEvent'))
+ .toHaveBeenCalledWith(1, 'window:scroll', collection_1.MapWrapper.createFromStringMap({ '$event': event }));
+ });
+ });
+ testing_internal_1.describe('nested nodes', function () {
+ testing_internal_1.it('should create nested node', function () {
+ var view = view_factory_1.createRenderView(defaultCmpTpl, [
+ beginElement('a', [], [], false, null),
+ beginElement('b', [], [], false, null),
+ text('someText', false, null),
+ endElement(),
+ endElement(),
+ ], null, nodeFactory);
+ testing_internal_1.expect(stringifyFragment(view.fragments[0].nodes)).toEqual('someText');
+ });
+ testing_internal_1.it('should store bound elements in depth first order', function () {
+ var view = view_factory_1.createRenderView(defaultCmpTpl, [
+ beginElement('a', ['id', '1'], [], false, null),
+ endElement(),
+ beginElement('a', ['id', '2'], [], true, null),
+ beginElement('a', ['id', '3'], [], false, null),
+ endElement(),
+ beginElement('a', ['id', '4'], [], true, null),
+ endElement(),
+ endElement(),
+ beginElement('a', ['id', '5'], [], false, null),
+ endElement(),
+ beginElement('a', ['id', '6'], [], true, null),
+ endElement(),
+ ], null, nodeFactory);
+ testing_internal_1.expect(mapAttrs(view.boundElements, 'id')).toEqual(['2', '4', '6']);
+ });
+ testing_internal_1.it('should store bound text nodes in depth first order', function () {
+ var view = view_factory_1.createRenderView(defaultCmpTpl, [
+ text('1', false, null),
+ text('2', true, null),
+ beginElement('a', [], [], false, null),
+ text('3', false, null),
+ text('4', true, null),
+ endElement(),
+ text('5', false, null),
+ text('6', true, null),
+ ], null, nodeFactory);
+ testing_internal_1.expect(mapText(view.boundTextNodes)).toEqual(['2', '4', '6']);
+ });
+ });
+ testing_internal_1.describe('merged embedded templates', function () {
+ testing_internal_1.it('should create separate fragments', function () {
+ var view = view_factory_1.createRenderView(defaultCmpTpl, [
+ embeddedTemplate(['attr1', 'value1'], true, null, [text('someText', false, null)])
+ ], null, nodeFactory);
+ testing_internal_1.expect(view.fragments.length).toBe(2);
+ testing_internal_1.expect(stringifyFragment(view.fragments[1].nodes)).toEqual('someText');
+ });
+ testing_internal_1.it('should store bound elements after the bound elements of earlier fragments', function () {
+ var view = view_factory_1.createRenderView(defaultCmpTpl, [
+ beginElement('a', ['id', '1.1'], [], true, null),
+ endElement(),
+ embeddedTemplate(['id', '1.2'], true, null, [
+ embeddedTemplate(['id', '2.1'], true, null, [
+ beginElement('a', ['id', '3.1'], [], true, null),
+ endElement()
+ ]),
+ beginElement('a', ['id', '2.2'], [], true, null),
+ endElement(),
+ ]),
+ beginElement('a', ['id', '1.3'], [], true, null),
+ endElement(),
+ ], null, nodeFactory);
+ testing_internal_1.expect(mapAttrs(view.boundElements, 'id'))
+ .toEqual(['1.1', '1.2', '1.3', '2.1', '2.2', '3.1']);
+ });
+ testing_internal_1.it('should store bound text nodes after the bound text nodes of earlier fragments', function () {
+ var view = view_factory_1.createRenderView(defaultCmpTpl, [
+ text('1.1', true, null),
+ embeddedTemplate(['id', '1.2'], true, null, [
+ text('2.1', true, null),
+ embeddedTemplate(['id', '2.1'], true, null, [
+ text('3.1', true, null),
+ ]),
+ text('2.2', true, null),
+ ]),
+ text('1.2', true, null),
+ ], null, nodeFactory);
+ testing_internal_1.expect(mapText(view.boundTextNodes))
+ .toEqual(['1.1', '1.2', '2.1', '2.2', '3.1']);
+ });
+ });
+ testing_internal_1.describe('non merged embedded templates', function () {
+ testing_internal_1.it('should only create the anchor element', function () {
+ var view = view_factory_1.createRenderView(defaultCmpTpl, [
+ embeddedTemplate(['id', '1.1'], false, null, [
+ text('someText', true, null),
+ beginElement('a', ['id', '2.1'], [], true, null),
+ endElement()
+ ])
+ ], null, nodeFactory);
+ testing_internal_1.expect(view.fragments.length).toBe(1);
+ testing_internal_1.expect(stringifyFragment(view.fragments[0].nodes))
+ .toEqual('');
+ testing_internal_1.expect(view.boundTextNodes.length).toBe(0);
+ testing_internal_1.expect(mapAttrs(view.boundElements, 'id')).toEqual(['1.1']);
+ });
+ });
+ testing_internal_1.describe('components', function () {
+ testing_internal_1.it('should store the component template in the same fragment', function () {
+ componentTemplates.set('0', [
+ text('hello', false, null),
+ ]);
+ var view = view_factory_1.createRenderView(defaultCmpTpl, [beginComponent('my-comp', [], [], null, '0'), endComponent()], null, nodeFactory);
+ testing_internal_1.expect(view.fragments.length).toBe(1);
+ testing_internal_1.expect(stringifyFragment(view.fragments[0].nodes)).toEqual('hello');
+ });
+ testing_internal_1.it('should use native shadow DOM', function () {
+ componentTemplates.set('0', new api_1.RenderComponentTemplate('someId', 'shortid', metadata_1.ViewEncapsulation.Native, [
+ text('hello', false, null),
+ ], []));
+ var view = view_factory_1.createRenderView(defaultCmpTpl, [beginComponent('my-comp', [], [], null, '0'), endComponent()], null, nodeFactory);
+ testing_internal_1.expect(view.fragments.length).toBe(1);
+ testing_internal_1.expect(stringifyFragment(view.fragments[0].nodes))
+ .toEqual('hello');
+ });
+ testing_internal_1.it('should store bound elements after the bound elements of the main template', function () {
+ componentTemplates.set('0', [
+ beginComponent('b-comp', ['id', '2.1'], [], null, '1'),
+ endComponent(),
+ beginComponent('b-comp', ['id', '2.2'], [], null, '1'),
+ endComponent(),
+ ]);
+ componentTemplates.set('1', [beginElement('a', ['id', '3.1'], [], true, null), endElement()]);
+ var view = view_factory_1.createRenderView(defaultCmpTpl, [
+ beginElement('a', ['id', '1.1'], [], true, null),
+ endElement(),
+ beginComponent('a-comp', ['id', '1.2'], [], null, '0'),
+ beginElement('a', ['id', '1.3'], [], true, null),
+ endElement(),
+ endComponent(),
+ beginElement('a', ['id', '1.4'], [], true, null),
+ endElement(),
+ ], null, nodeFactory);
+ testing_internal_1.expect(mapAttrs(view.boundElements, 'id'))
+ .toEqual(['1.1', '1.2', '1.3', '1.4', '2.1', '2.2', '3.1', '3.1']);
+ });
+ testing_internal_1.it('should store bound elements from the view before bound elements from content components', function () {
+ componentTemplates.set('0', [
+ beginElement('a', ['id', '2.1'], [], true, null),
+ endElement(),
+ ]);
+ componentTemplates.set('1', [
+ beginElement('a', ['id', '3.1'], [], true, null),
+ endElement(),
+ ]);
+ var view = view_factory_1.createRenderView(defaultCmpTpl, [
+ beginComponent('a-comp', ['id', '1.1'], [], null, '0'),
+ beginComponent('b-comp', ['id', '1.2'], [], null, '1'),
+ endComponent(),
+ endComponent(),
+ ], null, nodeFactory);
+ testing_internal_1.expect(mapAttrs(view.boundElements, 'id')).toEqual(['1.1', '1.2', '2.1', '3.1']);
+ });
+ testing_internal_1.it('should process nested components in depth first order', function () {
+ componentTemplates.set('0', [
+ beginComponent('b11-comp', ['id', '2.1'], [], null, '2'),
+ endComponent(),
+ beginComponent('b12-comp', ['id', '2.2'], [], null, '3'),
+ endComponent(),
+ ]);
+ componentTemplates.set('1', [
+ beginComponent('b21-comp', ['id', '3.1'], [], null, '4'),
+ endComponent(),
+ beginComponent('b22-comp', ['id', '3.2'], [], null, '5'),
+ endComponent(),
+ ]);
+ componentTemplates.set('2', [
+ beginElement('b11', ['id', '4.11'], [], true, null),
+ endElement(),
+ ]);
+ componentTemplates.set('3', [
+ beginElement('b12', ['id', '4.12'], [], true, null),
+ endElement(),
+ ]);
+ componentTemplates.set('4', [
+ beginElement('b21', ['id', '4.21'], [], true, null),
+ endElement(),
+ ]);
+ componentTemplates.set('5', [
+ beginElement('b22', ['id', '4.22'], [], true, null),
+ endElement(),
+ ]);
+ var view = view_factory_1.createRenderView(defaultCmpTpl, [
+ beginComponent('a1-comp', ['id', '1.1'], [], null, '0'),
+ endComponent(),
+ beginComponent('a2-comp', ['id', '1.2'], [], null, '1'),
+ endComponent(),
+ ], null, nodeFactory);
+ testing_internal_1.expect(mapAttrs(view.boundElements, 'id'))
+ .toEqual(['1.1', '1.2', '2.1', '2.2', '4.11', '4.12', '3.1', '3.2', '4.21', '4.22']);
+ });
+ testing_internal_1.it('should store bound text nodes after the bound text nodes of the main template', function () {
+ componentTemplates.set('0', [
+ text('2.1', true, null),
+ beginComponent('b-comp', [], [], null, '1'),
+ endComponent(),
+ beginComponent('b-comp', [], [], null, '1'),
+ endComponent(),
+ text('2.2', true, null),
+ ]);
+ componentTemplates.set('1', [
+ text('3.1', true, null),
+ ]);
+ var view = view_factory_1.createRenderView(defaultCmpTpl, [
+ text('1.1', true, null),
+ beginComponent('a-comp', [], [], null, '0'),
+ text('1.2', true, null),
+ endComponent(),
+ text('1.3', true, null),
+ ], null, nodeFactory);
+ testing_internal_1.expect(mapText(view.boundTextNodes))
+ .toEqual(['1.1', '1.2', '1.3', '2.1', '2.2', '3.1', '3.1']);
+ });
+ });
+ testing_internal_1.it('should store bound text nodes from the view before bound text nodes from content components', function () {
+ componentTemplates.set('0', [text('2.1', true, null)]);
+ componentTemplates.set('1', [text('3.1', true, null)]);
+ var view = view_factory_1.createRenderView(defaultCmpTpl, [
+ beginComponent('a-comp', [], [], null, '0'),
+ beginComponent('b-comp', [], [], null, '1'),
+ endComponent(),
+ endComponent(),
+ ], null, nodeFactory);
+ testing_internal_1.expect(mapText(view.boundTextNodes)).toEqual(['2.1', '3.1']);
+ });
+ testing_internal_1.describe('content projection', function () {
+ testing_internal_1.it('should remove non projected nodes', function () {
+ componentTemplates.set('0', []);
+ var view = view_factory_1.createRenderView(defaultCmpTpl, [
+ beginComponent('my-comp', [], [], null, '0'),
+ text('hello', false, null),
+ endComponent()
+ ], null, nodeFactory);
+ testing_internal_1.expect(stringifyFragment(view.fragments[0].nodes)).toEqual('');
+ });
+ testing_internal_1.it('should keep non projected nodes in the light dom when using native shadow dom', function () {
+ componentTemplates.set('0', new api_1.RenderComponentTemplate('someId', 'shortid', metadata_1.ViewEncapsulation.Native, [], []));
+ var view = view_factory_1.createRenderView(defaultCmpTpl, [
+ beginComponent('my-comp', [], [], null, '0'),
+ text('hello', false, null),
+ endComponent()
+ ], null, nodeFactory);
+ var rootEl = view.fragments[0].nodes[0];
+ testing_internal_1.expect(testing_internal_1.stringifyElement(rootEl))
+ .toEqual('hello');
+ });
+ testing_internal_1.it('should project commands based on their ngContentIndex', function () {
+ componentTemplates.set('0', [
+ text('(', false, null),
+ ngContent(0, null),
+ text(',', false, null),
+ ngContent(1, null),
+ text(')', false, null)
+ ]);
+ var view = view_factory_1.createRenderView(defaultCmpTpl, [
+ beginComponent('my-comp', [], [], null, '0'),
+ text('2', false, 1),
+ text('1', false, 0),
+ endComponent()
+ ], null, nodeFactory);
+ testing_internal_1.expect(stringifyFragment(view.fragments[0].nodes)).toEqual('(1,2)');
+ });
+ testing_internal_1.it('should reproject nodes over multiple ng-content commands', function () {
+ componentTemplates.set('0', [beginComponent('b-comp', [], [], null, '1'), ngContent(0, 0), endComponent()]);
+ componentTemplates.set('1', [text('(', false, null), ngContent(0, null), text(')', false, null)]);
+ var view = view_factory_1.createRenderView(defaultCmpTpl, [beginComponent('a-comp', [], [], null, '0'), text('hello', false, 0), endComponent()], null, nodeFactory);
+ testing_internal_1.expect(stringifyFragment(view.fragments[0].nodes))
+ .toEqual('(hello)');
+ });
+ testing_internal_1.it('should store content injection points for root component in a view', function () {
+ componentTemplates.set('0', [ngContent(0, null)]);
+ var view = view_factory_1.createRenderView(defaultCmpTpl, [beginComponent('a-comp', [], [], null, '0'), endComponent()], dom_adapter_1.DOM.createElement('root'), nodeFactory);
+ testing_internal_1.expect(stringifyFragment(view.rootContentInsertionPoints))
+ .toEqual('');
+ });
+ });
+ testing_internal_1.describe('view encapsulation', function () {
+ testing_internal_1.it('should not add attributes to elements in template with ViewEncapsulation.None', function () {
+ var tpl = new api_1.RenderComponentTemplate('someId', 'shortid', metadata_1.ViewEncapsulation.None, [], []);
+ var view = view_factory_1.createRenderView(tpl, [beginElement('div', [], [], false, null), endElement()], null, nodeFactory);
+ testing_internal_1.expect(stringifyFragment(view.fragments[0].nodes)).toEqual('');
+ });
+ testing_internal_1.it('should not add attributes to elements in template with ViewEncapsulation.Native', function () {
+ var tpl = new api_1.RenderComponentTemplate('someId', 'shortid', metadata_1.ViewEncapsulation.Native, [], []);
+ var view = view_factory_1.createRenderView(tpl, [beginElement('div', [], [], false, null), endElement()], null, nodeFactory);
+ testing_internal_1.expect(stringifyFragment(view.fragments[0].nodes)).toEqual('');
+ });
+ testing_internal_1.describe('ViewEncapsulation.Emulated', function () {
+ var encapsulatedTpl;
+ testing_internal_1.beforeEach(function () {
+ encapsulatedTpl =
+ new api_1.RenderComponentTemplate('someId', 'shortid', metadata_1.ViewEncapsulation.Emulated, [], []);
+ });
+ testing_internal_1.it('should add marker attributes to content elements', function () {
+ var view = view_factory_1.createRenderView(encapsulatedTpl, [beginElement('div', [], [], false, null), endElement()], null, nodeFactory);
+ testing_internal_1.expect(stringifyFragment(view.fragments[0].nodes))
+ .toEqual('');
+ });
+ testing_internal_1.it('should add marker attributes to content elements in merged embedded templates', function () {
+ var view = view_factory_1.createRenderView(encapsulatedTpl, [
+ embeddedTemplate([], true, null, [beginElement('div', [], [], false, null), endElement()])
+ ], null, nodeFactory);
+ testing_internal_1.expect(stringifyFragment(view.fragments[0].nodes)).toEqual('');
+ testing_internal_1.expect(stringifyFragment(view.fragments[1].nodes))
+ .toEqual('');
+ });
+ testing_internal_1.it('should add marker attributes to host elements and content elements of nested components', function () {
+ componentTemplates.set('0', new api_1.RenderComponentTemplate('innerComp', 'innerid', metadata_1.ViewEncapsulation.Emulated, [beginElement('div', [], [], false, null), endElement()], []));
+ var view = view_factory_1.createRenderView(encapsulatedTpl, [beginComponent('my-comp', [], [], null, '0'), endComponent()], null, nodeFactory);
+ testing_internal_1.expect(stringifyFragment(view.fragments[0].nodes))
+ .toEqual('');
+ });
+ });
+ });
+ });
+ testing_internal_1.describe('encapsulateStyles', function () {
+ var input = 'div[%COMP%] {}';
+ testing_internal_1.it('should not change styles for ViewEncapsulation.Native', function () {
+ var tpl = new api_1.RenderComponentTemplate('someId', 'shortid', metadata_1.ViewEncapsulation.Native, [], [input]);
+ testing_internal_1.expect(view_factory_1.encapsulateStyles(tpl)).toEqual([input]);
+ });
+ testing_internal_1.it('should not change styles for ViewEncapsulation.None', function () {
+ var tpl = new api_1.RenderComponentTemplate('someId', 'shortid', metadata_1.ViewEncapsulation.None, [], [input]);
+ testing_internal_1.expect(view_factory_1.encapsulateStyles(tpl)).toEqual([input]);
+ });
+ testing_internal_1.it('should change styles for ViewEncapsulation.Emulated', function () {
+ var tpl = new api_1.RenderComponentTemplate('someId', 'shortid', metadata_1.ViewEncapsulation.Emulated, [], [input]);
+ testing_internal_1.expect(view_factory_1.encapsulateStyles(tpl)).toEqual(['div[shortid] {}']);
+ });
+ });
+}
+exports.main = main;
+var DomNodeFactory = (function () {
+ function DomNodeFactory(_components) {
+ this._components = _components;
+ this._globalEventListeners = [];
+ this._localEventListeners = [];
+ }
+ DomNodeFactory.prototype.triggerLocalEvent = function (el, eventName, event) {
+ this._localEventListeners.forEach(function (listener) {
+ if (listener.eventName == eventName) {
+ listener.callback(event);
+ }
+ });
+ };
+ DomNodeFactory.prototype.triggerGlobalEvent = function (target, eventName, event) {
+ this._globalEventListeners.forEach(function (listener) {
+ if (listener.eventName == eventName && listener.target == target) {
+ listener.callback(event);
+ }
+ });
+ };
+ DomNodeFactory.prototype.resolveComponentTemplate = function (templateId) {
+ var data = this._components.get(templateId);
+ if (data instanceof api_1.RenderComponentTemplate) {
+ return data;
+ }
+ else {
+ return new api_1.RenderComponentTemplate(templateId, templateId, metadata_1.ViewEncapsulation.None, data, []);
+ }
+ };
+ DomNodeFactory.prototype.createTemplateAnchor = function (attrNameAndValues) {
+ var el = dom_adapter_1.DOM.createElement('template');
+ this._setAttributes(el, attrNameAndValues);
+ return el;
+ };
+ DomNodeFactory.prototype.createElement = function (name, attrNameAndValues) {
+ var el = dom_adapter_1.DOM.createElement(name);
+ this._setAttributes(el, attrNameAndValues);
+ return el;
+ };
+ DomNodeFactory.prototype.mergeElement = function (existing, attrNameAndValues) {
+ dom_adapter_1.DOM.clearNodes(existing);
+ this._setAttributes(existing, attrNameAndValues);
+ };
+ DomNodeFactory.prototype._setAttributes = function (el, attrNameAndValues) {
+ for (var attrIdx = 0; attrIdx < attrNameAndValues.length; attrIdx += 2) {
+ dom_adapter_1.DOM.setAttribute(el, attrNameAndValues[attrIdx], attrNameAndValues[attrIdx + 1]);
+ }
+ };
+ DomNodeFactory.prototype.createShadowRoot = function (host, templateId) {
+ var root = dom_adapter_1.DOM.createElement('shadow-root');
+ dom_adapter_1.DOM.appendChild(host, root);
+ return root;
+ };
+ DomNodeFactory.prototype.createText = function (value) { return dom_adapter_1.DOM.createTextNode(lang_1.isPresent(value) ? value : ''); };
+ DomNodeFactory.prototype.createRootContentInsertionPoint = function () {
+ return dom_adapter_1.DOM.createElement('root-content-insertion-point');
+ };
+ DomNodeFactory.prototype.appendChild = function (parent, child) { dom_adapter_1.DOM.appendChild(parent, child); };
+ DomNodeFactory.prototype.on = function (element, eventName, callback) {
+ this._localEventListeners.push(new LocalEventListener(element, eventName, callback));
+ };
+ DomNodeFactory.prototype.globalOn = function (target, eventName, callback) {
+ var _this = this;
+ var listener = new GlobalEventListener(target, eventName, callback);
+ this._globalEventListeners.push(listener);
+ return function () {
+ var index = _this._globalEventListeners.indexOf(listener);
+ if (index !== -1) {
+ _this._globalEventListeners.splice(index, 1);
+ }
+ };
+ };
+ return DomNodeFactory;
+})();
+var LocalEventListener = (function () {
+ function LocalEventListener(element, eventName, callback) {
+ this.element = element;
+ this.eventName = eventName;
+ this.callback = callback;
+ }
+ return LocalEventListener;
+})();
+var GlobalEventListener = (function () {
+ function GlobalEventListener(target, eventName, callback) {
+ this.target = target;
+ this.eventName = eventName;
+ this.callback = callback;
+ }
+ return GlobalEventListener;
+})();
+function stringifyFragment(nodes) {
+ return nodes.map(testing_internal_1.stringifyElement).join('');
+}
+function mapAttrs(nodes, attrName) {
+ return nodes.map(function (node) { return dom_adapter_1.DOM.getAttribute(node, attrName); });
+}
+function mapText(nodes) {
+ return nodes.map(function (node) { return dom_adapter_1.DOM.getText(node); });
+}
+//# sourceMappingURL=view_factory_spec.js.map
\ No newline at end of file
diff --git a/test/core/render/view_spec.js b/test/core/render/view_spec.js
new file mode 100644
index 00000000000..728d97c9f1d
--- /dev/null
+++ b/test/core/render/view_spec.js
@@ -0,0 +1,27 @@
+var testing_internal_1 = require('angular2/testing_internal');
+var view_1 = require('angular2/src/core/render/view');
+function main() {
+ testing_internal_1.describe('DefaultRenderView', function () {
+ testing_internal_1.describe('hydrate', function () {
+ testing_internal_1.it('should register global event listeners', function () {
+ var addCount = 0;
+ var adder = function () { addCount++; };
+ var view = new view_1.DefaultRenderView([], [], [], [], [adder], []);
+ view.hydrate();
+ testing_internal_1.expect(addCount).toBe(1);
+ });
+ });
+ testing_internal_1.describe('dehydrate', function () {
+ testing_internal_1.it('should deregister global event listeners', function () {
+ var removeCount = 0;
+ var adder = function () { return function () { removeCount++; }; };
+ var view = new view_1.DefaultRenderView([], [], [], [], [adder], []);
+ view.hydrate();
+ view.dehydrate();
+ testing_internal_1.expect(removeCount).toBe(1);
+ });
+ });
+ });
+}
+exports.main = main;
+//# sourceMappingURL=view_spec.js.map
\ No newline at end of file
diff --git a/test/core/services/rectangle_mock.js b/test/core/services/rectangle_mock.js
new file mode 100644
index 00000000000..8e4911b23d6
--- /dev/null
+++ b/test/core/services/rectangle_mock.js
@@ -0,0 +1,5 @@
+function createRectangle(left, top, width, height) {
+ return { left: left, top: top, width: width, height: height };
+}
+exports.createRectangle = createRectangle;
+//# sourceMappingURL=rectangle_mock.js.map
\ No newline at end of file
diff --git a/test/core/services/ruler_spec.js b/test/core/services/ruler_spec.js
new file mode 100644
index 00000000000..3f36d17558c
--- /dev/null
+++ b/test/core/services/ruler_spec.js
@@ -0,0 +1,38 @@
+var testing_internal_1 = require('angular2/testing_internal');
+var spies_1 = require('../spies');
+var dom_adapter_1 = require('angular2/src/core/dom/dom_adapter');
+var ruler_1 = require('angular2/src/core/services/ruler');
+var rectangle_mock_1 = require('./rectangle_mock');
+function assertDimensions(rect, left, right, top, bottom, width, height) {
+ testing_internal_1.expect(rect.left).toEqual(left);
+ testing_internal_1.expect(rect.right).toEqual(right);
+ testing_internal_1.expect(rect.top).toEqual(top);
+ testing_internal_1.expect(rect.bottom).toEqual(bottom);
+ testing_internal_1.expect(rect.width).toEqual(width);
+ testing_internal_1.expect(rect.height).toEqual(height);
+}
+function main() {
+ testing_internal_1.describe('ruler service', function () {
+ testing_internal_1.it('should allow measuring ElementRefs', testing_internal_1.inject([testing_internal_1.AsyncTestCompleter], function (async) {
+ var ruler = new ruler_1.Ruler(testing_internal_1.SpyObject.stub(new spies_1.SpyDomAdapter(), { 'getBoundingClientRect': rectangle_mock_1.createRectangle(10, 20, 200, 100) }));
+ var elRef = new spies_1.SpyElementRef();
+ ruler.measure(elRef).then(function (rect) {
+ assertDimensions(rect, 10, 210, 20, 120, 200, 100);
+ async.done();
+ });
+ }));
+ testing_internal_1.it('should return 0 for all rectangle values while measuring elements in a document fragment', testing_internal_1.inject([testing_internal_1.AsyncTestCompleter], function (async) {
+ var ruler = new ruler_1.Ruler(dom_adapter_1.DOM);
+ var elRef = new spies_1.SpyElementRef();
+ elRef.prop("nativeElement", dom_adapter_1.DOM.createElement('div'));
+ ruler.measure(elRef).then(function (rect) {
+ // here we are using an element created in a doc fragment so all the measures will come
+ // back as 0
+ assertDimensions(rect, 0, 0, 0, 0, 0, 0);
+ async.done();
+ });
+ }));
+ });
+}
+exports.main = main;
+//# sourceMappingURL=ruler_spec.js.map
\ No newline at end of file
diff --git a/test/core/services/title_spec.js b/test/core/services/title_spec.js
new file mode 100644
index 00000000000..08efb16ff1a
--- /dev/null
+++ b/test/core/services/title_spec.js
@@ -0,0 +1,22 @@
+var testing_internal_1 = require('angular2/testing_internal');
+var dom_adapter_1 = require('angular2/src/core/dom/dom_adapter');
+var title_1 = require('angular2/src/core/services/title');
+function main() {
+ testing_internal_1.describe('title service', function () {
+ var initialTitle = dom_adapter_1.DOM.getTitle();
+ var titleService = new title_1.Title();
+ testing_internal_1.afterEach(function () { dom_adapter_1.DOM.setTitle(initialTitle); });
+ testing_internal_1.it('should allow reading initial title', function () { testing_internal_1.expect(titleService.getTitle()).toEqual(initialTitle); });
+ testing_internal_1.it('should set a title on the injected document', function () {
+ titleService.setTitle('test title');
+ testing_internal_1.expect(dom_adapter_1.DOM.getTitle()).toEqual('test title');
+ testing_internal_1.expect(titleService.getTitle()).toEqual('test title');
+ });
+ testing_internal_1.it('should reset title to empty string if title not provided', function () {
+ titleService.setTitle(null);
+ testing_internal_1.expect(dom_adapter_1.DOM.getTitle()).toEqual('');
+ });
+ });
+}
+exports.main = main;
+//# sourceMappingURL=title_spec.js.map
\ No newline at end of file
diff --git a/test/core/spies.js b/test/core/spies.js
new file mode 100644
index 00000000000..9fb6db23eeb
--- /dev/null
+++ b/test/core/spies.js
@@ -0,0 +1,170 @@
+var __extends = (this && this.__extends) || function (d, b) {
+ for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
+ function __() { this.constructor = d; }
+ d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
+};
+var change_detection_1 = require('angular2/src/core/change_detection/change_detection');
+var api_1 = require('angular2/src/core/render/api');
+var directive_resolver_1 = require('angular2/src/core/linker/directive_resolver');
+var view_1 = require('angular2/src/core/linker/view');
+var element_ref_1 = require('angular2/src/core/linker/element_ref');
+var view_manager_1 = require('angular2/src/core/linker/view_manager');
+var view_pool_1 = require('angular2/src/core/linker/view_pool');
+var view_listener_1 = require('angular2/src/core/linker/view_listener');
+var proto_view_factory_1 = require('angular2/src/core/linker/proto_view_factory');
+var dom_adapter_1 = require('angular2/src/core/dom/dom_adapter');
+var element_injector_1 = require('angular2/src/core/linker/element_injector');
+var testing_internal_1 = require('angular2/testing_internal');
+var SpyDependencyProvider = (function (_super) {
+ __extends(SpyDependencyProvider, _super);
+ function SpyDependencyProvider() {
+ _super.apply(this, arguments);
+ }
+ return SpyDependencyProvider;
+})(testing_internal_1.SpyObject);
+exports.SpyDependencyProvider = SpyDependencyProvider;
+var SpyChangeDetector = (function (_super) {
+ __extends(SpyChangeDetector, _super);
+ function SpyChangeDetector() {
+ _super.call(this, change_detection_1.DynamicChangeDetector);
+ }
+ return SpyChangeDetector;
+})(testing_internal_1.SpyObject);
+exports.SpyChangeDetector = SpyChangeDetector;
+var SpyChangeDispatcher = (function (_super) {
+ __extends(SpyChangeDispatcher, _super);
+ function SpyChangeDispatcher() {
+ _super.apply(this, arguments);
+ }
+ return SpyChangeDispatcher;
+})(testing_internal_1.SpyObject);
+exports.SpyChangeDispatcher = SpyChangeDispatcher;
+var SpyIterableDifferFactory = (function (_super) {
+ __extends(SpyIterableDifferFactory, _super);
+ function SpyIterableDifferFactory() {
+ _super.apply(this, arguments);
+ }
+ return SpyIterableDifferFactory;
+})(testing_internal_1.SpyObject);
+exports.SpyIterableDifferFactory = SpyIterableDifferFactory;
+var SpyDirectiveResolver = (function (_super) {
+ __extends(SpyDirectiveResolver, _super);
+ function SpyDirectiveResolver() {
+ _super.call(this, directive_resolver_1.DirectiveResolver);
+ }
+ return SpyDirectiveResolver;
+})(testing_internal_1.SpyObject);
+exports.SpyDirectiveResolver = SpyDirectiveResolver;
+var SpyView = (function (_super) {
+ __extends(SpyView, _super);
+ function SpyView() {
+ _super.call(this, view_1.AppView);
+ }
+ return SpyView;
+})(testing_internal_1.SpyObject);
+exports.SpyView = SpyView;
+var SpyElementRef = (function (_super) {
+ __extends(SpyElementRef, _super);
+ function SpyElementRef() {
+ _super.call(this, element_ref_1.ElementRef);
+ }
+ return SpyElementRef;
+})(testing_internal_1.SpyObject);
+exports.SpyElementRef = SpyElementRef;
+var SpyAppViewManager = (function (_super) {
+ __extends(SpyAppViewManager, _super);
+ function SpyAppViewManager() {
+ _super.call(this, view_manager_1.AppViewManager);
+ }
+ return SpyAppViewManager;
+})(testing_internal_1.SpyObject);
+exports.SpyAppViewManager = SpyAppViewManager;
+var SpyRenderer = (function (_super) {
+ __extends(SpyRenderer, _super);
+ function SpyRenderer() {
+ // Note: Renderer is an abstract class,
+ // so we can't generates spy functions automatically
+ // by inspecting the prototype...
+ _super.call(this, api_1.Renderer);
+ this.spy('setEventDispatcher');
+ this.spy('destroyView');
+ this.spy('createView');
+ this.spy('createProtoView');
+ this.spy('hydrateView');
+ this.spy('dehydrateView');
+ this.spy('attachFragmentAfterElement');
+ this.spy('attachFragmentAfterFragment');
+ this.spy('detachFragment');
+ }
+ return SpyRenderer;
+})(testing_internal_1.SpyObject);
+exports.SpyRenderer = SpyRenderer;
+var SpyAppViewPool = (function (_super) {
+ __extends(SpyAppViewPool, _super);
+ function SpyAppViewPool() {
+ _super.call(this, view_pool_1.AppViewPool);
+ }
+ return SpyAppViewPool;
+})(testing_internal_1.SpyObject);
+exports.SpyAppViewPool = SpyAppViewPool;
+var SpyAppViewListener = (function (_super) {
+ __extends(SpyAppViewListener, _super);
+ function SpyAppViewListener() {
+ _super.call(this, view_listener_1.AppViewListener);
+ }
+ return SpyAppViewListener;
+})(testing_internal_1.SpyObject);
+exports.SpyAppViewListener = SpyAppViewListener;
+var SpyProtoViewFactory = (function (_super) {
+ __extends(SpyProtoViewFactory, _super);
+ function SpyProtoViewFactory() {
+ _super.call(this, proto_view_factory_1.ProtoViewFactory);
+ }
+ return SpyProtoViewFactory;
+})(testing_internal_1.SpyObject);
+exports.SpyProtoViewFactory = SpyProtoViewFactory;
+var SpyProtoElementInjector = (function (_super) {
+ __extends(SpyProtoElementInjector, _super);
+ function SpyProtoElementInjector() {
+ _super.call(this, element_injector_1.ProtoElementInjector);
+ }
+ return SpyProtoElementInjector;
+})(testing_internal_1.SpyObject);
+exports.SpyProtoElementInjector = SpyProtoElementInjector;
+var SpyElementInjector = (function (_super) {
+ __extends(SpyElementInjector, _super);
+ function SpyElementInjector() {
+ _super.call(this, element_injector_1.ElementInjector);
+ }
+ return SpyElementInjector;
+})(testing_internal_1.SpyObject);
+exports.SpyElementInjector = SpyElementInjector;
+var SpyPreBuiltObjects = (function (_super) {
+ __extends(SpyPreBuiltObjects, _super);
+ function SpyPreBuiltObjects() {
+ _super.call(this, element_injector_1.PreBuiltObjects);
+ }
+ return SpyPreBuiltObjects;
+})(testing_internal_1.SpyObject);
+exports.SpyPreBuiltObjects = SpyPreBuiltObjects;
+var SpyDomAdapter = (function (_super) {
+ __extends(SpyDomAdapter, _super);
+ function SpyDomAdapter() {
+ _super.call(this, dom_adapter_1.DomAdapter);
+ }
+ return SpyDomAdapter;
+})(testing_internal_1.SpyObject);
+exports.SpyDomAdapter = SpyDomAdapter;
+var SpyRenderEventDispatcher = (function (_super) {
+ __extends(SpyRenderEventDispatcher, _super);
+ function SpyRenderEventDispatcher() {
+ // Note: RenderEventDispatcher is an interface,
+ // so we can't pass it to super() and have to register
+ // the spy methods on our own.
+ _super.call(this);
+ this.spy('dispatchRenderEvent');
+ }
+ return SpyRenderEventDispatcher;
+})(testing_internal_1.SpyObject);
+exports.SpyRenderEventDispatcher = SpyRenderEventDispatcher;
+//# sourceMappingURL=spies.js.map
\ No newline at end of file
diff --git a/test/core/testability/testability_spec.js b/test/core/testability/testability_spec.js
new file mode 100644
index 00000000000..3a8f2af279f
--- /dev/null
+++ b/test/core/testability/testability_spec.js
@@ -0,0 +1,166 @@
+var __extends = (this && this.__extends) || function (d, b) {
+ for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
+ function __() { this.constructor = d; }
+ d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
+};
+var testing_internal_1 = require('angular2/testing_internal');
+var testability_1 = require('angular2/src/core/testability/testability');
+var ng_zone_1 = require('angular2/src/core/zone/ng_zone');
+var async_1 = require('angular2/src/facade/async');
+// Schedules a microtasks (using a resolved promise .then())
+function microTask(fn) {
+ async_1.PromiseWrapper.resolve(null).then(function (_) { fn(); });
+}
+var MockNgZone = (function (_super) {
+ __extends(MockNgZone, _super);
+ function MockNgZone() {
+ _super.call(this, { enableLongStackTrace: false });
+ this._onTurnStartStream = new async_1.EventEmitter(false);
+ this._onEventDoneStream = new async_1.EventEmitter(false);
+ }
+ Object.defineProperty(MockNgZone.prototype, "onTurnStart", {
+ get: function () { return this._onTurnStartStream; },
+ enumerable: true,
+ configurable: true
+ });
+ Object.defineProperty(MockNgZone.prototype, "onEventDone", {
+ get: function () { return this._onEventDoneStream; },
+ enumerable: true,
+ configurable: true
+ });
+ MockNgZone.prototype.start = function () { async_1.ObservableWrapper.callNext(this._onTurnStartStream, null); };
+ MockNgZone.prototype.finish = function () { async_1.ObservableWrapper.callNext(this._onEventDoneStream, null); };
+ return MockNgZone;
+})(ng_zone_1.NgZone);
+function main() {
+ testing_internal_1.describe('Testability', function () {
+ var testability, execute, ngZone;
+ testing_internal_1.beforeEach(function () {
+ ngZone = new MockNgZone();
+ testability = new testability_1.Testability(ngZone);
+ execute = new testing_internal_1.SpyObject().spy('execute');
+ });
+ testing_internal_1.describe('Pending count logic', function () {
+ testing_internal_1.it('should start with a pending count of 0', function () { testing_internal_1.expect(testability.getPendingRequestCount()).toEqual(0); });
+ testing_internal_1.it('should fire whenstable callbacks if pending count is 0', testing_internal_1.inject([testing_internal_1.AsyncTestCompleter], function (async) {
+ testability.whenStable(execute);
+ microTask(function () {
+ testing_internal_1.expect(execute).toHaveBeenCalled();
+ async.done();
+ });
+ }));
+ testing_internal_1.it('should not fire whenstable callbacks synchronously if pending count is 0', function () {
+ testability.whenStable(execute);
+ testing_internal_1.expect(execute).not.toHaveBeenCalled();
+ });
+ testing_internal_1.it('should not call whenstable callbacks when there are pending counts', testing_internal_1.inject([testing_internal_1.AsyncTestCompleter], function (async) {
+ testability.increasePendingRequestCount();
+ testability.increasePendingRequestCount();
+ testability.whenStable(execute);
+ microTask(function () {
+ testing_internal_1.expect(execute).not.toHaveBeenCalled();
+ testability.decreasePendingRequestCount();
+ microTask(function () {
+ testing_internal_1.expect(execute).not.toHaveBeenCalled();
+ async.done();
+ });
+ });
+ }));
+ testing_internal_1.it('should fire whenstable callbacks when pending drops to 0', testing_internal_1.inject([testing_internal_1.AsyncTestCompleter], function (async) {
+ testability.increasePendingRequestCount();
+ testability.whenStable(execute);
+ microTask(function () {
+ testing_internal_1.expect(execute).not.toHaveBeenCalled();
+ testability.decreasePendingRequestCount();
+ microTask(function () {
+ testing_internal_1.expect(execute).toHaveBeenCalled();
+ async.done();
+ });
+ });
+ }));
+ testing_internal_1.it('should not fire whenstable callbacks synchronously when pending drops to 0', function () {
+ testability.increasePendingRequestCount();
+ testability.whenStable(execute);
+ testability.decreasePendingRequestCount();
+ testing_internal_1.expect(execute).not.toHaveBeenCalled();
+ });
+ });
+ testing_internal_1.describe('NgZone callback logic', function () {
+ testing_internal_1.it('should start being ready', function () { testing_internal_1.expect(testability.isAngularEventPending()).toEqual(false); });
+ testing_internal_1.it('should fire whenstable callback if event is already finished', testing_internal_1.inject([testing_internal_1.AsyncTestCompleter], function (async) {
+ ngZone.start();
+ ngZone.finish();
+ testability.whenStable(execute);
+ microTask(function () {
+ testing_internal_1.expect(execute).toHaveBeenCalled();
+ async.done();
+ });
+ }));
+ testing_internal_1.it('should not fire whenstable callbacks synchronously if event is already finished', function () {
+ ngZone.start();
+ ngZone.finish();
+ testability.whenStable(execute);
+ testing_internal_1.expect(execute).not.toHaveBeenCalled();
+ });
+ testing_internal_1.it('should fire whenstable callback when event finishes', testing_internal_1.inject([testing_internal_1.AsyncTestCompleter], function (async) {
+ ngZone.start();
+ testability.whenStable(execute);
+ microTask(function () {
+ testing_internal_1.expect(execute).not.toHaveBeenCalled();
+ ngZone.finish();
+ microTask(function () {
+ testing_internal_1.expect(execute).toHaveBeenCalled();
+ async.done();
+ });
+ });
+ }));
+ testing_internal_1.it('should not fire whenstable callbacks synchronously when event finishes', function () {
+ ngZone.start();
+ testability.whenStable(execute);
+ ngZone.finish();
+ testing_internal_1.expect(execute).not.toHaveBeenCalled();
+ });
+ testing_internal_1.it('should not fire whenstable callback when event did not finish', testing_internal_1.inject([testing_internal_1.AsyncTestCompleter], function (async) {
+ ngZone.start();
+ testability.increasePendingRequestCount();
+ testability.whenStable(execute);
+ microTask(function () {
+ testing_internal_1.expect(execute).not.toHaveBeenCalled();
+ testability.decreasePendingRequestCount();
+ microTask(function () {
+ testing_internal_1.expect(execute).not.toHaveBeenCalled();
+ ngZone.finish();
+ microTask(function () {
+ testing_internal_1.expect(execute).toHaveBeenCalled();
+ async.done();
+ });
+ });
+ });
+ }));
+ testing_internal_1.it('should not fire whenstable callback when there are pending counts', testing_internal_1.inject([testing_internal_1.AsyncTestCompleter], function (async) {
+ ngZone.start();
+ testability.increasePendingRequestCount();
+ testability.increasePendingRequestCount();
+ testability.whenStable(execute);
+ microTask(function () {
+ testing_internal_1.expect(execute).not.toHaveBeenCalled();
+ ngZone.finish();
+ microTask(function () {
+ testing_internal_1.expect(execute).not.toHaveBeenCalled();
+ testability.decreasePendingRequestCount();
+ microTask(function () {
+ testing_internal_1.expect(execute).not.toHaveBeenCalled();
+ testability.decreasePendingRequestCount();
+ microTask(function () {
+ testing_internal_1.expect(execute).toHaveBeenCalled();
+ async.done();
+ });
+ });
+ });
+ });
+ }));
+ });
+ });
+}
+exports.main = main;
+//# sourceMappingURL=testability_spec.js.map
\ No newline at end of file
diff --git a/test/core/util/decorators_spec.js b/test/core/util/decorators_spec.js
new file mode 100644
index 00000000000..475966e55ad
--- /dev/null
+++ b/test/core/util/decorators_spec.js
@@ -0,0 +1,121 @@
+var __extends = (this && this.__extends) || function (d, b) {
+ for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
+ function __() { this.constructor = d; }
+ d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
+};
+var testing_internal_1 = require('angular2/testing_internal');
+var decorators_1 = require('angular2/src/core/util/decorators');
+var lang_1 = require('angular2/src/facade/lang');
+var angular2_1 = require('angular2/angular2');
+var reflection_1 = require('angular2/src/core/reflection/reflection');
+var TestAnnotation = (function () {
+ function TestAnnotation(arg) {
+ this.arg = arg;
+ }
+ return TestAnnotation;
+})();
+var TerminalAnnotation = (function () {
+ function TerminalAnnotation() {
+ this.terminal = true;
+ }
+ return TerminalAnnotation;
+})();
+var DecoratedParent = (function () {
+ function DecoratedParent() {
+ }
+ return DecoratedParent;
+})();
+var DecoratedChild = (function (_super) {
+ __extends(DecoratedChild, _super);
+ function DecoratedChild() {
+ _super.apply(this, arguments);
+ }
+ return DecoratedChild;
+})(DecoratedParent);
+function main() {
+ var Reflect = lang_1.global.Reflect;
+ var TerminalDecorator = decorators_1.makeDecorator(TerminalAnnotation);
+ var TestDecorator = decorators_1.makeDecorator(TestAnnotation, function (fn) { return fn.Terminal = TerminalDecorator; });
+ testing_internal_1.describe('decorators', function () {
+ testing_internal_1.it('should invoke as decorator', function () {
+ function Type() { }
+ TestDecorator({ marker: 'WORKS' })(Type);
+ var annotations = Reflect.getMetadata('annotations', Type);
+ testing_internal_1.expect(annotations[0].arg.marker).toEqual('WORKS');
+ });
+ testing_internal_1.it('should invoke as new', function () {
+ var annotation = new TestDecorator({ marker: 'WORKS' });
+ testing_internal_1.expect(annotation instanceof TestAnnotation).toEqual(true);
+ testing_internal_1.expect(annotation.arg.marker).toEqual('WORKS');
+ });
+ testing_internal_1.it('should invoke as chain', function () {
+ var chain = TestDecorator({ marker: 'WORKS' });
+ testing_internal_1.expect(typeof chain.Terminal).toEqual('function');
+ chain = chain.Terminal();
+ testing_internal_1.expect(chain.annotations[0] instanceof TestAnnotation).toEqual(true);
+ testing_internal_1.expect(chain.annotations[0].arg.marker).toEqual('WORKS');
+ testing_internal_1.expect(chain.annotations[1] instanceof TerminalAnnotation).toEqual(true);
+ });
+ testing_internal_1.it('should not apply decorators from the prototype chain', function () {
+ TestDecorator({ marker: 'parent' })(DecoratedParent);
+ TestDecorator({ marker: 'child' })(DecoratedChild);
+ var annotations = Reflect.getOwnMetadata('annotations', DecoratedChild);
+ testing_internal_1.expect(annotations.length).toBe(1);
+ testing_internal_1.expect(annotations[0].arg.marker).toEqual('child');
+ });
+ testing_internal_1.describe('Class', function () {
+ testing_internal_1.it('should create a class', function () {
+ var i0, i1;
+ var MyClass = TestDecorator('test-works')
+ .Class({
+ extends: decorators_1.Class({
+ constructor: function () { },
+ extendWorks: function () { return 'extend ' + this.arg; }
+ }),
+ constructor: [String, function (arg) { this.arg = arg; }],
+ methodA: [i0 = new angular2_1.Inject(String), [i1 = angular2_1.Inject(String), Number], function (a, b) { }],
+ works: function () { return this.arg; },
+ prototype: 'IGNORE'
+ });
+ var obj = new MyClass('WORKS');
+ testing_internal_1.expect(obj.arg).toEqual('WORKS');
+ testing_internal_1.expect(obj.works()).toEqual('WORKS');
+ testing_internal_1.expect(obj.extendWorks()).toEqual('extend WORKS');
+ testing_internal_1.expect(reflection_1.reflector.parameters(MyClass)).toEqual([[String]]);
+ testing_internal_1.expect(reflection_1.reflector.parameters(obj.methodA)).toEqual([[i0], [i1.annotation, Number]]);
+ var proto = MyClass.prototype;
+ testing_internal_1.expect(proto.extends).toEqual(undefined);
+ testing_internal_1.expect(proto.prototype).toEqual(undefined);
+ testing_internal_1.expect(reflection_1.reflector.annotations(MyClass)[0].arg).toEqual('test-works');
+ });
+ testing_internal_1.describe('errors', function () {
+ testing_internal_1.it('should ensure that last constructor is required', function () {
+ testing_internal_1.expect(function () { decorators_1.Class({}); })
+ .toThrowError("Only Function or Array is supported in Class definition for key 'constructor' is 'undefined'");
+ });
+ testing_internal_1.it('should ensure that we dont accidently patch native objects', function () {
+ testing_internal_1.expect(function () { decorators_1.Class({ constructor: Object }); })
+ .toThrowError("Can not use native Object as constructor");
+ });
+ testing_internal_1.it('should ensure that last possition is function', function () {
+ testing_internal_1.expect(function () { decorators_1.Class({ constructor: [] }); })
+ .toThrowError("Last position of Class method array must be Function in key constructor was 'undefined'");
+ });
+ testing_internal_1.it('should ensure that annotation count matches paramaters count', function () {
+ testing_internal_1.expect(function () { decorators_1.Class({ constructor: [String, function MyType() { }] }); })
+ .toThrowError("Number of annotations (1) does not match number of arguments (0) in the function: MyType");
+ });
+ testing_internal_1.it('should ensure that only Function|Arrays are supported', function () {
+ testing_internal_1.expect(function () { decorators_1.Class({ constructor: function () { }, method: 'non_function' }); })
+ .toThrowError("Only Function or Array is supported in Class definition for key 'method' is 'non_function'");
+ });
+ testing_internal_1.it('should ensure that extends is a Function', function () {
+ testing_internal_1.expect(function () { decorators_1.Class({ extends: 'non_type', constructor: function () { } }); })
+ .toThrowError("Class definition 'extends' property must be a constructor function was: non_type");
+ });
+ });
+ });
+ });
+}
+exports.main = main;
+//# sourceMappingURL=decorators_spec.js.map
\ No newline at end of file
diff --git a/test/core/zone/ng_zone_DEPRECATED_spec.js b/test/core/zone/ng_zone_DEPRECATED_spec.js
new file mode 100644
index 00000000000..b396c396df5
--- /dev/null
+++ b/test/core/zone/ng_zone_DEPRECATED_spec.js
@@ -0,0 +1,515 @@
+// TODO(yjbanov): this file tests the deprecated NgZone API. Delete it when
+// the old API is cleaned up.
+var test_lib_1 = require('angular2/test_lib');
+var async_1 = require('angular2/src/facade/async');
+var exceptions_1 = require('angular2/src/facade/exceptions');
+var ng_zone_1 = require('angular2/src/core/zone/ng_zone');
+var needsLongerTimers = test_lib_1.browserDetection.isSlow || test_lib_1.browserDetection.isEdge;
+var resultTimer = 1000;
+var testTimeout = test_lib_1.browserDetection.isEdge ? 1200 : 100;
+// Schedules a macrotask (using a timer)
+function macroTask(fn, timer) {
+ if (timer === void 0) { timer = 1; }
+ // adds longer timers for passing tests in IE and Edge
+ _zone.runOutsideAngular(function () { return async_1.TimerWrapper.setTimeout(fn, needsLongerTimers ? timer : 1); });
+}
+// Schedules a microtasks (using a resolved promise .then())
+function microTask(fn) {
+ async_1.PromiseWrapper.resolve(null).then(function (_) { fn(); });
+}
+var _log;
+var _errors;
+var _traces;
+var _zone;
+function logError(error, stackTrace) {
+ _errors.push(error);
+ _traces.push(stackTrace);
+}
+function main() {
+ test_lib_1.describe("NgZone", function () {
+ function createZone(enableLongStackTrace) {
+ var zone = new ng_zone_1.NgZone({ enableLongStackTrace: enableLongStackTrace });
+ zone.overrideOnTurnStart(_log.fn('onTurnStart'));
+ zone.overrideOnTurnDone(_log.fn('onTurnDone'));
+ return zone;
+ }
+ test_lib_1.beforeEach(function () {
+ _log = new test_lib_1.Log();
+ _errors = [];
+ _traces = [];
+ });
+ test_lib_1.describe('long stack trace', function () {
+ test_lib_1.beforeEach(function () { _zone = createZone(true); });
+ commonTests();
+ test_lib_1.it('should produce long stack traces', test_lib_1.inject([test_lib_1.AsyncTestCompleter], function (async) {
+ macroTask(function () {
+ _zone.overrideOnErrorHandler(logError);
+ var c = async_1.PromiseWrapper.completer();
+ _zone.run(function () {
+ async_1.TimerWrapper.setTimeout(function () {
+ async_1.TimerWrapper.setTimeout(function () {
+ c.resolve(null);
+ throw new exceptions_1.BaseException('ccc');
+ }, 0);
+ }, 0);
+ });
+ c.promise.then(function (_) {
+ test_lib_1.expect(_traces.length).toBe(1);
+ test_lib_1.expect(_traces[0].length).toBeGreaterThan(1);
+ async.done();
+ });
+ });
+ }), testTimeout);
+ test_lib_1.it('should produce long stack traces (when using microtasks)', test_lib_1.inject([test_lib_1.AsyncTestCompleter], function (async) {
+ macroTask(function () {
+ _zone.overrideOnErrorHandler(logError);
+ var c = async_1.PromiseWrapper.completer();
+ _zone.run(function () {
+ microTask(function () {
+ microTask(function () {
+ c.resolve(null);
+ throw new exceptions_1.BaseException("ddd");
+ });
+ });
+ });
+ c.promise.then(function (_) {
+ test_lib_1.expect(_traces.length).toBe(1);
+ test_lib_1.expect(_traces[0].length).toBeGreaterThan(1);
+ async.done();
+ });
+ });
+ }), testTimeout);
+ });
+ test_lib_1.describe('short stack trace', function () {
+ test_lib_1.beforeEach(function () { _zone = createZone(false); });
+ commonTests();
+ test_lib_1.it('should disable long stack traces', test_lib_1.inject([test_lib_1.AsyncTestCompleter], function (async) {
+ macroTask(function () {
+ _zone.overrideOnErrorHandler(logError);
+ var c = async_1.PromiseWrapper.completer();
+ _zone.run(function () {
+ async_1.TimerWrapper.setTimeout(function () {
+ async_1.TimerWrapper.setTimeout(function () {
+ c.resolve(null);
+ throw new exceptions_1.BaseException('ccc');
+ }, 0);
+ }, 0);
+ });
+ c.promise.then(function (_) {
+ test_lib_1.expect(_traces.length).toBe(1);
+ test_lib_1.expect(_traces[0].length).toEqual(1);
+ async.done();
+ });
+ });
+ }), testTimeout);
+ });
+ });
+}
+exports.main = main;
+function commonTests() {
+ test_lib_1.describe('isInInnerZone', function () {
+ test_lib_1.it('should return whether the code executes in the inner zone', function () {
+ test_lib_1.expect(test_lib_1.isInInnerZone()).toEqual(false);
+ _zone.run(function () { test_lib_1.expect(test_lib_1.isInInnerZone()).toEqual(true); });
+ }, testTimeout);
+ });
+ test_lib_1.describe('run', function () {
+ test_lib_1.it('should return the body return value from run', test_lib_1.inject([test_lib_1.AsyncTestCompleter], function (async) {
+ macroTask(function () { test_lib_1.expect(_zone.run(function () { return 6; })).toEqual(6); });
+ macroTask(function () { async.done(); });
+ }), testTimeout);
+ test_lib_1.it('should call onTurnStart and onTurnDone', test_lib_1.inject([test_lib_1.AsyncTestCompleter], function (async) {
+ macroTask(function () { _zone.run(_log.fn('run')); });
+ macroTask(function () {
+ test_lib_1.expect(_log.result()).toEqual('onTurnStart; run; onTurnDone');
+ async.done();
+ });
+ }), testTimeout);
+ test_lib_1.it('should call onEventDone once at the end of event', test_lib_1.inject([test_lib_1.AsyncTestCompleter], function (async) {
+ // The test is set up in a way that causes the zone loop to run onTurnDone twice
+ // then verified that onEventDone is only called once at the end
+ _zone.overrideOnTurnStart(null);
+ _zone.overrideOnEventDone(function () { _log.add('onEventDone'); });
+ var times = 0;
+ _zone.overrideOnTurnDone(function () {
+ times++;
+ _log.add("onTurnDone " + times);
+ if (times < 2) {
+ // Scheduling a microtask causes a second digest
+ microTask(function () { });
+ }
+ });
+ macroTask(function () { _zone.run(_log.fn('run')); });
+ macroTask(function () {
+ test_lib_1.expect(_log.result()).toEqual('run; onTurnDone 1; onTurnDone 2; onEventDone');
+ async.done();
+ }, resultTimer);
+ }), testTimeout);
+ test_lib_1.it('should call standalone onEventDone', test_lib_1.inject([test_lib_1.AsyncTestCompleter], function (async) {
+ _zone.overrideOnTurnStart(null);
+ _zone.overrideOnEventDone(function () { _log.add('onEventDone'); });
+ _zone.overrideOnTurnDone(null);
+ macroTask(function () { _zone.run(_log.fn('run')); });
+ macroTask(function () {
+ test_lib_1.expect(_log.result()).toEqual('run; onEventDone');
+ async.done();
+ }, resultTimer);
+ }), testTimeout);
+ test_lib_1.it('should not allow onEventDone to cause further digests', test_lib_1.inject([test_lib_1.AsyncTestCompleter], function (async) {
+ _zone.overrideOnTurnStart(null);
+ var eventDone = false;
+ _zone.overrideOnEventDone(function () {
+ if (eventDone)
+ throw 'Should not call this more than once';
+ _log.add('onEventDone');
+ // If not implemented correctly, this microtask will cause another digest,
+ // which is not what we want.
+ microTask(function () { });
+ eventDone = true;
+ });
+ _zone.overrideOnTurnDone(function () { _log.add('onTurnDone'); });
+ macroTask(function () { _zone.run(_log.fn('run')); });
+ macroTask(function () {
+ test_lib_1.expect(_log.result()).toEqual('run; onTurnDone; onEventDone');
+ async.done();
+ }, resultTimer);
+ }), testTimeout);
+ test_lib_1.it('should run async tasks scheduled inside onEventDone outside Angular zone', test_lib_1.inject([test_lib_1.AsyncTestCompleter], function (async) {
+ _zone.overrideOnTurnStart(null);
+ _zone.overrideOnEventDone(function () {
+ _log.add('onEventDone');
+ // If not implemented correctly, this time will cause another digest,
+ // which is not what we want.
+ async_1.TimerWrapper.setTimeout(function () { _log.add('asyncTask'); }, 5);
+ });
+ _zone.overrideOnTurnDone(function () { _log.add('onTurnDone'); });
+ macroTask(function () { _zone.run(_log.fn('run')); });
+ macroTask(function () {
+ async_1.TimerWrapper.setTimeout(function () {
+ test_lib_1.expect(_log.result()).toEqual('run; onTurnDone; onEventDone; asyncTask');
+ async.done();
+ }, 50);
+ });
+ }), testTimeout);
+ test_lib_1.it('should call onTurnStart once before a turn and onTurnDone once after the turn', test_lib_1.inject([test_lib_1.AsyncTestCompleter], function (async) {
+ macroTask(function () {
+ _zone.run(function () {
+ _log.add('run start');
+ microTask(_log.fn('async'));
+ _log.add('run end');
+ });
+ });
+ macroTask(function () {
+ // The microtask (async) is executed after the macrotask (run)
+ test_lib_1.expect(_log.result()).toEqual('onTurnStart; run start; run end; async; onTurnDone');
+ async.done();
+ }, resultTimer);
+ }), testTimeout);
+ test_lib_1.it('should not run onTurnStart and onTurnDone for nested Zone.run', test_lib_1.inject([test_lib_1.AsyncTestCompleter], function (async) {
+ macroTask(function () {
+ _zone.run(function () {
+ _log.add('start run');
+ _zone.run(function () {
+ _log.add('nested run');
+ microTask(_log.fn('nested run microtask'));
+ });
+ _log.add('end run');
+ });
+ });
+ macroTask(function () {
+ test_lib_1.expect(_log.result())
+ .toEqual('onTurnStart; start run; nested run; end run; nested run microtask; onTurnDone');
+ async.done();
+ }, resultTimer);
+ }), testTimeout);
+ test_lib_1.it('should not run onTurnStart and onTurnDone for nested Zone.run invoked from onTurnDone', test_lib_1.inject([test_lib_1.AsyncTestCompleter], function (async) {
+ _zone.overrideOnTurnStart(null);
+ _zone.overrideOnTurnDone(function () {
+ _log.add('onTurnDone:started');
+ _zone.run(function () { return _log.add('nested run'); });
+ _log.add('onTurnDone:finished');
+ });
+ macroTask(function () { _zone.run(function () { _log.add('start run'); }); });
+ macroTask(function () {
+ test_lib_1.expect(_log.result())
+ .toEqual('start run; onTurnDone:started; nested run; onTurnDone:finished');
+ async.done();
+ }, resultTimer);
+ }), testTimeout);
+ test_lib_1.it('should call onTurnStart and onTurnDone before and after each top-level run', test_lib_1.inject([test_lib_1.AsyncTestCompleter], function (async) {
+ macroTask(function () { _zone.run(_log.fn('run1')); });
+ macroTask(function () { _zone.run(_log.fn('run2')); });
+ macroTask(function () {
+ test_lib_1.expect(_log.result())
+ .toEqual('onTurnStart; run1; onTurnDone; onTurnStart; run2; onTurnDone');
+ async.done();
+ }, resultTimer);
+ }), testTimeout);
+ test_lib_1.it('should call onTurnStart and onTurnDone before and after each turn', test_lib_1.inject([test_lib_1.AsyncTestCompleter], function (async) {
+ var a;
+ var b;
+ macroTask(function () {
+ _zone.run(function () {
+ a = async_1.PromiseWrapper.completer();
+ b = async_1.PromiseWrapper.completer();
+ _log.add('run start');
+ a.promise.then(_log.fn('a then'));
+ b.promise.then(_log.fn('b then'));
+ });
+ });
+ macroTask(function () {
+ _zone.run(function () {
+ a.resolve('a');
+ b.resolve('b');
+ });
+ });
+ macroTask(function () {
+ test_lib_1.expect(_log.result())
+ .toEqual('onTurnStart; run start; onTurnDone; onTurnStart; a then; b then; onTurnDone');
+ async.done();
+ }, resultTimer);
+ }), testTimeout);
+ test_lib_1.it('should run a function outside of the angular zone', test_lib_1.inject([test_lib_1.AsyncTestCompleter], function (async) {
+ macroTask(function () { _zone.runOutsideAngular(_log.fn('run')); });
+ macroTask(function () {
+ test_lib_1.expect(_log.result()).toEqual('run');
+ async.done();
+ });
+ }), testTimeout);
+ test_lib_1.it('should call onTurnStart and onTurnDone when an inner microtask is scheduled from outside angular', test_lib_1.inject([test_lib_1.AsyncTestCompleter], function (async) {
+ var completer;
+ macroTask(function () { _zone.runOutsideAngular(function () { completer = async_1.PromiseWrapper.completer(); }); });
+ macroTask(function () { _zone.run(function () { completer.promise.then(_log.fn('executedMicrotask')); }); });
+ macroTask(function () {
+ _zone.runOutsideAngular(function () {
+ _log.add('scheduling a microtask');
+ completer.resolve(null);
+ });
+ });
+ macroTask(function () {
+ test_lib_1.expect(_log.result())
+ .toEqual(
+ // First VM turn => setup Promise then
+ 'onTurnStart; onTurnDone; ' +
+ // Second VM turn (outside of anguler)
+ 'scheduling a microtask; ' +
+ // Third VM Turn => execute the microtask (inside angular)
+ 'onTurnStart; executedMicrotask; onTurnDone');
+ async.done();
+ }, resultTimer);
+ }), testTimeout);
+ test_lib_1.it('should call onTurnStart before executing a microtask scheduled in onTurnDone as well as ' +
+ 'onTurnDone after executing the task', test_lib_1.inject([test_lib_1.AsyncTestCompleter], function (async) {
+ var ran = false;
+ _zone.overrideOnTurnStart(_log.fn('onTurnStart'));
+ _zone.overrideOnTurnDone(function () {
+ _log.add('onTurnDone(begin)');
+ if (!ran) {
+ microTask(function () {
+ ran = true;
+ _log.add('executedMicrotask');
+ });
+ }
+ _log.add('onTurnDone(end)');
+ });
+ macroTask(function () { _zone.run(_log.fn('run')); });
+ macroTask(function () {
+ test_lib_1.expect(_log.result())
+ .toEqual(
+ // First VM turn => 'run' macrotask
+ 'onTurnStart; run; onTurnDone(begin); onTurnDone(end); ' +
+ // Second VM Turn => microtask enqueued from onTurnDone
+ 'onTurnStart; executedMicrotask; onTurnDone(begin); onTurnDone(end)');
+ async.done();
+ }, resultTimer);
+ }), testTimeout);
+ test_lib_1.it('should call onTurnStart and onTurnDone for a scheduleMicrotask in onTurnDone triggered by ' +
+ 'a scheduleMicrotask in run', test_lib_1.inject([test_lib_1.AsyncTestCompleter], function (async) {
+ var ran = false;
+ _zone.overrideOnTurnStart(_log.fn('onTurnStart'));
+ _zone.overrideOnTurnDone(function () {
+ _log.add('onTurnDone(begin)');
+ if (!ran) {
+ _log.add('onTurnDone(scheduleMicrotask)');
+ microTask(function () {
+ ran = true;
+ _log.add('onTurnDone(executeMicrotask)');
+ });
+ }
+ _log.add('onTurnDone(end)');
+ });
+ macroTask(function () {
+ _zone.run(function () {
+ _log.add('scheduleMicrotask');
+ microTask(_log.fn('run(executeMicrotask)'));
+ });
+ });
+ macroTask(function () {
+ test_lib_1.expect(_log.result())
+ .toEqual(
+ // First VM Turn => a macrotask + the microtask it enqueues
+ 'onTurnStart; scheduleMicrotask; run(executeMicrotask); onTurnDone(begin); onTurnDone(scheduleMicrotask); onTurnDone(end); ' +
+ // Second VM Turn => the microtask enqueued from onTurnDone
+ 'onTurnStart; onTurnDone(executeMicrotask); onTurnDone(begin); onTurnDone(end)');
+ async.done();
+ }, resultTimer);
+ }), testTimeout);
+ test_lib_1.it('should execute promises scheduled in onTurnStart before promises scheduled in run', test_lib_1.inject([test_lib_1.AsyncTestCompleter], function (async) {
+ var donePromiseRan = false;
+ var startPromiseRan = false;
+ _zone.overrideOnTurnStart(function () {
+ _log.add('onTurnStart(begin)');
+ if (!startPromiseRan) {
+ _log.add('onTurnStart(schedulePromise)');
+ microTask(_log.fn('onTurnStart(executePromise)'));
+ startPromiseRan = true;
+ }
+ _log.add('onTurnStart(end)');
+ });
+ _zone.overrideOnTurnDone(function () {
+ _log.add('onTurnDone(begin)');
+ if (!donePromiseRan) {
+ _log.add('onTurnDone(schedulePromise)');
+ microTask(_log.fn('onTurnDone(executePromise)'));
+ donePromiseRan = true;
+ }
+ _log.add('onTurnDone(end)');
+ });
+ macroTask(function () {
+ _zone.run(function () {
+ _log.add('run start');
+ async_1.PromiseWrapper.resolve(null)
+ .then(function (_) {
+ _log.add('promise then');
+ async_1.PromiseWrapper.resolve(null).then(_log.fn('promise foo'));
+ return async_1.PromiseWrapper.resolve(null);
+ })
+ .then(_log.fn('promise bar'));
+ _log.add('run end');
+ });
+ });
+ macroTask(function () {
+ test_lib_1.expect(_log.result())
+ .toEqual(
+ // First VM turn: enqueue a microtask in onTurnStart
+ 'onTurnStart(begin); onTurnStart(schedulePromise); onTurnStart(end); ' +
+ // First VM turn: execute the macrotask which enqueues microtasks
+ 'run start; run end; ' +
+ // First VM turn: execute enqueued microtasks
+ 'onTurnStart(executePromise); promise then; promise foo; promise bar; ' +
+ // First VM turn: onTurnEnd, enqueue a microtask
+ 'onTurnDone(begin); onTurnDone(schedulePromise); onTurnDone(end); ' +
+ // Second VM turn: execute the microtask from onTurnEnd
+ 'onTurnStart(begin); onTurnStart(end); onTurnDone(executePromise); onTurnDone(begin); onTurnDone(end)');
+ async.done();
+ }, resultTimer);
+ }), testTimeout);
+ test_lib_1.it('should call onTurnStart and onTurnDone before and after each turn, respectively', test_lib_1.inject([test_lib_1.AsyncTestCompleter], function (async) {
+ var completerA;
+ var completerB;
+ macroTask(function () {
+ _zone.run(function () {
+ completerA = async_1.PromiseWrapper.completer();
+ completerB = async_1.PromiseWrapper.completer();
+ completerA.promise.then(_log.fn('a then'));
+ completerB.promise.then(_log.fn('b then'));
+ _log.add('run start');
+ });
+ });
+ macroTask(function () { _zone.run(function () { completerA.resolve(null); }); }, 20);
+ macroTask(function () { _zone.run(function () { completerB.resolve(null); }); }, 500);
+ macroTask(function () {
+ test_lib_1.expect(_log.result())
+ .toEqual(
+ // First VM turn
+ 'onTurnStart; run start; onTurnDone; ' +
+ // Second VM turn
+ 'onTurnStart; a then; onTurnDone; ' +
+ // Third VM turn
+ 'onTurnStart; b then; onTurnDone');
+ async.done();
+ }, resultTimer);
+ }), testTimeout);
+ test_lib_1.it('should call onTurnStart and onTurnDone before and after (respectively) all turns in a chain', test_lib_1.inject([test_lib_1.AsyncTestCompleter], function (async) {
+ macroTask(function () {
+ _zone.run(function () {
+ _log.add('run start');
+ microTask(function () {
+ _log.add('async1');
+ microTask(_log.fn('async2'));
+ });
+ _log.add('run end');
+ });
+ });
+ macroTask(function () {
+ test_lib_1.expect(_log.result())
+ .toEqual('onTurnStart; run start; run end; async1; async2; onTurnDone');
+ async.done();
+ }, resultTimer);
+ }), testTimeout);
+ test_lib_1.it('should call onTurnStart and onTurnDone for promises created outside of run body', test_lib_1.inject([test_lib_1.AsyncTestCompleter], function (async) {
+ var promise;
+ macroTask(function () {
+ _zone.runOutsideAngular(function () {
+ promise = async_1.PromiseWrapper.resolve(4).then(function (x) { return async_1.PromiseWrapper.resolve(x); });
+ });
+ _zone.run(function () {
+ promise.then(_log.fn('promise then'));
+ _log.add('zone run');
+ });
+ });
+ macroTask(function () {
+ test_lib_1.expect(_log.result())
+ .toEqual('onTurnStart; zone run; onTurnDone; onTurnStart; promise then; onTurnDone');
+ async.done();
+ }, resultTimer);
+ }), testTimeout);
+ });
+ test_lib_1.describe('exceptions', function () {
+ test_lib_1.it('should call the on error callback when it is defined', test_lib_1.inject([test_lib_1.AsyncTestCompleter], function (async) {
+ macroTask(function () {
+ _zone.overrideOnErrorHandler(logError);
+ var exception = new exceptions_1.BaseException('sync');
+ _zone.run(function () { throw exception; });
+ test_lib_1.expect(_errors.length).toBe(1);
+ test_lib_1.expect(_errors[0]).toBe(exception);
+ async.done();
+ });
+ }), testTimeout);
+ test_lib_1.it('should call onError for errors from microtasks', test_lib_1.inject([test_lib_1.AsyncTestCompleter], function (async) {
+ _zone.overrideOnErrorHandler(logError);
+ var exception = new exceptions_1.BaseException('async');
+ macroTask(function () { _zone.run(function () { microTask(function () { throw exception; }); }); });
+ macroTask(function () {
+ test_lib_1.expect(_errors.length).toBe(1);
+ test_lib_1.expect(_errors[0]).toEqual(exception);
+ async.done();
+ }, resultTimer);
+ }), testTimeout);
+ test_lib_1.it('should call onError when onTurnDone throws and the zone is sync', test_lib_1.inject([test_lib_1.AsyncTestCompleter], function (async) {
+ var exception = new exceptions_1.BaseException('fromOnTurnDone');
+ _zone.overrideOnErrorHandler(logError);
+ _zone.overrideOnTurnDone(function () { throw exception; });
+ macroTask(function () { _zone.run(function () { }); });
+ macroTask(function () {
+ test_lib_1.expect(_errors.length).toBe(1);
+ test_lib_1.expect(_errors[0]).toEqual(exception);
+ async.done();
+ }, resultTimer);
+ }), testTimeout);
+ test_lib_1.it('should call onError when onTurnDone throws and the zone is async', test_lib_1.inject([test_lib_1.AsyncTestCompleter], function (async) {
+ var asyncRan = false;
+ var exception = new exceptions_1.BaseException('fromOnTurnDone');
+ _zone.overrideOnErrorHandler(logError);
+ _zone.overrideOnTurnDone(function () { throw exception; });
+ macroTask(function () { _zone.run(function () { microTask(function () { asyncRan = true; }); }); });
+ macroTask(function () {
+ test_lib_1.expect(asyncRan).toBe(true);
+ test_lib_1.expect(_errors.length).toBe(1);
+ test_lib_1.expect(_errors[0]).toEqual(exception);
+ async.done();
+ }, resultTimer);
+ }), testTimeout);
+ });
+}
+//# sourceMappingURL=ng_zone_DEPRECATED_spec.js.map
\ No newline at end of file
diff --git a/test/core/zone/ng_zone_spec.js b/test/core/zone/ng_zone_spec.js
new file mode 100644
index 00000000000..d9714890f6d
--- /dev/null
+++ b/test/core/zone/ng_zone_spec.js
@@ -0,0 +1,572 @@
+var testing_internal_1 = require('angular2/testing_internal');
+var async_1 = require('angular2/src/facade/async');
+var exceptions_1 = require('angular2/src/facade/exceptions');
+var ng_zone_1 = require('angular2/src/core/zone/ng_zone');
+var needsLongerTimers = testing_internal_1.browserDetection.isSlow || testing_internal_1.browserDetection.isEdge;
+var resultTimer = 1000;
+var testTimeout = testing_internal_1.browserDetection.isEdge ? 1200 : 100;
+// Schedules a macrotask (using a timer)
+function macroTask(fn, timer) {
+ if (timer === void 0) { timer = 1; }
+ // adds longer timers for passing tests in IE and Edge
+ _zone.runOutsideAngular(function () { return async_1.TimerWrapper.setTimeout(fn, needsLongerTimers ? timer : 1); });
+}
+// Schedules a microtasks (using a resolved promise .then())
+function microTask(fn) {
+ async_1.PromiseWrapper.resolve(null).then(function (_) { fn(); });
+}
+var _log;
+var _errors;
+var _traces;
+var _zone;
+function logOnError() {
+ async_1.ObservableWrapper.subscribe(_zone.onError, function (ngErr) {
+ _errors.push(ngErr.error);
+ _traces.push(ngErr.stackTrace);
+ });
+}
+function logOnTurnStart() {
+ async_1.ObservableWrapper.subscribe(_zone.onTurnStart, _log.fn('onTurnStart'));
+}
+function logOnTurnDone() {
+ async_1.ObservableWrapper.subscribe(_zone.onTurnDone, _log.fn('onTurnDone'));
+}
+function logOnEventDone() {
+ async_1.ObservableWrapper.subscribe(_zone.onEventDone, _log.fn('onEventDone'));
+}
+function main() {
+ testing_internal_1.describe("NgZone", function () {
+ function createZone(enableLongStackTrace) {
+ return new ng_zone_1.NgZone({ enableLongStackTrace: enableLongStackTrace });
+ }
+ testing_internal_1.beforeEach(function () {
+ _log = new testing_internal_1.Log();
+ _errors = [];
+ _traces = [];
+ });
+ testing_internal_1.describe('long stack trace', function () {
+ testing_internal_1.beforeEach(function () { _zone = createZone(true); });
+ commonTests();
+ testing_internal_1.it('should produce long stack traces', testing_internal_1.inject([testing_internal_1.AsyncTestCompleter], function (async) {
+ macroTask(function () {
+ logOnError();
+ var c = async_1.PromiseWrapper.completer();
+ _zone.run(function () {
+ async_1.TimerWrapper.setTimeout(function () {
+ async_1.TimerWrapper.setTimeout(function () {
+ c.resolve(null);
+ throw new exceptions_1.BaseException('ccc');
+ }, 0);
+ }, 0);
+ });
+ c.promise.then(function (_) {
+ testing_internal_1.expect(_traces.length).toBe(1);
+ testing_internal_1.expect(_traces[0].length).toBeGreaterThan(1);
+ async.done();
+ });
+ });
+ }), testTimeout);
+ testing_internal_1.it('should produce long stack traces (when using microtasks)', testing_internal_1.inject([testing_internal_1.AsyncTestCompleter], function (async) {
+ macroTask(function () {
+ logOnError();
+ var c = async_1.PromiseWrapper.completer();
+ _zone.run(function () {
+ microTask(function () {
+ microTask(function () {
+ c.resolve(null);
+ throw new exceptions_1.BaseException("ddd");
+ });
+ });
+ });
+ c.promise.then(function (_) {
+ testing_internal_1.expect(_traces.length).toBe(1);
+ testing_internal_1.expect(_traces[0].length).toBeGreaterThan(1);
+ async.done();
+ });
+ });
+ }), testTimeout);
+ });
+ testing_internal_1.describe('short stack trace', function () {
+ testing_internal_1.beforeEach(function () { _zone = createZone(false); });
+ commonTests();
+ testing_internal_1.it('should disable long stack traces', testing_internal_1.inject([testing_internal_1.AsyncTestCompleter], function (async) {
+ macroTask(function () {
+ logOnError();
+ var c = async_1.PromiseWrapper.completer();
+ _zone.run(function () {
+ async_1.TimerWrapper.setTimeout(function () {
+ async_1.TimerWrapper.setTimeout(function () {
+ c.resolve(null);
+ throw new exceptions_1.BaseException('ccc');
+ }, 0);
+ }, 0);
+ });
+ c.promise.then(function (_) {
+ testing_internal_1.expect(_traces.length).toBe(1);
+ testing_internal_1.expect(_traces[0].length).toEqual(1);
+ async.done();
+ });
+ });
+ }), testTimeout);
+ });
+ });
+}
+exports.main = main;
+function commonTests() {
+ testing_internal_1.describe('hasPendingMicrotasks', function () {
+ testing_internal_1.it('should be false', function () { testing_internal_1.expect(_zone.hasPendingMicrotasks).toBe(false); });
+ testing_internal_1.it('should be true', function () {
+ _zone.run(function () { microTask(function () { }); });
+ testing_internal_1.expect(_zone.hasPendingMicrotasks).toBe(true);
+ });
+ });
+ testing_internal_1.describe('hasPendingTimers', function () {
+ testing_internal_1.it('should be false', function () { testing_internal_1.expect(_zone.hasPendingTimers).toBe(false); });
+ testing_internal_1.it('should be true', function () {
+ _zone.run(function () { async_1.TimerWrapper.setTimeout(function () { }, 0); });
+ testing_internal_1.expect(_zone.hasPendingTimers).toBe(true);
+ });
+ });
+ testing_internal_1.describe('hasPendingAsyncTasks', function () {
+ testing_internal_1.it('should be false', function () { testing_internal_1.expect(_zone.hasPendingAsyncTasks).toBe(false); });
+ testing_internal_1.it('should be true when microtask is scheduled', function () {
+ _zone.run(function () { microTask(function () { }); });
+ testing_internal_1.expect(_zone.hasPendingAsyncTasks).toBe(true);
+ });
+ testing_internal_1.it('should be true when timer is scheduled', function () {
+ _zone.run(function () { async_1.TimerWrapper.setTimeout(function () { }, 0); });
+ testing_internal_1.expect(_zone.hasPendingAsyncTasks).toBe(true);
+ });
+ });
+ testing_internal_1.describe('isInInnerZone', function () {
+ testing_internal_1.it('should return whether the code executes in the inner zone', function () {
+ testing_internal_1.expect(testing_internal_1.isInInnerZone()).toEqual(false);
+ _zone.run(function () { testing_internal_1.expect(testing_internal_1.isInInnerZone()).toEqual(true); });
+ }, testTimeout);
+ });
+ testing_internal_1.describe('run', function () {
+ testing_internal_1.it('should return the body return value from run', testing_internal_1.inject([testing_internal_1.AsyncTestCompleter], function (async) {
+ macroTask(function () { testing_internal_1.expect(_zone.run(function () { return 6; })).toEqual(6); });
+ macroTask(function () { async.done(); });
+ }), testTimeout);
+ testing_internal_1.it('should call onTurnStart and onTurnDone', testing_internal_1.inject([testing_internal_1.AsyncTestCompleter], function (async) {
+ logOnTurnStart();
+ logOnTurnDone();
+ macroTask(function () { _zone.run(_log.fn('run')); });
+ macroTask(function () {
+ testing_internal_1.expect(_log.result()).toEqual('onTurnStart; run; onTurnDone');
+ async.done();
+ });
+ }), testTimeout);
+ testing_internal_1.it('should call onEventDone once at the end of event', testing_internal_1.inject([testing_internal_1.AsyncTestCompleter], function (async) {
+ // The test is set up in a way that causes the zone loop to run onTurnDone twice
+ // then verified that onEventDone is only called once at the end
+ logOnEventDone();
+ var times = 0;
+ async_1.ObservableWrapper.subscribe(_zone.onTurnDone, function (_) {
+ times++;
+ _log.add("onTurnDone " + times);
+ if (times < 2) {
+ // Scheduling a microtask causes a second digest
+ _zone.run(function () { microTask(function () { }); });
+ }
+ });
+ macroTask(function () { _zone.run(_log.fn('run')); });
+ macroTask(function () {
+ testing_internal_1.expect(_log.result()).toEqual('run; onTurnDone 1; onTurnDone 2; onEventDone');
+ async.done();
+ }, resultTimer);
+ }), testTimeout);
+ testing_internal_1.it('should call standalone onEventDone', testing_internal_1.inject([testing_internal_1.AsyncTestCompleter], function (async) {
+ logOnEventDone();
+ macroTask(function () { _zone.run(_log.fn('run')); });
+ macroTask(function () {
+ testing_internal_1.expect(_log.result()).toEqual('run; onEventDone');
+ async.done();
+ }, resultTimer);
+ }), testTimeout);
+ testing_internal_1.it('should run subscriber listeners in the subscription zone (outside)', testing_internal_1.inject([testing_internal_1.AsyncTestCompleter], function (async) {
+ // Each subscriber fires a microtask outside the Angular zone. The test
+ // then verifies that those microtasks do not cause additional digests.
+ var turnStart = false;
+ async_1.ObservableWrapper.subscribe(_zone.onTurnStart, function (_) {
+ if (turnStart)
+ throw 'Should not call this more than once';
+ _log.add('onTurnStart');
+ microTask(function () { });
+ turnStart = true;
+ });
+ var turnDone = false;
+ async_1.ObservableWrapper.subscribe(_zone.onTurnDone, function (_) {
+ if (turnDone)
+ throw 'Should not call this more than once';
+ _log.add('onTurnDone');
+ microTask(function () { });
+ turnDone = true;
+ });
+ var eventDone = false;
+ async_1.ObservableWrapper.subscribe(_zone.onEventDone, function (_) {
+ if (eventDone)
+ throw 'Should not call this more than once';
+ _log.add('onEventDone');
+ microTask(function () { });
+ eventDone = true;
+ });
+ macroTask(function () { _zone.run(_log.fn('run')); });
+ macroTask(function () {
+ testing_internal_1.expect(_log.result()).toEqual('onTurnStart; run; onTurnDone; onEventDone');
+ async.done();
+ }, resultTimer);
+ }), testTimeout);
+ testing_internal_1.it('should run subscriber listeners in the subscription zone (inside)', testing_internal_1.inject([testing_internal_1.AsyncTestCompleter], function (async) {
+ // the only practical use-case to run a callback inside the zone is
+ // change detection after "onTurnDone". That's the only case tested.
+ var turnDone = false;
+ async_1.ObservableWrapper.subscribe(_zone.onTurnDone, function (_) {
+ _log.add('onTurnDone');
+ if (turnDone)
+ return;
+ _zone.run(function () { microTask(function () { }); });
+ turnDone = true;
+ });
+ macroTask(function () { _zone.run(_log.fn('run')); });
+ macroTask(function () {
+ testing_internal_1.expect(_log.result()).toEqual('run; onTurnDone; onTurnDone');
+ async.done();
+ }, resultTimer);
+ }), testTimeout);
+ testing_internal_1.it('should run async tasks scheduled inside onEventDone outside Angular zone', testing_internal_1.inject([testing_internal_1.AsyncTestCompleter], function (async) {
+ async_1.ObservableWrapper.subscribe(_zone.onEventDone, function (_) {
+ _log.add('onEventDone');
+ // If not implemented correctly, this time will cause another digest,
+ // which is not what we want.
+ async_1.TimerWrapper.setTimeout(function () { _log.add('asyncTask'); }, 5);
+ });
+ logOnTurnDone();
+ macroTask(function () { _zone.run(_log.fn('run')); });
+ macroTask(function () {
+ async_1.TimerWrapper.setTimeout(function () {
+ testing_internal_1.expect(_log.result()).toEqual('run; onTurnDone; onEventDone; asyncTask');
+ async.done();
+ }, 50);
+ });
+ }), testTimeout);
+ testing_internal_1.it('should call onTurnStart once before a turn and onTurnDone once after the turn', testing_internal_1.inject([testing_internal_1.AsyncTestCompleter], function (async) {
+ logOnTurnStart();
+ logOnTurnDone();
+ macroTask(function () {
+ _zone.run(function () {
+ _log.add('run start');
+ microTask(_log.fn('async'));
+ _log.add('run end');
+ });
+ });
+ macroTask(function () {
+ // The microtask (async) is executed after the macrotask (run)
+ testing_internal_1.expect(_log.result()).toEqual('onTurnStart; run start; run end; async; onTurnDone');
+ async.done();
+ }, resultTimer);
+ }), testTimeout);
+ testing_internal_1.it('should not run onTurnStart and onTurnDone for nested Zone.run', testing_internal_1.inject([testing_internal_1.AsyncTestCompleter], function (async) {
+ logOnTurnStart();
+ logOnTurnDone();
+ macroTask(function () {
+ _zone.run(function () {
+ _log.add('start run');
+ _zone.run(function () {
+ _log.add('nested run');
+ microTask(_log.fn('nested run microtask'));
+ });
+ _log.add('end run');
+ });
+ });
+ macroTask(function () {
+ testing_internal_1.expect(_log.result())
+ .toEqual('onTurnStart; start run; nested run; end run; nested run microtask; onTurnDone');
+ async.done();
+ }, resultTimer);
+ }), testTimeout);
+ testing_internal_1.it('should not run onTurnStart and onTurnDone for nested Zone.run invoked from onTurnDone', testing_internal_1.inject([testing_internal_1.AsyncTestCompleter], function (async) {
+ async_1.ObservableWrapper.subscribe(_zone.onTurnDone, function (_) {
+ _log.add('onTurnDone:started');
+ _zone.run(function () { return _log.add('nested run'); });
+ _log.add('onTurnDone:finished');
+ });
+ macroTask(function () { _zone.run(function () { _log.add('start run'); }); });
+ macroTask(function () {
+ testing_internal_1.expect(_log.result())
+ .toEqual('start run; onTurnDone:started; nested run; onTurnDone:finished');
+ async.done();
+ }, resultTimer);
+ }), testTimeout);
+ testing_internal_1.it('should call onTurnStart and onTurnDone before and after each top-level run', testing_internal_1.inject([testing_internal_1.AsyncTestCompleter], function (async) {
+ logOnTurnStart();
+ logOnTurnDone();
+ macroTask(function () { _zone.run(_log.fn('run1')); });
+ macroTask(function () { _zone.run(_log.fn('run2')); });
+ macroTask(function () {
+ testing_internal_1.expect(_log.result())
+ .toEqual('onTurnStart; run1; onTurnDone; onTurnStart; run2; onTurnDone');
+ async.done();
+ }, resultTimer);
+ }), testTimeout);
+ testing_internal_1.it('should call onTurnStart and onTurnDone before and after each turn', testing_internal_1.inject([testing_internal_1.AsyncTestCompleter], function (async) {
+ logOnTurnStart();
+ logOnTurnDone();
+ var a;
+ var b;
+ macroTask(function () {
+ _zone.run(function () {
+ a = async_1.PromiseWrapper.completer();
+ b = async_1.PromiseWrapper.completer();
+ _log.add('run start');
+ a.promise.then(_log.fn('a then'));
+ b.promise.then(_log.fn('b then'));
+ });
+ });
+ macroTask(function () {
+ _zone.run(function () {
+ a.resolve('a');
+ b.resolve('b');
+ });
+ });
+ macroTask(function () {
+ testing_internal_1.expect(_log.result())
+ .toEqual('onTurnStart; run start; onTurnDone; onTurnStart; a then; b then; onTurnDone');
+ async.done();
+ }, resultTimer);
+ }), testTimeout);
+ testing_internal_1.it('should run a function outside of the angular zone', testing_internal_1.inject([testing_internal_1.AsyncTestCompleter], function (async) {
+ logOnTurnStart();
+ logOnTurnDone();
+ macroTask(function () { _zone.runOutsideAngular(_log.fn('run')); });
+ macroTask(function () {
+ testing_internal_1.expect(_log.result()).toEqual('run');
+ async.done();
+ });
+ }), testTimeout);
+ testing_internal_1.it('should call onTurnStart and onTurnDone when an inner microtask is scheduled from outside angular', testing_internal_1.inject([testing_internal_1.AsyncTestCompleter], function (async) {
+ logOnTurnStart();
+ logOnTurnDone();
+ var completer;
+ macroTask(function () { _zone.runOutsideAngular(function () { completer = async_1.PromiseWrapper.completer(); }); });
+ macroTask(function () { _zone.run(function () { completer.promise.then(_log.fn('executedMicrotask')); }); });
+ macroTask(function () {
+ _zone.runOutsideAngular(function () {
+ _log.add('scheduling a microtask');
+ completer.resolve(null);
+ });
+ });
+ macroTask(function () {
+ testing_internal_1.expect(_log.result())
+ .toEqual(
+ // First VM turn => setup Promise then
+ 'onTurnStart; onTurnDone; ' +
+ // Second VM turn (outside of anguler)
+ 'scheduling a microtask; ' +
+ // Third VM Turn => execute the microtask (inside angular)
+ 'onTurnStart; executedMicrotask; onTurnDone');
+ async.done();
+ }, resultTimer);
+ }), testTimeout);
+ testing_internal_1.it('should call onTurnStart before executing a microtask scheduled in onTurnDone as well as ' +
+ 'onTurnDone after executing the task', testing_internal_1.inject([testing_internal_1.AsyncTestCompleter], function (async) {
+ var ran = false;
+ logOnTurnStart();
+ async_1.ObservableWrapper.subscribe(_zone.onTurnDone, function (_) {
+ _log.add('onTurnDone(begin)');
+ if (!ran) {
+ _zone.run(function () {
+ microTask(function () {
+ ran = true;
+ _log.add('executedMicrotask');
+ });
+ });
+ }
+ _log.add('onTurnDone(end)');
+ });
+ macroTask(function () { _zone.run(_log.fn('run')); });
+ macroTask(function () {
+ testing_internal_1.expect(_log.result())
+ .toEqual(
+ // First VM turn => 'run' macrotask
+ 'onTurnStart; run; onTurnDone(begin); onTurnDone(end); ' +
+ // Second VM Turn => microtask enqueued from onTurnDone
+ 'onTurnStart; executedMicrotask; onTurnDone(begin); onTurnDone(end)');
+ async.done();
+ }, resultTimer);
+ }), testTimeout);
+ testing_internal_1.it('should call onTurnStart and onTurnDone for a scheduleMicrotask in onTurnDone triggered by ' +
+ 'a scheduleMicrotask in run', testing_internal_1.inject([testing_internal_1.AsyncTestCompleter], function (async) {
+ var ran = false;
+ logOnTurnStart();
+ async_1.ObservableWrapper.subscribe(_zone.onTurnDone, function (_) {
+ _log.add('onTurnDone(begin)');
+ if (!ran) {
+ _log.add('onTurnDone(scheduleMicrotask)');
+ _zone.run(function () {
+ microTask(function () {
+ ran = true;
+ _log.add('onTurnDone(executeMicrotask)');
+ });
+ });
+ }
+ _log.add('onTurnDone(end)');
+ });
+ macroTask(function () {
+ _zone.run(function () {
+ _log.add('scheduleMicrotask');
+ microTask(_log.fn('run(executeMicrotask)'));
+ });
+ });
+ macroTask(function () {
+ testing_internal_1.expect(_log.result())
+ .toEqual(
+ // First VM Turn => a macrotask + the microtask it enqueues
+ 'onTurnStart; scheduleMicrotask; run(executeMicrotask); onTurnDone(begin); onTurnDone(scheduleMicrotask); onTurnDone(end); ' +
+ // Second VM Turn => the microtask enqueued from onTurnDone
+ 'onTurnStart; onTurnDone(executeMicrotask); onTurnDone(begin); onTurnDone(end)');
+ async.done();
+ }, resultTimer);
+ }), testTimeout);
+ testing_internal_1.it('should execute promises scheduled in onTurnStart before promises scheduled in run', testing_internal_1.inject([testing_internal_1.AsyncTestCompleter], function (async) {
+ var donePromiseRan = false;
+ var startPromiseRan = false;
+ async_1.ObservableWrapper.subscribe(_zone.onTurnStart, function (_) {
+ _log.add('onTurnStart(begin)');
+ if (!startPromiseRan) {
+ _log.add('onTurnStart(schedulePromise)');
+ _zone.run(function () { microTask(_log.fn('onTurnStart(executePromise)')); });
+ startPromiseRan = true;
+ }
+ _log.add('onTurnStart(end)');
+ });
+ async_1.ObservableWrapper.subscribe(_zone.onTurnDone, function (_) {
+ _log.add('onTurnDone(begin)');
+ if (!donePromiseRan) {
+ _log.add('onTurnDone(schedulePromise)');
+ _zone.run(function () { microTask(_log.fn('onTurnDone(executePromise)')); });
+ donePromiseRan = true;
+ }
+ _log.add('onTurnDone(end)');
+ });
+ macroTask(function () {
+ _zone.run(function () {
+ _log.add('run start');
+ async_1.PromiseWrapper.resolve(null)
+ .then(function (_) {
+ _log.add('promise then');
+ async_1.PromiseWrapper.resolve(null).then(_log.fn('promise foo'));
+ return async_1.PromiseWrapper.resolve(null);
+ })
+ .then(_log.fn('promise bar'));
+ _log.add('run end');
+ });
+ });
+ macroTask(function () {
+ testing_internal_1.expect(_log.result())
+ .toEqual(
+ // First VM turn: enqueue a microtask in onTurnStart
+ 'onTurnStart(begin); onTurnStart(schedulePromise); onTurnStart(end); ' +
+ // First VM turn: execute the macrotask which enqueues microtasks
+ 'run start; run end; ' +
+ // First VM turn: execute enqueued microtasks
+ 'onTurnStart(executePromise); promise then; promise foo; promise bar; ' +
+ // First VM turn: onTurnEnd, enqueue a microtask
+ 'onTurnDone(begin); onTurnDone(schedulePromise); onTurnDone(end); ' +
+ // Second VM turn: execute the microtask from onTurnEnd
+ 'onTurnStart(begin); onTurnStart(end); onTurnDone(executePromise); onTurnDone(begin); onTurnDone(end)');
+ async.done();
+ }, resultTimer);
+ }), testTimeout);
+ testing_internal_1.it('should call onTurnStart and onTurnDone before and after each turn, respectively', testing_internal_1.inject([testing_internal_1.AsyncTestCompleter], function (async) {
+ var completerA;
+ var completerB;
+ logOnTurnStart();
+ logOnTurnDone();
+ macroTask(function () {
+ _zone.run(function () {
+ completerA = async_1.PromiseWrapper.completer();
+ completerB = async_1.PromiseWrapper.completer();
+ completerA.promise.then(_log.fn('a then'));
+ completerB.promise.then(_log.fn('b then'));
+ _log.add('run start');
+ });
+ });
+ macroTask(function () { _zone.run(function () { completerA.resolve(null); }); }, 20);
+ macroTask(function () { _zone.run(function () { completerB.resolve(null); }); }, 500);
+ macroTask(function () {
+ testing_internal_1.expect(_log.result())
+ .toEqual(
+ // First VM turn
+ 'onTurnStart; run start; onTurnDone; ' +
+ // Second VM turn
+ 'onTurnStart; a then; onTurnDone; ' +
+ // Third VM turn
+ 'onTurnStart; b then; onTurnDone');
+ async.done();
+ }, resultTimer);
+ }), testTimeout);
+ testing_internal_1.it('should call onTurnStart and onTurnDone before and after (respectively) all turns in a chain', testing_internal_1.inject([testing_internal_1.AsyncTestCompleter], function (async) {
+ logOnTurnStart();
+ logOnTurnDone();
+ macroTask(function () {
+ _zone.run(function () {
+ _log.add('run start');
+ microTask(function () {
+ _log.add('async1');
+ microTask(_log.fn('async2'));
+ });
+ _log.add('run end');
+ });
+ });
+ macroTask(function () {
+ testing_internal_1.expect(_log.result())
+ .toEqual('onTurnStart; run start; run end; async1; async2; onTurnDone');
+ async.done();
+ }, resultTimer);
+ }), testTimeout);
+ testing_internal_1.it('should call onTurnStart and onTurnDone for promises created outside of run body', testing_internal_1.inject([testing_internal_1.AsyncTestCompleter], function (async) {
+ logOnTurnStart();
+ logOnTurnDone();
+ var promise;
+ macroTask(function () {
+ _zone.runOutsideAngular(function () {
+ promise = async_1.PromiseWrapper.resolve(4).then(function (x) { return async_1.PromiseWrapper.resolve(x); });
+ });
+ _zone.run(function () {
+ promise.then(_log.fn('promise then'));
+ _log.add('zone run');
+ });
+ });
+ macroTask(function () {
+ testing_internal_1.expect(_log.result())
+ .toEqual('onTurnStart; zone run; onTurnDone; onTurnStart; promise then; onTurnDone');
+ async.done();
+ }, resultTimer);
+ }), testTimeout);
+ });
+ testing_internal_1.describe('exceptions', function () {
+ testing_internal_1.it('should call the on error callback when it is defined', testing_internal_1.inject([testing_internal_1.AsyncTestCompleter], function (async) {
+ macroTask(function () {
+ logOnError();
+ var exception = new exceptions_1.BaseException('sync');
+ _zone.run(function () { throw exception; });
+ testing_internal_1.expect(_errors.length).toBe(1);
+ testing_internal_1.expect(_errors[0]).toBe(exception);
+ async.done();
+ });
+ }), testTimeout);
+ testing_internal_1.it('should call onError for errors from microtasks', testing_internal_1.inject([testing_internal_1.AsyncTestCompleter], function (async) {
+ logOnError();
+ var exception = new exceptions_1.BaseException('async');
+ macroTask(function () { _zone.run(function () { microTask(function () { throw exception; }); }); });
+ macroTask(function () {
+ testing_internal_1.expect(_errors.length).toBe(1);
+ testing_internal_1.expect(_errors[0]).toEqual(exception);
+ async.done();
+ }, resultTimer);
+ }), testTimeout);
+ });
+}
+//# sourceMappingURL=ng_zone_spec.js.map
\ No newline at end of file
diff --git a/test/dev_mode_spec.js b/test/dev_mode_spec.js
new file mode 100644
index 00000000000..fd66d7ce620
--- /dev/null
+++ b/test/dev_mode_spec.js
@@ -0,0 +1,9 @@
+var testing_internal_1 = require('angular2/testing_internal');
+var lang_1 = require('angular2/src/facade/lang');
+function main() {
+ testing_internal_1.describe('dev mode', function () {
+ testing_internal_1.it('is enabled in our tests by default', function () { testing_internal_1.expect(lang_1.assertionsEnabled()).toBe(true); });
+ });
+}
+exports.main = main;
+//# sourceMappingURL=dev_mode_spec.js.map
\ No newline at end of file
diff --git a/test/http/backends/jsonp_backend_spec.js b/test/http/backends/jsonp_backend_spec.js
new file mode 100644
index 00000000000..164b9a9d165
--- /dev/null
+++ b/test/http/backends/jsonp_backend_spec.js
@@ -0,0 +1,142 @@
+var __extends = (this && this.__extends) || function (d, b) {
+ for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
+ function __() { this.constructor = d; }
+ d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
+};
+var testing_internal_1 = require('angular2/testing_internal');
+var browser_jsonp_1 = require('angular2/src/http/backends/browser_jsonp');
+var jsonp_backend_1 = require('angular2/src/http/backends/jsonp_backend');
+var core_1 = require('angular2/core');
+var lang_1 = require('angular2/src/facade/lang');
+var async_1 = require('angular2/src/facade/async');
+var static_request_1 = require('angular2/src/http/static_request');
+var collection_1 = require('angular2/src/facade/collection');
+var base_request_options_1 = require('angular2/src/http/base_request_options');
+var base_response_options_1 = require('angular2/src/http/base_response_options');
+var enums_1 = require('angular2/src/http/enums');
+var addEventListenerSpy;
+var existingScripts = [];
+var unused;
+var MockBrowserJsonp = (function (_super) {
+ __extends(MockBrowserJsonp, _super);
+ function MockBrowserJsonp() {
+ _super.call(this);
+ this.callbacks = new collection_1.Map();
+ }
+ MockBrowserJsonp.prototype.addEventListener = function (type, cb) { this.callbacks.set(type, cb); };
+ MockBrowserJsonp.prototype.removeEventListener = function (type, cb) { this.callbacks.delete(type); };
+ MockBrowserJsonp.prototype.dispatchEvent = function (type, argument) {
+ if (!lang_1.isPresent(argument)) {
+ argument = {};
+ }
+ var cb = this.callbacks.get(type);
+ if (lang_1.isPresent(cb)) {
+ cb(argument);
+ }
+ };
+ MockBrowserJsonp.prototype.build = function (url) {
+ var script = new MockBrowserJsonp();
+ script.src = url;
+ existingScripts.push(script);
+ return script;
+ };
+ MockBrowserJsonp.prototype.send = function (node) {
+ };
+ MockBrowserJsonp.prototype.cleanup = function (node) {
+ };
+ return MockBrowserJsonp;
+})(browser_jsonp_1.BrowserJsonp);
+function main() {
+ testing_internal_1.describe('JSONPBackend', function () {
+ var backend;
+ var sampleRequest;
+ testing_internal_1.beforeEach(function () {
+ var injector = core_1.Injector.resolveAndCreate([
+ core_1.provide(base_response_options_1.ResponseOptions, { useClass: base_response_options_1.BaseResponseOptions }),
+ core_1.provide(browser_jsonp_1.BrowserJsonp, { useClass: MockBrowserJsonp }),
+ core_1.provide(jsonp_backend_1.JSONPBackend, { useClass: jsonp_backend_1.JSONPBackend_ })
+ ]);
+ backend = injector.get(jsonp_backend_1.JSONPBackend);
+ var base = new base_request_options_1.BaseRequestOptions();
+ sampleRequest = new static_request_1.Request(base.merge(new base_request_options_1.RequestOptions({ url: 'https://google.com' })));
+ });
+ testing_internal_1.afterEach(function () { existingScripts = []; });
+ testing_internal_1.it('should create a connection', function () {
+ var instance;
+ testing_internal_1.expect(function () { return instance = backend.createConnection(sampleRequest); }).not.toThrow();
+ testing_internal_1.expect(instance).toBeAnInstanceOf(jsonp_backend_1.JSONPConnection);
+ });
+ testing_internal_1.describe('JSONPConnection', function () {
+ testing_internal_1.it('should use the injected BaseResponseOptions to create the response', testing_internal_1.inject([testing_internal_1.AsyncTestCompleter], function (async) {
+ var connection = new jsonp_backend_1.JSONPConnection_(sampleRequest, new MockBrowserJsonp(), new base_response_options_1.ResponseOptions({ type: enums_1.ResponseTypes.Error }));
+ connection.response.subscribe(function (res) {
+ testing_internal_1.expect(res.type).toBe(enums_1.ResponseTypes.Error);
+ async.done();
+ });
+ connection.finished();
+ existingScripts[0].dispatchEvent('load');
+ }));
+ testing_internal_1.it('should ignore load/callback when disposed', testing_internal_1.inject([testing_internal_1.AsyncTestCompleter], function (async) {
+ var connection = new jsonp_backend_1.JSONPConnection_(sampleRequest, new MockBrowserJsonp());
+ var spy = new testing_internal_1.SpyObject();
+ var loadSpy = spy.spy('load');
+ var errorSpy = spy.spy('error');
+ var returnSpy = spy.spy('cancelled');
+ var request = connection.response.subscribe(loadSpy, errorSpy, returnSpy);
+ request.unsubscribe();
+ connection.finished('Fake data');
+ existingScripts[0].dispatchEvent('load');
+ async_1.TimerWrapper.setTimeout(function () {
+ testing_internal_1.expect(connection.readyState).toBe(enums_1.ReadyStates.Cancelled);
+ testing_internal_1.expect(loadSpy).not.toHaveBeenCalled();
+ testing_internal_1.expect(errorSpy).not.toHaveBeenCalled();
+ testing_internal_1.expect(returnSpy).not.toHaveBeenCalled();
+ async.done();
+ }, 10);
+ }));
+ testing_internal_1.it('should report error if loaded without invoking callback', testing_internal_1.inject([testing_internal_1.AsyncTestCompleter], function (async) {
+ var connection = new jsonp_backend_1.JSONPConnection_(sampleRequest, new MockBrowserJsonp());
+ connection.response.subscribe(function (res) {
+ testing_internal_1.expect("response listener called").toBe(false);
+ async.done();
+ }, function (err) {
+ testing_internal_1.expect(err.text()).toEqual('JSONP injected script did not invoke callback.');
+ async.done();
+ });
+ existingScripts[0].dispatchEvent('load');
+ }));
+ testing_internal_1.it('should report error if script contains error', testing_internal_1.inject([testing_internal_1.AsyncTestCompleter], function (async) {
+ var connection = new jsonp_backend_1.JSONPConnection_(sampleRequest, new MockBrowserJsonp());
+ connection.response.subscribe(function (res) {
+ testing_internal_1.expect("response listener called").toBe(false);
+ async.done();
+ }, function (err) {
+ testing_internal_1.expect(err.text()).toBe('Oops!');
+ async.done();
+ });
+ existingScripts[0].dispatchEvent('error', ({ message: "Oops!" }));
+ }));
+ testing_internal_1.it('should throw if request method is not GET', function () {
+ [enums_1.RequestMethods.Post, enums_1.RequestMethods.Put, enums_1.RequestMethods.Delete, enums_1.RequestMethods.Options,
+ enums_1.RequestMethods.Head, enums_1.RequestMethods.Patch]
+ .forEach(function (method) {
+ var base = new base_request_options_1.BaseRequestOptions();
+ var req = new static_request_1.Request(base.merge(new base_request_options_1.RequestOptions({ url: 'https://google.com', method: method })));
+ testing_internal_1.expect(function () { return new jsonp_backend_1.JSONPConnection_(req, new MockBrowserJsonp()).response.subscribe(); })
+ .toThrowError();
+ });
+ });
+ testing_internal_1.it('should respond with data passed to callback', testing_internal_1.inject([testing_internal_1.AsyncTestCompleter], function (async) {
+ var connection = new jsonp_backend_1.JSONPConnection_(sampleRequest, new MockBrowserJsonp());
+ connection.response.subscribe(function (res) {
+ testing_internal_1.expect(res.json()).toEqual(({ fake_payload: true, blob_id: 12345 }));
+ async.done();
+ });
+ connection.finished(({ fake_payload: true, blob_id: 12345 }));
+ existingScripts[0].dispatchEvent('load');
+ }));
+ });
+ });
+}
+exports.main = main;
+//# sourceMappingURL=jsonp_backend_spec.js.map
\ No newline at end of file
diff --git a/test/http/backends/mock_backend_spec.js b/test/http/backends/mock_backend_spec.js
new file mode 100644
index 00000000000..208e17c0947
--- /dev/null
+++ b/test/http/backends/mock_backend_spec.js
@@ -0,0 +1,85 @@
+var testing_internal_1 = require('angular2/testing_internal');
+var mock_backend_1 = require('angular2/src/http/backends/mock_backend');
+var core_1 = require('angular2/core');
+var static_request_1 = require('angular2/src/http/static_request');
+var static_response_1 = require('angular2/src/http/static_response');
+var base_request_options_1 = require('angular2/src/http/base_request_options');
+var base_response_options_1 = require('angular2/src/http/base_response_options');
+function main() {
+ testing_internal_1.describe('MockBackend', function () {
+ var backend;
+ var sampleRequest1;
+ var sampleResponse1;
+ var sampleRequest2;
+ var sampleResponse2;
+ var connection;
+ testing_internal_1.beforeEach(function () {
+ var injector = core_1.Injector.resolveAndCreate([core_1.provide(base_response_options_1.ResponseOptions, { useClass: base_response_options_1.BaseResponseOptions }), mock_backend_1.MockBackend]);
+ backend = injector.get(mock_backend_1.MockBackend);
+ var base = new base_request_options_1.BaseRequestOptions();
+ sampleRequest1 = new static_request_1.Request(base.merge(new base_request_options_1.RequestOptions({ url: 'https://google.com' })));
+ sampleResponse1 = new static_response_1.Response(new base_response_options_1.ResponseOptions({ body: 'response1' }));
+ sampleRequest2 = new static_request_1.Request(base.merge(new base_request_options_1.RequestOptions({ url: 'https://google.com' })));
+ sampleResponse2 = new static_response_1.Response(new base_response_options_1.ResponseOptions({ body: 'response2' }));
+ });
+ testing_internal_1.it('should create a new MockBackend', function () { testing_internal_1.expect(backend).toBeAnInstanceOf(mock_backend_1.MockBackend); });
+ testing_internal_1.it('should create a new MockConnection', function () { testing_internal_1.expect(backend.createConnection(sampleRequest1)).toBeAnInstanceOf(mock_backend_1.MockConnection); });
+ testing_internal_1.it('should create a new connection and allow subscription', function () {
+ var connection = backend.createConnection(sampleRequest1);
+ connection.response.subscribe(function () { });
+ });
+ testing_internal_1.it('should allow responding after subscription', testing_internal_1.inject([testing_internal_1.AsyncTestCompleter], function (async) {
+ var connection = backend.createConnection(sampleRequest1);
+ connection.response.subscribe(function (res) { async.done(); });
+ connection.mockRespond(sampleResponse1);
+ }));
+ testing_internal_1.it('should allow subscribing after responding', testing_internal_1.inject([testing_internal_1.AsyncTestCompleter], function (async) {
+ var connection = backend.createConnection(sampleRequest1);
+ connection.mockRespond(sampleResponse1);
+ connection.response.subscribe(function (res) { async.done(); });
+ }));
+ testing_internal_1.it('should allow responding after subscription with an error', testing_internal_1.inject([testing_internal_1.AsyncTestCompleter], function (async) {
+ var connection = backend.createConnection(sampleRequest1);
+ connection.response.subscribe(null, function () { async.done(); });
+ connection.mockError(new Error('nope'));
+ }));
+ testing_internal_1.it('should not throw when there are no unresolved requests', testing_internal_1.inject([testing_internal_1.AsyncTestCompleter], function (async) {
+ var connection = backend.createConnection(sampleRequest1);
+ connection.response.subscribe(function () { async.done(); });
+ connection.mockRespond(sampleResponse1);
+ backend.verifyNoPendingRequests();
+ }));
+ testing_internal_1.xit('should throw when there are unresolved requests', testing_internal_1.inject([testing_internal_1.AsyncTestCompleter], function (async) {
+ var connection = backend.createConnection(sampleRequest1);
+ connection.response.subscribe(function () { async.done(); });
+ backend.verifyNoPendingRequests();
+ }));
+ testing_internal_1.it('should work when requests are resolved out of order', testing_internal_1.inject([testing_internal_1.AsyncTestCompleter], function (async) {
+ var connection1 = backend.createConnection(sampleRequest1);
+ var connection2 = backend.createConnection(sampleRequest1);
+ connection1.response.subscribe(function () { async.done(); });
+ connection2.response.subscribe(function () { });
+ connection2.mockRespond(sampleResponse1);
+ connection1.mockRespond(sampleResponse1);
+ backend.verifyNoPendingRequests();
+ }));
+ testing_internal_1.xit('should allow double subscribing', testing_internal_1.inject([testing_internal_1.AsyncTestCompleter], function (async) {
+ var responses = [sampleResponse1, sampleResponse2];
+ backend.connections.subscribe(function (c) { return c.mockRespond(responses.shift()); });
+ var responseObservable = backend.createConnection(sampleRequest1).response;
+ responseObservable.subscribe(function (res) { return testing_internal_1.expect(res.text()).toBe('response1'); });
+ responseObservable.subscribe(function (res) { return testing_internal_1.expect(res.text()).toBe('response2'); }, null, async.done);
+ }));
+ // TODO(robwormald): readyStates are leaving?
+ testing_internal_1.it('should allow resolution of requests manually', function () {
+ var connection1 = backend.createConnection(sampleRequest1);
+ var connection2 = backend.createConnection(sampleRequest1);
+ connection1.response.subscribe(function () { });
+ connection2.response.subscribe(function () { });
+ backend.resolveAllConnections();
+ backend.verifyNoPendingRequests();
+ });
+ });
+}
+exports.main = main;
+//# sourceMappingURL=mock_backend_spec.js.map
\ No newline at end of file
diff --git a/test/http/backends/xhr_backend_spec.js b/test/http/backends/xhr_backend_spec.js
new file mode 100644
index 00000000000..d24676c4338
--- /dev/null
+++ b/test/http/backends/xhr_backend_spec.js
@@ -0,0 +1,155 @@
+var __extends = (this && this.__extends) || function (d, b) {
+ for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
+ function __() { this.constructor = d; }
+ d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
+};
+var testing_internal_1 = require('angular2/testing_internal');
+var browser_xhr_1 = require('angular2/src/http/backends/browser_xhr');
+var xhr_backend_1 = require('angular2/src/http/backends/xhr_backend');
+var core_1 = require('angular2/core');
+var static_request_1 = require('angular2/src/http/static_request');
+var headers_1 = require('angular2/src/http/headers');
+var collection_1 = require('angular2/src/facade/collection');
+var base_request_options_1 = require('angular2/src/http/base_request_options');
+var base_response_options_1 = require('angular2/src/http/base_response_options');
+var enums_1 = require('angular2/src/http/enums');
+var abortSpy;
+var sendSpy;
+var openSpy;
+var setRequestHeaderSpy;
+var addEventListenerSpy;
+var existingXHRs = [];
+var unused;
+var MockBrowserXHR = (function (_super) {
+ __extends(MockBrowserXHR, _super);
+ function MockBrowserXHR() {
+ _super.call(this);
+ this.callbacks = new collection_1.Map();
+ var spy = new testing_internal_1.SpyObject();
+ this.abort = abortSpy = spy.spy('abort');
+ this.send = sendSpy = spy.spy('send');
+ this.open = openSpy = spy.spy('open');
+ this.setRequestHeader = setRequestHeaderSpy = spy.spy('setRequestHeader');
+ }
+ MockBrowserXHR.prototype.setStatusCode = function (status) { this.status = status; };
+ MockBrowserXHR.prototype.setResponse = function (value) { this.response = value; };
+ MockBrowserXHR.prototype.setResponseText = function (value) { this.responseText = value; };
+ MockBrowserXHR.prototype.addEventListener = function (type, cb) { this.callbacks.set(type, cb); };
+ MockBrowserXHR.prototype.removeEventListener = function (type, cb) { this.callbacks.delete(type); };
+ MockBrowserXHR.prototype.dispatchEvent = function (type) { this.callbacks.get(type)({}); };
+ MockBrowserXHR.prototype.build = function () {
+ var xhr = new MockBrowserXHR();
+ existingXHRs.push(xhr);
+ return xhr;
+ };
+ return MockBrowserXHR;
+})(browser_xhr_1.BrowserXhr);
+function main() {
+ testing_internal_1.describe('XHRBackend', function () {
+ var backend;
+ var sampleRequest;
+ testing_internal_1.beforeEach(function () {
+ var injector = core_1.Injector.resolveAndCreate([
+ core_1.provide(base_response_options_1.ResponseOptions, { useClass: base_response_options_1.BaseResponseOptions }),
+ core_1.provide(browser_xhr_1.BrowserXhr, { useClass: MockBrowserXHR }),
+ xhr_backend_1.XHRBackend
+ ]);
+ backend = injector.get(xhr_backend_1.XHRBackend);
+ var base = new base_request_options_1.BaseRequestOptions();
+ sampleRequest = new static_request_1.Request(base.merge(new base_request_options_1.RequestOptions({ url: 'https://google.com' })));
+ });
+ testing_internal_1.afterEach(function () { existingXHRs = []; });
+ testing_internal_1.it('should create a connection', function () { testing_internal_1.expect(function () { return backend.createConnection(sampleRequest); }).not.toThrow(); });
+ testing_internal_1.describe('XHRConnection', function () {
+ testing_internal_1.it('should use the injected BaseResponseOptions to create the response', testing_internal_1.inject([testing_internal_1.AsyncTestCompleter], function (async) {
+ var connection = new xhr_backend_1.XHRConnection(sampleRequest, new MockBrowserXHR(), new base_response_options_1.ResponseOptions({ type: enums_1.ResponseTypes.Error }));
+ connection.response.subscribe(function (res) {
+ testing_internal_1.expect(res.type).toBe(enums_1.ResponseTypes.Error);
+ async.done();
+ });
+ existingXHRs[0].dispatchEvent('load');
+ }));
+ testing_internal_1.it('should complete a request', testing_internal_1.inject([testing_internal_1.AsyncTestCompleter], function (async) {
+ var connection = new xhr_backend_1.XHRConnection(sampleRequest, new MockBrowserXHR(), new base_response_options_1.ResponseOptions({ type: enums_1.ResponseTypes.Error }));
+ connection.response.subscribe(function (res) { testing_internal_1.expect(res.type).toBe(enums_1.ResponseTypes.Error); }, null, function () { async.done(); });
+ existingXHRs[0].dispatchEvent('load');
+ }));
+ testing_internal_1.it('should call abort when disposed', function () {
+ var connection = new xhr_backend_1.XHRConnection(sampleRequest, new MockBrowserXHR());
+ var request = connection.response.subscribe();
+ request.unsubscribe();
+ testing_internal_1.expect(abortSpy).toHaveBeenCalled();
+ });
+ testing_internal_1.it('should create an error Response on error', testing_internal_1.inject([testing_internal_1.AsyncTestCompleter], function (async) {
+ var connection = new xhr_backend_1.XHRConnection(sampleRequest, new MockBrowserXHR(), new base_response_options_1.ResponseOptions({ type: enums_1.ResponseTypes.Error }));
+ connection.response.subscribe(null, function (res) {
+ testing_internal_1.expect(res.type).toBe(enums_1.ResponseTypes.Error);
+ async.done();
+ });
+ existingXHRs[0].dispatchEvent('error');
+ }));
+ testing_internal_1.it('should call open with method and url when subscribed to', function () {
+ var connection = new xhr_backend_1.XHRConnection(sampleRequest, new MockBrowserXHR());
+ testing_internal_1.expect(openSpy).not.toHaveBeenCalled();
+ connection.response.subscribe();
+ testing_internal_1.expect(openSpy).toHaveBeenCalledWith('GET', sampleRequest.url);
+ });
+ testing_internal_1.it('should call send on the backend with request body when subscribed to', function () {
+ var body = 'Some body to love';
+ var base = new base_request_options_1.BaseRequestOptions();
+ var connection = new xhr_backend_1.XHRConnection(new static_request_1.Request(base.merge(new base_request_options_1.RequestOptions({ body: body }))), new MockBrowserXHR());
+ testing_internal_1.expect(sendSpy).not.toHaveBeenCalled();
+ connection.response.subscribe();
+ testing_internal_1.expect(sendSpy).toHaveBeenCalledWith(body);
+ });
+ testing_internal_1.it('should attach headers to the request', function () {
+ var headers = new headers_1.Headers({ 'Content-Type': 'text/xml', 'Breaking-Bad': '<3', 'X-Multi': ['a', 'b'] });
+ var base = new base_request_options_1.BaseRequestOptions();
+ var connection = new xhr_backend_1.XHRConnection(new static_request_1.Request(base.merge(new base_request_options_1.RequestOptions({ headers: headers }))), new MockBrowserXHR());
+ connection.response.subscribe();
+ testing_internal_1.expect(setRequestHeaderSpy).toHaveBeenCalledWith('Content-Type', 'text/xml');
+ testing_internal_1.expect(setRequestHeaderSpy).toHaveBeenCalledWith('Breaking-Bad', '<3');
+ testing_internal_1.expect(setRequestHeaderSpy).toHaveBeenCalledWith('X-Multi', 'a,b');
+ });
+ testing_internal_1.it('should return the correct status code', testing_internal_1.inject([testing_internal_1.AsyncTestCompleter], function (async) {
+ var statusCode = 418;
+ var connection = new xhr_backend_1.XHRConnection(sampleRequest, new MockBrowserXHR(), new base_response_options_1.ResponseOptions({ status: statusCode }));
+ connection.response.subscribe(function (res) {
+ testing_internal_1.expect(res.status).toBe(statusCode);
+ async.done();
+ });
+ existingXHRs[0].setStatusCode(statusCode);
+ existingXHRs[0].dispatchEvent('load');
+ }));
+ testing_internal_1.it('should normalize IE\'s 1223 status code into 204', testing_internal_1.inject([testing_internal_1.AsyncTestCompleter], function (async) {
+ var statusCode = 1223;
+ var normalizedCode = 204;
+ var connection = new xhr_backend_1.XHRConnection(sampleRequest, new MockBrowserXHR(), new base_response_options_1.ResponseOptions({ status: statusCode }));
+ connection.response.subscribe(function (res) {
+ testing_internal_1.expect(res.status).toBe(normalizedCode);
+ async.done();
+ });
+ existingXHRs[0].setStatusCode(statusCode);
+ existingXHRs[0].dispatchEvent('load');
+ }));
+ testing_internal_1.it('should normalize responseText and response', testing_internal_1.inject([testing_internal_1.AsyncTestCompleter], function (async) {
+ var responseBody = 'Doge';
+ var connection1 = new xhr_backend_1.XHRConnection(sampleRequest, new MockBrowserXHR(), new base_response_options_1.ResponseOptions());
+ var connection2 = new xhr_backend_1.XHRConnection(sampleRequest, new MockBrowserXHR(), new base_response_options_1.ResponseOptions());
+ connection1.response.subscribe(function (res) {
+ testing_internal_1.expect(res.text()).toBe(responseBody);
+ connection2.response.subscribe(function (ress) {
+ testing_internal_1.expect(ress.text()).toBe(responseBody);
+ async.done();
+ });
+ existingXHRs[1].setResponse(responseBody);
+ existingXHRs[1].dispatchEvent('load');
+ });
+ existingXHRs[0].setResponseText(responseBody);
+ existingXHRs[0].dispatchEvent('load');
+ }));
+ });
+ });
+}
+exports.main = main;
+//# sourceMappingURL=xhr_backend_spec.js.map
\ No newline at end of file
diff --git a/test/http/base_request_options_spec.js b/test/http/base_request_options_spec.js
new file mode 100644
index 00000000000..8f1d96e9f32
--- /dev/null
+++ b/test/http/base_request_options_spec.js
@@ -0,0 +1,20 @@
+var testing_internal_1 = require('angular2/testing_internal');
+var base_request_options_1 = require('angular2/src/http/base_request_options');
+var enums_1 = require('angular2/src/http/enums');
+function main() {
+ testing_internal_1.describe('BaseRequestOptions', function () {
+ testing_internal_1.it('should create a new object when calling merge', function () {
+ var options1 = new base_request_options_1.BaseRequestOptions();
+ var options2 = options1.merge(new base_request_options_1.RequestOptions({ method: enums_1.RequestMethods.Delete }));
+ testing_internal_1.expect(options2).not.toBe(options1);
+ testing_internal_1.expect(options2.method).toBe(enums_1.RequestMethods.Delete);
+ });
+ testing_internal_1.it('should retain previously merged values when merging again', function () {
+ var options1 = new base_request_options_1.BaseRequestOptions();
+ var options2 = options1.merge(new base_request_options_1.RequestOptions({ method: enums_1.RequestMethods.Delete }));
+ testing_internal_1.expect(options2.method).toBe(enums_1.RequestMethods.Delete);
+ });
+ });
+}
+exports.main = main;
+//# sourceMappingURL=base_request_options_spec.js.map
\ No newline at end of file
diff --git a/test/http/headers_spec.js b/test/http/headers_spec.js
new file mode 100644
index 00000000000..c63d7699227
--- /dev/null
+++ b/test/http/headers_spec.js
@@ -0,0 +1,51 @@
+var headers_1 = require('angular2/src/http/headers');
+var collection_1 = require('angular2/src/facade/collection');
+var testing_internal_1 = require('angular2/testing_internal');
+function main() {
+ testing_internal_1.describe('Headers', function () {
+ testing_internal_1.it('should conform to spec', function () {
+ // Examples borrowed from https://developer.mozilla.org/en-US/docs/Web/API/Headers/Headers
+ // Spec at https://fetch.spec.whatwg.org/#dom-headers
+ var firstHeaders = new headers_1.Headers(); // Currently empty
+ firstHeaders.append('Content-Type', 'image/jpeg');
+ testing_internal_1.expect(firstHeaders.get('Content-Type')).toBe('image/jpeg');
+ var httpHeaders = collection_1.StringMapWrapper.create();
+ collection_1.StringMapWrapper.set(httpHeaders, 'Content-Type', 'image/jpeg');
+ collection_1.StringMapWrapper.set(httpHeaders, 'Accept-Charset', 'utf-8');
+ collection_1.StringMapWrapper.set(httpHeaders, 'X-My-Custom-Header', 'Zeke are cool');
+ var secondHeaders = new headers_1.Headers(httpHeaders);
+ var secondHeadersObj = new headers_1.Headers(secondHeaders);
+ testing_internal_1.expect(secondHeadersObj.get('Content-Type')).toBe('image/jpeg');
+ });
+ testing_internal_1.describe('initialization', function () {
+ testing_internal_1.it('should merge values in provided dictionary', function () {
+ var map = collection_1.StringMapWrapper.create();
+ collection_1.StringMapWrapper.set(map, 'foo', 'bar');
+ var headers = new headers_1.Headers(map);
+ testing_internal_1.expect(headers.get('foo')).toBe('bar');
+ testing_internal_1.expect(headers.getAll('foo')).toEqual(['bar']);
+ });
+ });
+ testing_internal_1.describe('.set()', function () {
+ testing_internal_1.it('should clear all values and re-set for the provided key', function () {
+ var map = collection_1.StringMapWrapper.create();
+ collection_1.StringMapWrapper.set(map, 'foo', 'bar');
+ var headers = new headers_1.Headers(map);
+ testing_internal_1.expect(headers.get('foo')).toBe('bar');
+ testing_internal_1.expect(headers.getAll('foo')).toEqual(['bar']);
+ headers.set('foo', 'baz');
+ testing_internal_1.expect(headers.get('foo')).toBe('baz');
+ testing_internal_1.expect(headers.getAll('foo')).toEqual(['baz']);
+ });
+ testing_internal_1.it('should convert input array to string', function () {
+ var headers = new headers_1.Headers();
+ var inputArr = ['bar', 'baz'];
+ headers.set('foo', inputArr);
+ testing_internal_1.expect(/bar, ?baz/g.test(headers.get('foo'))).toBe(true);
+ testing_internal_1.expect(/bar, ?baz/g.test(headers.getAll('foo')[0])).toBe(true);
+ });
+ });
+ });
+}
+exports.main = main;
+//# sourceMappingURL=headers_spec.js.map
\ No newline at end of file
diff --git a/test/http/http_spec.js b/test/http/http_spec.js
new file mode 100644
index 00000000000..ea51c65878d
--- /dev/null
+++ b/test/http/http_spec.js
@@ -0,0 +1,295 @@
+var __extends = (this && this.__extends) || function (d, b) {
+ for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
+ function __() { this.constructor = d; }
+ d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
+};
+var testing_internal_1 = require('angular2/testing_internal');
+var core_1 = require('angular2/core');
+var mock_backend_1 = require('angular2/src/http/backends/mock_backend');
+var http_1 = require('angular2/http');
+var Rx = require('@reactivex/rxjs/dist/cjs/Rx');
+var Observable = Rx.Observable, Subject = Rx.Subject;
+var SpyObserver = (function (_super) {
+ __extends(SpyObserver, _super);
+ function SpyObserver() {
+ _super.call(this);
+ this.onNext = this.spy('onNext');
+ this.onError = this.spy('onError');
+ this.onCompleted = this.spy('onCompleted');
+ }
+ return SpyObserver;
+})(testing_internal_1.SpyObject);
+function main() {
+ testing_internal_1.describe('injectables', function () {
+ var url = 'http://foo.bar';
+ var http;
+ var parentInjector;
+ var childInjector;
+ var jsonpBackend;
+ var xhrBackend;
+ var jsonp;
+ testing_internal_1.it('should allow using jsonpInjectables and httpInjectables in same injector', testing_internal_1.inject([testing_internal_1.AsyncTestCompleter], function (async) {
+ parentInjector = core_1.Injector.resolveAndCreate([
+ core_1.provide(http_1.XHRBackend, { useClass: mock_backend_1.MockBackend }),
+ core_1.provide(http_1.JSONPBackend, { useClass: mock_backend_1.MockBackend })
+ ]);
+ childInjector = parentInjector.resolveAndCreateChild([
+ http_1.HTTP_PROVIDERS,
+ http_1.JSONP_PROVIDERS,
+ core_1.provide(http_1.XHRBackend, { useClass: mock_backend_1.MockBackend }),
+ core_1.provide(http_1.JSONPBackend, { useClass: mock_backend_1.MockBackend })
+ ]);
+ http = childInjector.get(http_1.Http);
+ jsonp = childInjector.get(http_1.Jsonp);
+ jsonpBackend = childInjector.get(http_1.JSONPBackend);
+ xhrBackend = childInjector.get(http_1.XHRBackend);
+ var xhrCreatedConnections = 0;
+ var jsonpCreatedConnections = 0;
+ xhrBackend.connections.subscribe(function () {
+ xhrCreatedConnections++;
+ testing_internal_1.expect(xhrCreatedConnections).toEqual(1);
+ if (jsonpCreatedConnections) {
+ async.done();
+ }
+ });
+ http.get(url).subscribe(function () { });
+ jsonpBackend.connections.subscribe(function () {
+ jsonpCreatedConnections++;
+ testing_internal_1.expect(jsonpCreatedConnections).toEqual(1);
+ if (xhrCreatedConnections) {
+ async.done();
+ }
+ });
+ jsonp.request(url).subscribe(function () { });
+ }));
+ });
+ testing_internal_1.describe('http', function () {
+ var url = 'http://foo.bar';
+ var http;
+ var injector;
+ var backend;
+ var baseResponse;
+ var jsonp;
+ testing_internal_1.beforeEach(function () {
+ injector = core_1.Injector.resolveAndCreate([
+ http_1.BaseRequestOptions,
+ mock_backend_1.MockBackend,
+ core_1.provide(http_1.Http, {
+ useFactory: function (backend, defaultOptions) {
+ return new http_1.Http(backend, defaultOptions);
+ },
+ deps: [mock_backend_1.MockBackend, http_1.BaseRequestOptions]
+ }),
+ core_1.provide(http_1.Jsonp, {
+ useFactory: function (backend, defaultOptions) {
+ return new http_1.Jsonp(backend, defaultOptions);
+ },
+ deps: [mock_backend_1.MockBackend, http_1.BaseRequestOptions]
+ })
+ ]);
+ http = injector.get(http_1.Http);
+ jsonp = injector.get(http_1.Jsonp);
+ backend = injector.get(mock_backend_1.MockBackend);
+ baseResponse = new http_1.Response(new http_1.ResponseOptions({ body: 'base response' }));
+ });
+ testing_internal_1.afterEach(function () { return backend.verifyNoPendingRequests(); });
+ testing_internal_1.describe('Http', function () {
+ testing_internal_1.describe('.request()', function () {
+ testing_internal_1.it('should return an Observable', function () { testing_internal_1.expect(http.request(url)).toBeAnInstanceOf(Observable); });
+ testing_internal_1.it('should accept a fully-qualified request as its only parameter', testing_internal_1.inject([testing_internal_1.AsyncTestCompleter], function (async) {
+ backend.connections.subscribe(function (c) {
+ testing_internal_1.expect(c.request.url).toBe('https://google.com');
+ c.mockRespond(new http_1.Response(new http_1.ResponseOptions({ body: 'Thank you' })));
+ async.done();
+ });
+ http.request(new http_1.Request(new http_1.RequestOptions({ url: 'https://google.com' })))
+ .subscribe(function (res) { });
+ }));
+ testing_internal_1.it('should perform a get request for given url if only passed a string', testing_internal_1.inject([testing_internal_1.AsyncTestCompleter], function (async) {
+ backend.connections.subscribe(function (c) { return c.mockRespond(baseResponse); });
+ http.request('http://basic.connection')
+ .subscribe(function (res) {
+ testing_internal_1.expect(res.text()).toBe('base response');
+ async.done();
+ });
+ }));
+ testing_internal_1.it('should perform a get request and complete the response', testing_internal_1.inject([testing_internal_1.AsyncTestCompleter], function (async) {
+ backend.connections.subscribe(function (c) { return c.mockRespond(baseResponse); });
+ http.request('http://basic.connection')
+ .subscribe(function (res) { testing_internal_1.expect(res.text()).toBe('base response'); }, null, function () { async.done(); });
+ }));
+ testing_internal_1.it('should perform multiple get requests and complete the responses', testing_internal_1.inject([testing_internal_1.AsyncTestCompleter], function (async) {
+ backend.connections.subscribe(function (c) { return c.mockRespond(baseResponse); });
+ http.request('http://basic.connection')
+ .subscribe(function (res) { testing_internal_1.expect(res.text()).toBe('base response'); });
+ http.request('http://basic.connection')
+ .subscribe(function (res) { testing_internal_1.expect(res.text()).toBe('base response'); }, null, function () { async.done(); });
+ }));
+ // TODO: make dart not complain about "argument type 'Map' cannot be assigned to the
+ // parameter type 'IRequestOptions'"
+ // xit('should perform a get request for given url if passed a dictionary',
+ // inject([AsyncTestCompleter], async => {
+ // ObservableWrapper.subscribe(backend.connections, c => c.mockRespond(baseResponse));
+ // ObservableWrapper.subscribe(http.request(url, {method: RequestMethods.GET}), res =>
+ // {
+ // expect(res.text()).toBe('base response');
+ // async.done();
+ // });
+ // }));
+ testing_internal_1.it('should throw if url is not a string or Request', function () {
+ var req = {};
+ testing_internal_1.expect(function () { return http.request(req); })
+ .toThrowError('First argument must be a url string or Request instance.');
+ });
+ });
+ testing_internal_1.describe('.get()', function () {
+ testing_internal_1.it('should perform a get request for given url', testing_internal_1.inject([testing_internal_1.AsyncTestCompleter], function (async) {
+ backend.connections.subscribe(function (c) {
+ testing_internal_1.expect(c.request.method).toBe(http_1.RequestMethods.Get);
+ backend.resolveAllConnections();
+ async.done();
+ });
+ http.get(url).subscribe(function (res) { });
+ }));
+ });
+ testing_internal_1.describe('.post()', function () {
+ testing_internal_1.it('should perform a post request for given url', testing_internal_1.inject([testing_internal_1.AsyncTestCompleter], function (async) {
+ backend.connections.subscribe(function (c) {
+ testing_internal_1.expect(c.request.method).toBe(http_1.RequestMethods.Post);
+ backend.resolveAllConnections();
+ async.done();
+ });
+ http.post(url, 'post me').subscribe(function (res) { });
+ }));
+ testing_internal_1.it('should attach the provided body to the request', testing_internal_1.inject([testing_internal_1.AsyncTestCompleter], function (async) {
+ var body = 'this is my post body';
+ backend.connections.subscribe(function (c) {
+ testing_internal_1.expect(c.request.text()).toBe(body);
+ backend.resolveAllConnections();
+ async.done();
+ });
+ http.post(url, body).subscribe(function (res) { });
+ }));
+ });
+ testing_internal_1.describe('.put()', function () {
+ testing_internal_1.it('should perform a put request for given url', testing_internal_1.inject([testing_internal_1.AsyncTestCompleter], function (async) {
+ backend.connections.subscribe(function (c) {
+ testing_internal_1.expect(c.request.method).toBe(http_1.RequestMethods.Put);
+ backend.resolveAllConnections();
+ async.done();
+ });
+ http.put(url, 'put me').subscribe(function (res) { });
+ }));
+ testing_internal_1.it('should attach the provided body to the request', testing_internal_1.inject([testing_internal_1.AsyncTestCompleter], function (async) {
+ var body = 'this is my put body';
+ backend.connections.subscribe(function (c) {
+ testing_internal_1.expect(c.request.text()).toBe(body);
+ backend.resolveAllConnections();
+ async.done();
+ });
+ http.put(url, body).subscribe(function (res) { });
+ }));
+ });
+ testing_internal_1.describe('.delete()', function () {
+ testing_internal_1.it('should perform a delete request for given url', testing_internal_1.inject([testing_internal_1.AsyncTestCompleter], function (async) {
+ backend.connections.subscribe(function (c) {
+ testing_internal_1.expect(c.request.method).toBe(http_1.RequestMethods.Delete);
+ backend.resolveAllConnections();
+ async.done();
+ });
+ http.delete(url).subscribe(function (res) { });
+ }));
+ });
+ testing_internal_1.describe('.patch()', function () {
+ testing_internal_1.it('should perform a patch request for given url', testing_internal_1.inject([testing_internal_1.AsyncTestCompleter], function (async) {
+ backend.connections.subscribe(function (c) {
+ testing_internal_1.expect(c.request.method).toBe(http_1.RequestMethods.Patch);
+ backend.resolveAllConnections();
+ async.done();
+ });
+ http.patch(url, 'this is my patch body').subscribe(function (res) { });
+ }));
+ testing_internal_1.it('should attach the provided body to the request', testing_internal_1.inject([testing_internal_1.AsyncTestCompleter], function (async) {
+ var body = 'this is my patch body';
+ backend.connections.subscribe(function (c) {
+ testing_internal_1.expect(c.request.text()).toBe(body);
+ backend.resolveAllConnections();
+ async.done();
+ });
+ http.patch(url, body).subscribe(function (res) { });
+ }));
+ });
+ testing_internal_1.describe('.head()', function () {
+ testing_internal_1.it('should perform a head request for given url', testing_internal_1.inject([testing_internal_1.AsyncTestCompleter], function (async) {
+ backend.connections.subscribe(function (c) {
+ testing_internal_1.expect(c.request.method).toBe(http_1.RequestMethods.Head);
+ backend.resolveAllConnections();
+ async.done();
+ });
+ http.head(url).subscribe(function (res) { });
+ }));
+ });
+ testing_internal_1.describe('searchParams', function () {
+ testing_internal_1.it('should append search params to url', testing_internal_1.inject([testing_internal_1.AsyncTestCompleter], function (async) {
+ var params = new http_1.URLSearchParams();
+ params.append('q', 'puppies');
+ backend.connections.subscribe(function (c) {
+ testing_internal_1.expect(c.request.url).toEqual('https://www.google.com?q=puppies');
+ backend.resolveAllConnections();
+ async.done();
+ });
+ http.get('https://www.google.com', new http_1.RequestOptions({ search: params }))
+ .subscribe(function (res) { });
+ }));
+ testing_internal_1.it('should append string search params to url', testing_internal_1.inject([testing_internal_1.AsyncTestCompleter], function (async) {
+ backend.connections.subscribe(function (c) {
+ testing_internal_1.expect(c.request.url).toEqual('https://www.google.com?q=piggies');
+ backend.resolveAllConnections();
+ async.done();
+ });
+ http.get('https://www.google.com', new http_1.RequestOptions({ search: 'q=piggies' }))
+ .subscribe(function (res) { });
+ }));
+ testing_internal_1.it('should produce valid url when url already contains a query', testing_internal_1.inject([testing_internal_1.AsyncTestCompleter], function (async) {
+ backend.connections.subscribe(function (c) {
+ testing_internal_1.expect(c.request.url).toEqual('https://www.google.com?q=angular&as_eq=1.x');
+ backend.resolveAllConnections();
+ async.done();
+ });
+ http.get('https://www.google.com?q=angular', new http_1.RequestOptions({ search: 'as_eq=1.x' }))
+ .subscribe(function (res) { });
+ }));
+ });
+ testing_internal_1.describe('string method names', function () {
+ testing_internal_1.it('should allow case insensitive strings for method names', function () {
+ testing_internal_1.inject([testing_internal_1.AsyncTestCompleter], function (async) {
+ backend.connections.subscribe(function (c) {
+ testing_internal_1.expect(c.request.method)
+ .toBe(http_1.RequestMethods.Post);
+ c.mockRespond(new http_1.Response(new http_1.ResponseOptions({ body: 'Thank you' })));
+ async.done();
+ });
+ http.request(new http_1.Request(new http_1.RequestOptions({ url: 'https://google.com', method: 'PosT' })))
+ .subscribe(function (res) { });
+ });
+ });
+ testing_internal_1.it('should throw when invalid string parameter is passed for method name', function () {
+ testing_internal_1.expect(function () {
+ http.request(new http_1.Request(new http_1.RequestOptions({ url: 'https://google.com', method: 'Invalid' })));
+ }).toThrowError('Invalid request method. The method "Invalid" is not supported.');
+ });
+ });
+ });
+ testing_internal_1.describe('Jsonp', function () {
+ testing_internal_1.describe('.request()', function () {
+ testing_internal_1.it('should throw if url is not a string or Request', function () {
+ var req = {};
+ testing_internal_1.expect(function () { return jsonp.request(req); })
+ .toThrowError('First argument must be a url string or Request instance.');
+ });
+ });
+ });
+ });
+}
+exports.main = main;
+//# sourceMappingURL=http_spec.js.map
\ No newline at end of file
diff --git a/test/http/url_search_params_spec.js b/test/http/url_search_params_spec.js
new file mode 100644
index 00000000000..8696d4920d4
--- /dev/null
+++ b/test/http/url_search_params_spec.js
@@ -0,0 +1,63 @@
+var testing_internal_1 = require('angular2/testing_internal');
+var url_search_params_1 = require('angular2/src/http/url_search_params');
+function main() {
+ testing_internal_1.describe('URLSearchParams', function () {
+ testing_internal_1.it('should conform to spec', function () {
+ var paramsString = "q=URLUtils.searchParams&topic=api";
+ var searchParams = new url_search_params_1.URLSearchParams(paramsString);
+ // Tests borrowed from example at
+ // https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams
+ // Compliant with spec described at https://url.spec.whatwg.org/#urlsearchparams
+ testing_internal_1.expect(searchParams.has("topic")).toBe(true);
+ testing_internal_1.expect(searchParams.has("foo")).toBe(false);
+ testing_internal_1.expect(searchParams.get("topic")).toEqual("api");
+ testing_internal_1.expect(searchParams.getAll("topic")).toEqual(["api"]);
+ testing_internal_1.expect(searchParams.get("foo")).toBe(null);
+ searchParams.append("topic", "webdev");
+ testing_internal_1.expect(searchParams.getAll("topic")).toEqual(["api", "webdev"]);
+ testing_internal_1.expect(searchParams.toString()).toEqual("q=URLUtils.searchParams&topic=api&topic=webdev");
+ searchParams.delete("topic");
+ testing_internal_1.expect(searchParams.toString()).toEqual("q=URLUtils.searchParams");
+ // Test default constructor
+ testing_internal_1.expect(new url_search_params_1.URLSearchParams().toString()).toBe("");
+ });
+ testing_internal_1.it('should support map-like merging operation via setAll()', function () {
+ var mapA = new url_search_params_1.URLSearchParams('a=1&a=2&a=3&c=8');
+ var mapB = new url_search_params_1.URLSearchParams('a=4&a=5&a=6&b=7');
+ mapA.setAll(mapB);
+ testing_internal_1.expect(mapA.has('a')).toBe(true);
+ testing_internal_1.expect(mapA.has('b')).toBe(true);
+ testing_internal_1.expect(mapA.has('c')).toBe(true);
+ testing_internal_1.expect(mapA.getAll('a')).toEqual(['4']);
+ testing_internal_1.expect(mapA.getAll('b')).toEqual(['7']);
+ testing_internal_1.expect(mapA.getAll('c')).toEqual(['8']);
+ testing_internal_1.expect(mapA.toString()).toEqual('a=4&c=8&b=7');
+ });
+ testing_internal_1.it('should support multimap-like merging operation via appendAll()', function () {
+ var mapA = new url_search_params_1.URLSearchParams('a=1&a=2&a=3&c=8');
+ var mapB = new url_search_params_1.URLSearchParams('a=4&a=5&a=6&b=7');
+ mapA.appendAll(mapB);
+ testing_internal_1.expect(mapA.has('a')).toBe(true);
+ testing_internal_1.expect(mapA.has('b')).toBe(true);
+ testing_internal_1.expect(mapA.has('c')).toBe(true);
+ testing_internal_1.expect(mapA.getAll('a')).toEqual(['1', '2', '3', '4', '5', '6']);
+ testing_internal_1.expect(mapA.getAll('b')).toEqual(['7']);
+ testing_internal_1.expect(mapA.getAll('c')).toEqual(['8']);
+ testing_internal_1.expect(mapA.toString()).toEqual('a=1&a=2&a=3&a=4&a=5&a=6&c=8&b=7');
+ });
+ testing_internal_1.it('should support multimap-like merging operation via replaceAll()', function () {
+ var mapA = new url_search_params_1.URLSearchParams('a=1&a=2&a=3&c=8');
+ var mapB = new url_search_params_1.URLSearchParams('a=4&a=5&a=6&b=7');
+ mapA.replaceAll(mapB);
+ testing_internal_1.expect(mapA.has('a')).toBe(true);
+ testing_internal_1.expect(mapA.has('b')).toBe(true);
+ testing_internal_1.expect(mapA.has('c')).toBe(true);
+ testing_internal_1.expect(mapA.getAll('a')).toEqual(['4', '5', '6']);
+ testing_internal_1.expect(mapA.getAll('b')).toEqual(['7']);
+ testing_internal_1.expect(mapA.getAll('c')).toEqual(['8']);
+ testing_internal_1.expect(mapA.toString()).toEqual('a=4&a=5&a=6&c=8&b=7');
+ });
+ });
+}
+exports.main = main;
+//# sourceMappingURL=url_search_params_spec.js.map
\ No newline at end of file
diff --git a/test/mock/view_resolver_mock_spec.js b/test/mock/view_resolver_mock_spec.js
new file mode 100644
index 00000000000..97ebe6429d0
--- /dev/null
+++ b/test/mock/view_resolver_mock_spec.js
@@ -0,0 +1,113 @@
+var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") return Reflect.decorate(decorators, target, key, desc);
+ switch (arguments.length) {
+ case 2: return decorators.reduceRight(function(o, d) { return (d && d(o)) || o; }, target);
+ case 3: return decorators.reduceRight(function(o, d) { return (d && d(target, key)), void 0; }, void 0);
+ case 4: return decorators.reduceRight(function(o, d) { return (d && d(target, key, o)) || o; }, desc);
+ }
+};
+var __metadata = (this && this.__metadata) || function (k, v) {
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
+};
+var testing_internal_1 = require('angular2/testing_internal');
+var lang_1 = require('angular2/src/facade/lang');
+var view_resolver_mock_1 = require('angular2/src/mock/view_resolver_mock');
+var metadata_1 = require('angular2/src/core/metadata');
+var lang_2 = require('angular2/src/facade/lang');
+function main() {
+ testing_internal_1.describe('MockViewResolver', function () {
+ var viewResolver;
+ testing_internal_1.beforeEach(function () { viewResolver = new view_resolver_mock_1.MockViewResolver(); });
+ testing_internal_1.describe('View overriding', function () {
+ testing_internal_1.it('should fallback to the default ViewResolver when templates are not overridden', function () {
+ var view = viewResolver.resolve(SomeComponent);
+ testing_internal_1.expect(view.template).toEqual('template');
+ testing_internal_1.expect(view.directives).toEqual([SomeDirective]);
+ });
+ testing_internal_1.it('should allow overriding the @View', function () {
+ viewResolver.setView(SomeComponent, new metadata_1.ViewMetadata({ template: 'overridden template' }));
+ var view = viewResolver.resolve(SomeComponent);
+ testing_internal_1.expect(view.template).toEqual('overridden template');
+ testing_internal_1.expect(lang_2.isBlank(view.directives)).toBe(true);
+ });
+ testing_internal_1.it('should not allow overriding a view after it has been resolved', function () {
+ viewResolver.resolve(SomeComponent);
+ testing_internal_1.expect(function () {
+ viewResolver.setView(SomeComponent, new metadata_1.ViewMetadata({ template: 'overridden template' }));
+ })
+ .toThrowError("The component " + lang_1.stringify(SomeComponent) + " has already been compiled, its configuration can not be changed");
+ });
+ });
+ testing_internal_1.describe('inline template definition overriding', function () {
+ testing_internal_1.it('should allow overriding the default template', function () {
+ viewResolver.setInlineTemplate(SomeComponent, 'overridden template');
+ var view = viewResolver.resolve(SomeComponent);
+ testing_internal_1.expect(view.template).toEqual('overridden template');
+ testing_internal_1.expect(view.directives).toEqual([SomeDirective]);
+ });
+ testing_internal_1.it('should allow overriding an overriden @View', function () {
+ viewResolver.setView(SomeComponent, new metadata_1.ViewMetadata({ template: 'overridden template' }));
+ viewResolver.setInlineTemplate(SomeComponent, 'overridden template x 2');
+ var view = viewResolver.resolve(SomeComponent);
+ testing_internal_1.expect(view.template).toEqual('overridden template x 2');
+ });
+ testing_internal_1.it('should not allow overriding a view after it has been resolved', function () {
+ viewResolver.resolve(SomeComponent);
+ testing_internal_1.expect(function () { viewResolver.setInlineTemplate(SomeComponent, 'overridden template'); })
+ .toThrowError("The component " + lang_1.stringify(SomeComponent) + " has already been compiled, its configuration can not be changed");
+ });
+ });
+ testing_internal_1.describe('Directive overriding', function () {
+ testing_internal_1.it('should allow overriding a directive from the default view', function () {
+ viewResolver.overrideViewDirective(SomeComponent, SomeDirective, SomeOtherDirective);
+ var view = viewResolver.resolve(SomeComponent);
+ testing_internal_1.expect(view.directives.length).toEqual(1);
+ testing_internal_1.expect(view.directives[0]).toBe(SomeOtherDirective);
+ });
+ testing_internal_1.it('should allow overriding a directive from an overriden @View', function () {
+ viewResolver.setView(SomeComponent, new metadata_1.ViewMetadata({ directives: [SomeOtherDirective] }));
+ viewResolver.overrideViewDirective(SomeComponent, SomeOtherDirective, SomeComponent);
+ var view = viewResolver.resolve(SomeComponent);
+ testing_internal_1.expect(view.directives.length).toEqual(1);
+ testing_internal_1.expect(view.directives[0]).toBe(SomeComponent);
+ });
+ testing_internal_1.it('should throw when the overridden directive is not present', function () {
+ viewResolver.overrideViewDirective(SomeComponent, SomeOtherDirective, SomeDirective);
+ testing_internal_1.expect(function () { viewResolver.resolve(SomeComponent); })
+ .toThrowError("Overriden directive " + lang_1.stringify(SomeOtherDirective) + " not found in the template of " + lang_1.stringify(SomeComponent));
+ });
+ testing_internal_1.it('should not allow overriding a directive after its view has been resolved', function () {
+ viewResolver.resolve(SomeComponent);
+ testing_internal_1.expect(function () {
+ viewResolver.overrideViewDirective(SomeComponent, SomeDirective, SomeOtherDirective);
+ })
+ .toThrowError("The component " + lang_1.stringify(SomeComponent) + " has already been compiled, its configuration can not be changed");
+ });
+ });
+ });
+}
+exports.main = main;
+var SomeDirective = (function () {
+ function SomeDirective() {
+ }
+ return SomeDirective;
+})();
+var SomeComponent = (function () {
+ function SomeComponent() {
+ }
+ SomeComponent = __decorate([
+ metadata_1.Component({ selector: 'cmp' }),
+ metadata_1.View({
+ template: 'template',
+ directives: [SomeDirective],
+ }),
+ __metadata('design:paramtypes', [])
+ ], SomeComponent);
+ return SomeComponent;
+})();
+var SomeOtherDirective = (function () {
+ function SomeOtherDirective() {
+ }
+ return SomeOtherDirective;
+})();
+//# sourceMappingURL=view_resolver_mock_spec.js.map
\ No newline at end of file
diff --git a/test/public_api_spec.js b/test/public_api_spec.js
new file mode 100644
index 00000000000..a0199d297f7
--- /dev/null
+++ b/test/public_api_spec.js
@@ -0,0 +1,1358 @@
+var testing_internal_1 = require('angular2/testing_internal');
+var symbol_inspector_1 = require('./symbol_inspector/symbol_inspector');
+var symbol_differ_1 = require('./symbol_inspector/symbol_differ');
+// =================================================================================================
+// =================================================================================================
+// =========== S T O P - S T O P - S T O P - S T O P - S T O P - S T O P ===========
+// =================================================================================================
+// =================================================================================================
+//
+// DO NOT EDIT THIS LIST OF PUBLIC APIS UNLESS YOU GET IT CLEARED BY: mhevery, vsavkin, or tbosch!
+//
+// =================================================================================================
+// =================================================================================================
+var NG_ALL = [
+ 'APP_COMPONENT',
+ 'APP_ID',
+ 'AbstractProviderError',
+ 'AbstractProviderError.addKey()',
+ 'AbstractProviderError.constructResolvingMessage',
+ 'AbstractProviderError.constructResolvingMessage=',
+ 'AbstractProviderError.context',
+ 'AbstractProviderError.injectors',
+ 'AbstractProviderError.injectors=',
+ 'AbstractProviderError.keys',
+ 'AbstractProviderError.keys=',
+ 'AbstractProviderError.message',
+ 'AbstractProviderError.message=',
+ 'AbstractProviderError.stackTrace',
+ 'AbstractControl',
+ 'AbstractControl.dirty',
+ 'AbstractControl.errors',
+ 'AbstractControl.find()',
+ 'AbstractControl.getError()',
+ 'AbstractControl.hasError()',
+ 'AbstractControl.setErrors()',
+ 'AbstractControl.markAsDirty()',
+ 'AbstractControl.markAsPending()',
+ 'AbstractControl.markAsTouched()',
+ 'AbstractControl.pending',
+ 'AbstractControl.pristine',
+ 'AbstractControl.setParent()',
+ 'AbstractControl.status',
+ 'AbstractControl.touched',
+ 'AbstractControl.untouched',
+ 'AbstractControl.updateValueAndValidity()',
+ 'AbstractControl.valid',
+ 'AbstractControl.validator',
+ 'AbstractControl.validator=',
+ 'AbstractControl.asyncValidator',
+ 'AbstractControl.asyncValidator=',
+ 'AbstractControl.value',
+ 'AbstractControl.valueChanges',
+ 'AbstractControl.statusChanges',
+ 'AbstractControlDirective',
+ 'AbstractControlDirective.control',
+ 'AbstractControlDirective.dirty',
+ 'AbstractControlDirective.errors',
+ 'AbstractControlDirective.pristine',
+ 'AbstractControlDirective.touched',
+ 'AbstractControlDirective.untouched',
+ 'AbstractControlDirective.valid',
+ 'AbstractControlDirective.value',
+ 'AbstractControlDirective.path',
+ 'AppRootUrl',
+ 'AppRootUrl.value',
+ 'AppRootUrl.value=',
+ 'AppViewManager:js',
+ 'AppViewManager.getHostElement():js',
+ /*
+ Abstract methods
+ 'AppViewManager.attachViewInContainer()',
+ 'AppViewManager.createEmbeddedViewInContainer()',
+ 'AppViewManager.createHostViewInContainer()',
+ 'AppViewManager.createRootHostView()',
+ 'AppViewManager.destroyRootHostView()',
+ 'AppViewManager.destroyViewInContainer()',
+ 'AppViewManager.detachViewInContainer()',
+ 'AppViewManager.getComponent()',
+ 'AppViewManager.getNamedElementInComponentView()',
+ 'AppViewManager.getViewContainer()',
+ */
+ 'ApplicationRef:js',
+ 'ApplicationRef.injector:js',
+ 'ApplicationRef.zone:js',
+ 'ApplicationRef.componentTypes:js',
+ /*
+ Abstract methods
+ 'ApplicationRef.bootstrap()',
+ 'ApplicationRef.dispose()',
+ 'ApplicationRef.registerBootstrapListener()',
+ 'ApplicationRef.registerDisposeListener()',
+ 'ApplicationRef.tick()',
+ */
+ 'AsyncPipe',
+ 'AsyncPipe.onDestroy()',
+ 'AsyncPipe.transform()',
+ 'Attribute',
+ 'Attribute.attributeName',
+ 'Attribute.token',
+ 'AttributeMetadata',
+ 'AttributeMetadata.attributeName',
+ 'AttributeMetadata.token',
+ 'Binding',
+ 'Binding.dependencies',
+ 'Binding.multi',
+ 'Binding.useExisting',
+ 'Binding.useClass',
+ 'Binding.useFactory',
+ 'Binding.useValue',
+ 'Binding.token',
+ 'Binding.toAlias',
+ 'Binding.toClass',
+ 'Binding.toFactory',
+ 'Binding.toValue',
+ 'Provider',
+ 'Provider.dependencies',
+ 'Provider.multi',
+ 'Provider.useExisting',
+ 'Provider.useClass',
+ 'Provider.useFactory',
+ 'Provider.useValue',
+ 'Provider.token',
+ 'ProviderBuilder',
+ 'ProviderBuilder.toAlias()',
+ 'ProviderBuilder.toClass()',
+ 'ProviderBuilder.toFactory()',
+ 'ProviderBuilder.toValue()',
+ 'ProviderBuilder.token',
+ 'ProviderBuilder.token=',
+ 'By#all()',
+ 'By#css()',
+ 'By#directive()',
+ 'By',
+ 'CORE_DIRECTIVES',
+ 'COMMON_DIRECTIVES',
+ 'AMBIENT_DIRECTIVES:js',
+ 'ChangeDetectionError',
+ 'ChangeDetectionError.context',
+ 'ChangeDetectionError.location',
+ 'ChangeDetectionError.location=',
+ 'ChangeDetectionError.message',
+ 'ChangeDetectionError.stackTrace',
+ 'ChangeDetectionError.wrapperMessage',
+ 'ChangeDetectionStrategy#CheckAlways',
+ 'ChangeDetectionStrategy#CheckOnce',
+ 'ChangeDetectionStrategy#Checked',
+ 'ChangeDetectionStrategy#Default',
+ 'ChangeDetectionStrategy#Detached',
+ 'ChangeDetectionStrategy#OnPush',
+ 'ChangeDetectionStrategy#OnPushObserve',
+ 'ChangeDetectionStrategy#values',
+ 'ChangeDetectionStrategy',
+ 'ChangeDetectionStrategy.index',
+ 'ChangeDetectorRef',
+ /*
+ Abstract methods
+ 'ChangeDetectorRef.detach()',
+ 'ChangeDetectorRef.detectChanges()',
+ 'ChangeDetectorRef.markForCheck()',
+ 'ChangeDetectorRef.reattach()',*/
+ 'CheckboxControlValueAccessor',
+ 'CheckboxControlValueAccessor.onChange',
+ 'CheckboxControlValueAccessor.onChange=',
+ 'CheckboxControlValueAccessor.onTouched',
+ 'CheckboxControlValueAccessor.onTouched=',
+ 'CheckboxControlValueAccessor.registerOnChange()',
+ 'CheckboxControlValueAccessor.registerOnTouched()',
+ 'CheckboxControlValueAccessor.writeValue()',
+ 'Class:js',
+ 'Compiler:js',
+ /*
+ Abstract methods
+ 'Compiler.compileInHost()',
+ 'Compiler.clearCache()',
+ */
+ 'Component',
+ 'Component.bindings',
+ 'Component.providers',
+ 'Component.changeDetection',
+ 'Component.outputs',
+ 'Component.events',
+ 'Component.exportAs',
+ 'Component.host',
+ 'Component.moduleId',
+ 'Component.inputs',
+ 'Component.properties',
+ 'Component.queries',
+ 'Component.selector',
+ 'Component.viewBindings',
+ 'Component.viewProviders',
+ 'Component.directives',
+ 'Component.encapsulation',
+ 'Component.pipes',
+ 'Component.styleUrls',
+ 'Component.styles',
+ 'Component.template',
+ 'Component.templateUrl',
+ 'ComponentMetadata',
+ 'ComponentMetadata.bindings',
+ 'ComponentMetadata.providers',
+ 'ComponentMetadata.changeDetection',
+ 'ComponentMetadata.outputs',
+ 'ComponentMetadata.events',
+ 'ComponentMetadata.exportAs',
+ 'ComponentMetadata.host',
+ 'ComponentMetadata.moduleId',
+ 'ComponentMetadata.inputs',
+ 'ComponentMetadata.properties',
+ 'ComponentMetadata.queries',
+ 'ComponentMetadata.selector',
+ 'ComponentMetadata.viewBindings',
+ 'ComponentMetadata.viewProviders',
+ 'ComponentMetadata.directives',
+ 'ComponentMetadata.encapsulation',
+ 'ComponentMetadata.pipes',
+ 'ComponentMetadata.styleUrls',
+ 'ComponentMetadata.styles',
+ 'ComponentMetadata.template',
+ 'ComponentMetadata.templateUrl',
+ 'ComponentRef',
+ 'ComponentRef.componentType',
+ 'ComponentRef.componentType=',
+ 'ComponentRef.hostComponent:js',
+ 'ComponentRef.hostView:js',
+ 'ComponentRef.injector',
+ 'ComponentRef.injector=',
+ 'ComponentRef.instance',
+ 'ComponentRef.instance=',
+ 'ComponentRef.location',
+ 'ComponentRef.location=',
+ /*
+ Abstract method
+ 'ComponentRef.dispose()',
+ 'ComponentRef.hostComponentType',
+ */
+ 'ContentChild',
+ 'ContentChild.descendants',
+ 'ContentChild.first',
+ 'ContentChild.isVarBindingQuery',
+ 'ContentChild.isViewQuery',
+ 'ContentChild.selector',
+ 'ContentChild.token',
+ 'ContentChild.varBindings',
+ 'ContentChildMetadata',
+ 'ContentChildMetadata.descendants',
+ 'ContentChildMetadata.first',
+ 'ContentChildMetadata.isVarBindingQuery',
+ 'ContentChildMetadata.isViewQuery',
+ 'ContentChildMetadata.selector',
+ 'ContentChildMetadata.token',
+ 'ContentChildMetadata.varBindings',
+ 'ContentChildren',
+ 'ContentChildren.descendants',
+ 'ContentChildren.first',
+ 'ContentChildren.isVarBindingQuery',
+ 'ContentChildren.isViewQuery',
+ 'ContentChildren.selector',
+ 'ContentChildren.token',
+ 'ContentChildren.varBindings',
+ 'ContentChildrenMetadata',
+ 'ContentChildrenMetadata.descendants',
+ 'ContentChildrenMetadata.first',
+ 'ContentChildrenMetadata.isVarBindingQuery',
+ 'ContentChildrenMetadata.isViewQuery',
+ 'ContentChildrenMetadata.selector',
+ 'ContentChildrenMetadata.token',
+ 'ContentChildrenMetadata.varBindings',
+ 'Control',
+ 'Control.dirty',
+ 'Control.errors',
+ 'Control.find()',
+ 'Control.getError()',
+ 'Control.hasError()',
+ 'Control.markAsDirty()',
+ 'Control.markAsPending()',
+ 'Control.markAsTouched()',
+ 'Control.pending',
+ 'Control.pristine',
+ 'Control.registerOnChange()',
+ 'Control.setParent()',
+ 'Control.status',
+ 'Control.touched',
+ 'Control.untouched',
+ 'Control.updateValue()',
+ 'Control.updateValueAndValidity()',
+ 'Control.valid',
+ 'Control.validator',
+ 'Control.validator=',
+ 'Control.asyncValidator',
+ 'Control.asyncValidator=',
+ 'Control.value',
+ 'Control.valueChanges',
+ 'Control.statusChanges',
+ 'Control.setErrors()',
+ 'ControlArray',
+ 'ControlArray.at()',
+ 'ControlArray.controls',
+ 'ControlArray.controls=',
+ 'ControlArray.dirty',
+ 'ControlArray.errors',
+ 'ControlArray.find()',
+ 'ControlArray.getError()',
+ 'ControlArray.hasError()',
+ 'ControlArray.insert()',
+ 'ControlArray.length',
+ 'ControlArray.markAsDirty()',
+ 'ControlArray.markAsPending()',
+ 'ControlArray.markAsTouched()',
+ 'ControlArray.pending',
+ 'ControlArray.pristine',
+ 'ControlArray.push()',
+ 'ControlArray.removeAt()',
+ 'ControlArray.setParent()',
+ 'ControlArray.status',
+ 'ControlArray.touched',
+ 'ControlArray.untouched',
+ 'ControlArray.updateValueAndValidity()',
+ 'ControlArray.valid',
+ 'ControlArray.validator',
+ 'ControlArray.validator=',
+ 'ControlArray.asyncValidator',
+ 'ControlArray.asyncValidator=',
+ 'ControlArray.value',
+ 'ControlArray.valueChanges',
+ 'ControlArray.statusChanges',
+ 'ControlArray.setErrors()',
+ 'ControlContainer',
+ 'ControlContainer.control',
+ 'ControlContainer.dirty',
+ 'ControlContainer.errors',
+ 'ControlContainer.formDirective',
+ 'ControlContainer.name',
+ 'ControlContainer.name=',
+ 'ControlContainer.path',
+ 'ControlContainer.pristine',
+ 'ControlContainer.touched',
+ 'ControlContainer.untouched',
+ 'ControlContainer.valid',
+ 'ControlContainer.value',
+ 'ControlGroup',
+ 'ControlGroup.addControl()',
+ 'ControlGroup.contains()',
+ 'ControlGroup.controls',
+ 'ControlGroup.controls=',
+ 'ControlGroup.dirty',
+ 'ControlGroup.errors',
+ 'ControlGroup.exclude()',
+ 'ControlGroup.find()',
+ 'ControlGroup.getError()',
+ 'ControlGroup.hasError()',
+ 'ControlGroup.include()',
+ 'ControlGroup.markAsDirty()',
+ 'ControlGroup.markAsPending()',
+ 'ControlGroup.markAsTouched()',
+ 'ControlGroup.pending',
+ 'ControlGroup.pristine',
+ 'ControlGroup.removeControl()',
+ 'ControlGroup.setParent()',
+ 'ControlGroup.status',
+ 'ControlGroup.touched',
+ 'ControlGroup.untouched',
+ 'ControlGroup.updateValueAndValidity()',
+ 'ControlGroup.valid',
+ 'ControlGroup.validator',
+ 'ControlGroup.validator=',
+ 'ControlGroup.asyncValidator',
+ 'ControlGroup.asyncValidator=',
+ 'ControlGroup.value',
+ 'ControlGroup.valueChanges',
+ 'ControlGroup.statusChanges',
+ 'ControlGroup.setErrors()',
+ 'CurrencyPipe',
+ 'CurrencyPipe.transform()',
+ 'CyclicDependencyError',
+ 'CyclicDependencyError.addKey()',
+ 'CyclicDependencyError.constructResolvingMessage',
+ 'CyclicDependencyError.constructResolvingMessage=',
+ 'CyclicDependencyError.context',
+ 'CyclicDependencyError.injectors',
+ 'CyclicDependencyError.injectors=',
+ 'CyclicDependencyError.keys',
+ 'CyclicDependencyError.keys=',
+ 'CyclicDependencyError.message',
+ 'CyclicDependencyError.message=',
+ 'CyclicDependencyError.stackTrace',
+ 'COMMON_PIPES',
+ 'AMBIENT_PIPES:js',
+ 'DOCUMENT',
+ 'DatePipe',
+ 'DatePipe.supports()',
+ 'DatePipe.transform()',
+ 'DebugElement',
+ 'DebugElement.children',
+ 'DebugElement.componentInstance',
+ 'DebugElement.componentViewChildren',
+ 'DebugElement.elementRef',
+ /*
+ Abstract methods
+ 'DebugElement.getDirectiveInstance()',
+ 'DebugElement.getLocal()',
+ 'DebugElement.hasDirective()',
+ 'DebugElement.inject()',
+ */
+ 'DebugElement.nativeElement',
+ 'DebugElement.query()',
+ 'DebugElement.queryAll()',
+ 'DecimalPipe',
+ 'DecimalPipe.transform()',
+ 'RequiredValidator',
+ 'MinLengthValidator',
+ 'MinLengthValidator.validate()',
+ 'MaxLengthValidator',
+ 'MaxLengthValidator.validate()',
+ 'Validator:dart',
+ 'DefaultValueAccessor',
+ 'DefaultValueAccessor.onChange',
+ 'DefaultValueAccessor.onChange=',
+ 'DefaultValueAccessor.onTouched',
+ 'DefaultValueAccessor.onTouched=',
+ 'DefaultValueAccessor.registerOnChange()',
+ 'DefaultValueAccessor.registerOnTouched()',
+ 'DefaultValueAccessor.writeValue()',
+ 'Dependency#fromKey()',
+ 'Dependency',
+ 'Dependency.key',
+ 'Dependency.key=',
+ 'Dependency.lowerBoundVisibility',
+ 'Dependency.lowerBoundVisibility=',
+ 'Dependency.optional',
+ 'Dependency.optional=',
+ 'Dependency.properties',
+ 'Dependency.properties=',
+ 'Dependency.upperBoundVisibility',
+ 'Dependency.upperBoundVisibility=',
+ 'DependencyMetadata',
+ 'DependencyMetadata.token',
+ 'Directive',
+ 'Directive.bindings',
+ 'Directive.providers',
+ 'Directive.outputs',
+ 'Directive.events',
+ 'Directive.exportAs',
+ 'Directive.host',
+ 'Directive.moduleId',
+ 'Directive.inputs',
+ 'Directive.properties',
+ 'Directive.queries',
+ 'Directive.selector',
+ 'DirectiveMetadata',
+ 'DirectiveMetadata.bindings',
+ 'DirectiveMetadata.providers',
+ 'DirectiveMetadata.outputs',
+ 'DirectiveMetadata.events',
+ 'DirectiveMetadata.exportAs',
+ 'DirectiveMetadata.host',
+ 'DirectiveMetadata.moduleId',
+ 'DirectiveMetadata.inputs',
+ 'DirectiveMetadata.properties',
+ 'DirectiveMetadata.queries',
+ 'DirectiveMetadata.selector',
+ 'DirectiveResolver',
+ 'DirectiveResolver.resolve()',
+ 'DynamicComponentLoader',
+ /*
+ Abstract methods
+ 'DynamicComponentLoader.loadAsRoot()',
+ 'DynamicComponentLoader.loadIntoLocation()',
+ 'DynamicComponentLoader.loadNextToLocation()',
+ */
+ 'ELEMENT_PROBE_PROVIDERS',
+ 'ELEMENT_PROBE_BINDINGS',
+ 'ElementRef',
+ 'ElementRef.boundElementIndex',
+ 'ElementRef.boundElementIndex=',
+ 'ElementRef.nativeElement',
+ 'ElementRef.parentView',
+ 'ElementRef.parentView=',
+ 'ElementRef.renderView',
+ 'ErrorHandlingFn:dart',
+ 'Output',
+ 'Output.bindingPropertyName',
+ 'EventEmitter',
+ /*
+ Dart Stream/EventEmitter
+ */
+ 'EventEmitter.add():dart',
+ 'EventEmitter.addError():dart',
+ 'EventEmitter.any():dart',
+ 'EventEmitter.asBroadcastStream():dart',
+ 'EventEmitter.asyncExpand():dart',
+ 'EventEmitter.asyncMap():dart',
+ 'EventEmitter.close():dart',
+ 'EventEmitter.contains():dart',
+ 'EventEmitter.distinct():dart',
+ 'EventEmitter.drain():dart',
+ 'EventEmitter.elementAt():dart',
+ 'EventEmitter.every():dart',
+ 'EventEmitter.expand():dart',
+ 'EventEmitter.first:dart',
+ 'EventEmitter.firstWhere():dart',
+ 'EventEmitter.fold():dart',
+ 'EventEmitter.forEach():dart',
+ 'EventEmitter.handleError():dart',
+ 'EventEmitter.isBroadcast:dart',
+ 'EventEmitter.isEmpty:dart',
+ 'EventEmitter.join():dart',
+ 'EventEmitter.last:dart',
+ 'EventEmitter.lastWhere():dart',
+ 'EventEmitter.length:dart',
+ 'EventEmitter.listen():dart',
+ 'EventEmitter.map():dart',
+ 'EventEmitter.pipe():dart',
+ 'EventEmitter.reduce():dart',
+ 'EventEmitter.single:dart',
+ 'EventEmitter.singleWhere():dart',
+ 'EventEmitter.skip():dart',
+ 'EventEmitter.skipWhile():dart',
+ 'EventEmitter.take():dart',
+ 'EventEmitter.takeWhile():dart',
+ 'EventEmitter.timeout():dart',
+ 'EventEmitter.toList():dart',
+ 'EventEmitter.toSet():dart',
+ 'EventEmitter.transform():dart',
+ 'EventEmitter.where():dart',
+ 'ExceptionHandler',
+ 'ExceptionHandler#exceptionToString()',
+ 'ExceptionHandler.call()',
+ /*
+ RxJS API - may need to maintain as RxJS evolves
+ */
+ 'EventEmitter.mapTo():js',
+ 'EventEmitter.next():js',
+ 'EventEmitter.materialize():js',
+ 'EventEmitter.merge():js',
+ 'EventEmitter.mergeAll():js',
+ 'EventEmitter.mergeMap():js',
+ 'EventEmitter.mergeMapTo():js',
+ 'EventEmitter.multicast():js',
+ 'EventEmitter.observeOn():js',
+ 'EventEmitter.remove():js',
+ 'EventEmitter.repeat():js',
+ 'EventEmitter.retry():js',
+ 'EventEmitter.retryWhen():js',
+ 'EventEmitter.throttle():js',
+ 'EventEmitter.toPromise():js',
+ 'EventEmitter.window():js',
+ 'EventEmitter.windowCount():js',
+ 'EventEmitter.windowTime():js',
+ 'EventEmitter.windowToggle():js',
+ 'EventEmitter.windowWhen():js',
+ 'EventEmitter.withLatestFrom():js',
+ 'EventEmitter.zip():js',
+ 'EventEmitter.zipAll():js',
+ 'Observable:js',
+ 'Observable#combineLatest():js',
+ 'Observable#concat():js',
+ 'Observable#create():js',
+ 'Observable#defer():js',
+ 'Observable#empty():js',
+ 'Observable#forkJoin():js',
+ 'Observable#from():js',
+ 'Observable#fromArray():js',
+ 'Observable#fromEvent():js',
+ 'Observable#fromEventPattern():js',
+ 'Observable#fromPromise():js',
+ 'Observable#interval():js',
+ 'Observable#merge():js',
+ 'Observable#never():js',
+ 'Observable#of():js',
+ 'Observable#range():js',
+ 'Observable#throw():js',
+ 'Observable#timer():js',
+ 'Observable#zip():js',
+ 'Observable.buffer():js',
+ 'Observable.bufferCount():js',
+ 'Observable.bufferTime():js',
+ 'Observable.bufferToggle():js',
+ 'Observable.bufferWhen():js',
+ 'Observable.catch():js',
+ 'Observable.combineAll():js',
+ 'Observable.combineLatest():js',
+ 'Observable.concat():js',
+ 'Observable.concatAll():js',
+ 'Observable.concatMap():js',
+ 'Observable.concatMapTo():js',
+ 'Observable.count():js',
+ 'Observable.debounce():js',
+ 'Observable.debounceTime():js',
+ 'Observable.defaultIfEmpty():js',
+ 'Observable.delay():js',
+ 'Observable.dematerialize():js',
+ 'Observable.distinctUntilChanged():js',
+ 'Observable.do():js',
+ 'Observable.every():js',
+ 'Observable.expand():js',
+ 'Observable.filter():js',
+ 'Observable.finally():js',
+ 'Observable.first():js',
+ 'Observable.flatMap():js',
+ 'Observable.flatMapTo():js',
+ 'Observable.forEach():js',
+ 'Observable.groupBy():js',
+ 'Observable.ignoreElements():js',
+ 'Observable.last():js',
+ 'Observable.lift():js',
+ 'Observable.map():js',
+ 'Observable.mapTo():js',
+ 'Observable.materialize():js',
+ 'Observable.merge():js',
+ 'Observable.mergeAll():js',
+ 'Observable.mergeMap():js',
+ 'Observable.mergeMapTo():js',
+ 'Observable.multicast():js',
+ 'Observable.observeOn():js',
+ 'OutputMetadata',
+ 'OutputMetadata.bindingPropertyName',
+ 'enableDevMode():js',
+ 'ExpressionChangedAfterItHasBeenCheckedException',
+ 'ExpressionChangedAfterItHasBeenCheckedException.message',
+ 'ExpressionChangedAfterItHasBeenCheckedException.stackTrace',
+ 'FORM_PROVIDERS',
+ 'FORM_BINDINGS',
+ 'FORM_DIRECTIVES',
+ 'FormBuilder',
+ 'FormBuilder.array()',
+ 'FormBuilder.control()',
+ 'FormBuilder.group()',
+ 'Host',
+ 'HostBinding',
+ 'HostBinding.hostPropertyName',
+ 'HostBindingMetadata',
+ 'HostBindingMetadata.hostPropertyName',
+ 'HostListener',
+ 'HostListener.args',
+ 'HostListener.eventName',
+ 'HostListenerMetadata',
+ 'HostListenerMetadata.args',
+ 'HostListenerMetadata.eventName',
+ 'HostMetadata',
+ 'Inject',
+ 'Inject.token',
+ 'InjectMetadata',
+ 'InjectMetadata.token',
+ 'Injectable',
+ 'InjectableMetadata',
+ 'Injector#fromResolvedBindings()',
+ 'Injector#fromResolvedProviders()',
+ 'Injector#resolve()',
+ 'Injector#resolveAndCreate()',
+ 'Injector',
+ 'Injector.createChildFromResolved()',
+ 'Injector.debugContext()',
+ 'Injector.displayName',
+ 'Injector.get()',
+ 'Injector.getAt()',
+ 'Injector.getOptional()',
+ 'Injector.instantiateResolved()',
+ 'Injector.internalStrategy',
+ 'Injector.parent',
+ 'Injector.resolveAndCreateChild()',
+ 'Injector.resolveAndInstantiate()',
+ 'InstantiationError',
+ 'InstantiationError.addKey()',
+ 'InstantiationError.causeKey',
+ 'InstantiationError.context',
+ 'InstantiationError.injectors',
+ 'InstantiationError.injectors=',
+ 'InstantiationError.keys',
+ 'InstantiationError.keys=',
+ 'InstantiationError.message',
+ 'InstantiationError.stackTrace',
+ 'InstantiationError.wrapperMessage',
+ 'InvalidProviderError',
+ 'InvalidProviderError.message',
+ 'InvalidProviderError.stackTrace',
+ 'IterableDiffers#create()',
+ 'IterableDiffers#extend()',
+ 'IterableDiffers',
+ 'IterableDiffers.factories',
+ 'IterableDiffers.find()',
+ 'JsonPipe',
+ 'JsonPipe.transform()',
+ 'Key#get()',
+ 'Key#numberOfKeys',
+ 'Key',
+ 'Key.displayName',
+ 'Key.id',
+ 'Key.id=',
+ 'Key.token',
+ 'Key.token=',
+ 'KeyValueDiffers#create()',
+ 'KeyValueDiffers#extend()',
+ 'KeyValueDiffers',
+ 'KeyValueDiffers.factories',
+ 'KeyValueDiffers.find()',
+ 'LowerCasePipe',
+ 'LowerCasePipe.transform()',
+ 'NG_VALIDATORS',
+ 'NG_VALUE_ACCESSOR',
+ 'NG_ASYNC_VALIDATORS',
+ 'NgClass',
+ 'NgClass.doCheck()',
+ 'NgClass.initialClasses=',
+ 'NgClass.onDestroy()',
+ 'NgClass.rawClass=',
+ 'NgControl',
+ 'NgControl.control',
+ 'NgControl.dirty',
+ 'NgControl.errors',
+ 'NgControl.name',
+ 'NgControl.name=',
+ 'NgControl.path',
+ 'NgControl.pristine',
+ 'NgControl.touched',
+ 'NgControl.untouched',
+ 'NgControl.valid',
+ 'NgControl.validator',
+ 'NgControl.asyncValidator',
+ 'NgControl.value',
+ 'NgControl.valueAccessor',
+ 'NgControl.valueAccessor=',
+ 'NgControlGroup',
+ 'NgControlGroup.control',
+ 'NgControlGroup.dirty',
+ 'NgControlGroup.errors',
+ 'NgControlGroup.formDirective',
+ 'NgControlGroup.name',
+ 'NgControlGroup.name=',
+ 'NgControlGroup.onDestroy()',
+ 'NgControlGroup.onInit()',
+ 'NgControlGroup.path',
+ 'NgControlGroup.pristine',
+ 'NgControlGroup.touched',
+ 'NgControlGroup.untouched',
+ 'NgControlGroup.valid',
+ 'NgControlGroup.value',
+ 'NgControlGroup.validator',
+ 'NgControlGroup.asyncValidator',
+ 'NgControlStatus',
+ 'NgControlStatus.ngClassDirty',
+ 'NgControlStatus.ngClassInvalid',
+ 'NgControlStatus.ngClassPristine',
+ 'NgControlStatus.ngClassTouched',
+ 'NgControlStatus.ngClassUntouched',
+ 'NgControlStatus.ngClassValid',
+ 'NgControlName',
+ 'NgControlName.control',
+ 'NgControlName.dirty',
+ 'NgControlName.errors',
+ 'NgControlName.formDirective',
+ 'NgControlName.model',
+ 'NgControlName.model=',
+ 'NgControlName.name',
+ 'NgControlName.name=',
+ 'NgControlName.onChanges()',
+ 'NgControlName.onDestroy()',
+ 'NgControlName.path',
+ 'NgControlName.pristine',
+ 'NgControlName.touched',
+ 'NgControlName.untouched',
+ 'NgControlName.update',
+ 'NgControlName.update=',
+ 'NgControlName.valid',
+ 'NgControlName.validator',
+ 'NgControlName.asyncValidator',
+ 'NgControlName.value',
+ 'NgControlName.valueAccessor',
+ 'NgControlName.valueAccessor=',
+ 'NgControlName.viewModel',
+ 'NgControlName.viewModel=',
+ 'NgControlName.viewToModelUpdate()',
+ 'NgFor',
+ 'NgFor.doCheck()',
+ 'NgFor.ngForOf=',
+ 'NgFor.ngForTemplate=',
+ 'NgForm',
+ 'NgForm.addControl()',
+ 'NgForm.addControlGroup()',
+ 'NgForm.control',
+ 'NgForm.controls',
+ 'NgForm.dirty',
+ 'NgForm.errors',
+ 'NgForm.form',
+ 'NgForm.form=',
+ 'NgForm.formDirective',
+ 'NgForm.getControl()',
+ 'NgForm.getControlGroup()',
+ 'NgForm.name',
+ 'NgForm.name=',
+ 'NgForm.ngSubmit',
+ 'NgForm.ngSubmit=',
+ 'NgForm.onSubmit()',
+ 'NgForm.path',
+ 'NgForm.pristine',
+ 'NgForm.removeControl()',
+ 'NgForm.removeControlGroup()',
+ 'NgForm.touched',
+ 'NgForm.untouched',
+ 'NgForm.updateModel()',
+ 'NgForm.valid',
+ 'NgForm.value',
+ 'NgFormControl',
+ 'NgFormControl.control',
+ 'NgFormControl.dirty',
+ 'NgFormControl.errors',
+ 'NgFormControl.form',
+ 'NgFormControl.form=',
+ 'NgFormControl.model',
+ 'NgFormControl.model=',
+ 'NgFormControl.name',
+ 'NgFormControl.name=',
+ 'NgFormControl.onChanges()',
+ 'NgFormControl.path',
+ 'NgFormControl.pristine',
+ 'NgFormControl.touched',
+ 'NgFormControl.untouched',
+ 'NgFormControl.update',
+ 'NgFormControl.update=',
+ 'NgFormControl.valid',
+ 'NgFormControl.validator',
+ 'NgFormControl.asyncValidator',
+ 'NgFormControl.value',
+ 'NgFormControl.valueAccessor',
+ 'NgFormControl.valueAccessor=',
+ 'NgFormControl.viewModel',
+ 'NgFormControl.viewModel=',
+ 'NgFormControl.viewToModelUpdate()',
+ 'NgFormModel',
+ 'NgFormModel.addControl()',
+ 'NgFormModel.addControlGroup()',
+ 'NgFormModel.control',
+ 'NgFormModel.directives',
+ 'NgFormModel.directives=',
+ 'NgFormModel.dirty',
+ 'NgFormModel.errors',
+ 'NgFormModel.form',
+ 'NgFormModel.form=',
+ 'NgFormModel.formDirective',
+ 'NgFormModel.getControl()',
+ 'NgFormModel.getControlGroup()',
+ 'NgFormModel.name',
+ 'NgFormModel.name=',
+ 'NgFormModel.ngSubmit',
+ 'NgFormModel.ngSubmit=',
+ 'NgFormModel.onChanges()',
+ 'NgFormModel.onSubmit()',
+ 'NgFormModel.path',
+ 'NgFormModel.pristine',
+ 'NgFormModel.removeControl()',
+ 'NgFormModel.removeControlGroup()',
+ 'NgFormModel.touched',
+ 'NgFormModel.untouched',
+ 'NgFormModel.updateModel()',
+ 'NgFormModel.valid',
+ 'NgFormModel.value',
+ 'NgIf',
+ 'NgIf.ngIf=',
+ 'NgModel',
+ 'NgModel.control',
+ 'NgModel.dirty',
+ 'NgModel.errors',
+ 'NgModel.model',
+ 'NgModel.model=',
+ 'NgModel.name',
+ 'NgModel.name=',
+ 'NgModel.onChanges()',
+ 'NgModel.path',
+ 'NgModel.pristine',
+ 'NgModel.touched',
+ 'NgModel.untouched',
+ 'NgModel.update',
+ 'NgModel.update=',
+ 'NgModel.valid',
+ 'NgModel.validator',
+ 'NgModel.asyncValidator',
+ 'NgModel.value',
+ 'NgModel.valueAccessor',
+ 'NgModel.valueAccessor=',
+ 'NgModel.viewModel',
+ 'NgModel.viewModel=',
+ 'NgModel.viewToModelUpdate()',
+ 'NgSelectOption',
+ 'NgStyle',
+ 'NgStyle.doCheck()',
+ 'NgStyle.rawStyle=',
+ 'NgSwitch',
+ 'NgSwitch.ngSwitch=',
+ 'NgSwitchDefault',
+ 'NgSwitchWhen',
+ 'NgSwitchWhen.ngSwitchWhen=',
+ 'NgZone',
+ 'NgZone.hasPendingAsyncTasks',
+ 'NgZone.hasPendingMicrotasks',
+ 'NgZone.hasPendingTimers',
+ 'NgZone.onError',
+ 'NgZone.onEventDone',
+ 'NgZone.onTurnDone',
+ 'NgZone.onTurnStart',
+ 'NgZone.overrideOnErrorHandler()',
+ 'NgZone.overrideOnEventDone()',
+ 'NgZone.overrideOnTurnDone()',
+ 'NgZone.overrideOnTurnStart()',
+ 'NgZone.run()',
+ 'NgZone.runOutsideAngular()',
+ 'NgZoneError',
+ 'NgZoneError.error',
+ 'NgZoneError.stackTrace',
+ 'NoAnnotationError',
+ 'NoAnnotationError.message',
+ 'NoAnnotationError.stackTrace',
+ 'NoProviderError',
+ 'NoProviderError.addKey()',
+ 'NoProviderError.constructResolvingMessage',
+ 'NoProviderError.constructResolvingMessage=',
+ 'NoProviderError.context',
+ 'NoProviderError.injectors',
+ 'NoProviderError.injectors=',
+ 'NoProviderError.keys',
+ 'NoProviderError.keys=',
+ 'NoProviderError.message',
+ 'NoProviderError.message=',
+ 'NoProviderError.stackTrace',
+ 'NumberPipe',
+ 'ObservableListDiff.check():dart',
+ 'ObservableListDiff.collection:dart',
+ 'ObservableListDiff.diff():dart',
+ 'ObservableListDiff.forEachAddedItem():dart',
+ 'ObservableListDiff.forEachItem():dart',
+ 'ObservableListDiff.forEachMovedItem():dart',
+ 'ObservableListDiff.forEachPreviousItem():dart',
+ 'ObservableListDiff.forEachRemovedItem():dart',
+ 'ObservableListDiff.isDirty:dart',
+ 'ObservableListDiff.length:dart',
+ 'ObservableListDiff.onDestroy():dart',
+ 'ObservableListDiff:dart',
+ 'ObservableListDiffFactory.create():dart',
+ 'ObservableListDiffFactory.supports():dart',
+ 'ObservableListDiffFactory:dart',
+ 'OpaqueToken',
+ 'Optional',
+ 'OptionalMetadata',
+ 'OutOfBoundsError',
+ 'OutOfBoundsError.message',
+ 'OutOfBoundsError.stackTrace',
+ 'PercentPipe',
+ 'PercentPipe.transform()',
+ 'Pipe',
+ 'Pipe.name',
+ 'Pipe.pure',
+ 'PipeMetadata',
+ 'PipeMetadata.name',
+ 'PipeMetadata.pure',
+ 'PlatformRef',
+ /*
+ Abstract methods
+ 'PlatformRef.application()',
+ 'PlatformRef.asyncApplication()',
+ 'PlatformRef.dispose()',
+ 'PlatformRef.registerDisposeListener()',
+ */
+ 'PlatformRef.injector',
+ 'Input',
+ 'Input.bindingPropertyName',
+ 'InputMetadata',
+ 'InputMetadata.bindingPropertyName',
+ 'ProtoViewRef',
+ 'Query',
+ 'Query.descendants',
+ 'Query.first',
+ 'Query.isVarBindingQuery',
+ 'Query.isViewQuery',
+ 'Query.selector',
+ 'Query.token',
+ 'Query.varBindings',
+ 'QueryList',
+ 'QueryList.any():dart',
+ 'QueryList.contains():dart',
+ 'QueryList.elementAt():dart',
+ 'QueryList.every():dart',
+ 'QueryList.expand():dart',
+ 'QueryList.notifyOnChanges():',
+ 'QueryList.first',
+ 'QueryList.firstWhere():dart',
+ 'QueryList.fold():dart',
+ 'QueryList.forEach():dart',
+ 'QueryList.isEmpty',
+ 'QueryList.isNotEmpty',
+ 'QueryList.iterator',
+ 'QueryList.join():dart',
+ 'QueryList.last',
+ 'QueryList.lastWhere():dart',
+ 'QueryList.length',
+ 'QueryList.map()',
+ 'QueryList.changes',
+ 'QueryList.reduce():dart',
+ 'QueryList.reset()',
+ 'QueryList.single',
+ 'QueryList.singleWhere():dart',
+ 'QueryList.skip():dart',
+ 'QueryList.skipWhile():dart',
+ 'QueryList.take():dart',
+ 'QueryList.takeWhile():dart',
+ 'QueryList.toList():dart',
+ 'QueryList.toSet():dart',
+ 'QueryList.where():dart',
+ 'QueryMetadata',
+ 'QueryMetadata.descendants',
+ 'QueryMetadata.first',
+ 'QueryMetadata.isVarBindingQuery',
+ 'QueryMetadata.isViewQuery',
+ 'QueryMetadata.selector',
+ 'QueryMetadata.token',
+ 'QueryMetadata.varBindings',
+ 'RenderFragmentRef',
+ 'RenderProtoViewRef',
+ 'RenderViewRef',
+ 'RenderViewWithFragments',
+ 'RenderViewWithFragments.fragmentRefs',
+ 'RenderViewWithFragments.fragmentRefs=',
+ 'RenderViewWithFragments.viewRef',
+ 'RenderViewWithFragments.viewRef=',
+ 'Renderer',
+ /*
+ Abstract methods
+ 'Renderer.attachFragmentAfterElement()',
+ 'Renderer.attachFragmentAfterFragment()',
+ 'Renderer.createProtoView()',
+ 'Renderer.registerComponentTemplate()',
+ 'Renderer.createRootHostView()',
+ 'Renderer.createView()',
+ 'Renderer.dehydrateView()',
+ 'Renderer.destroyView()',
+ 'Renderer.detachFragment()',
+ 'Renderer.getNativeElementSync()',
+ 'Renderer.hydrateView()',
+ 'Renderer.invokeElementMethod()',
+ 'Renderer.setElementAttribute()',
+ 'Renderer.setElementClass()',
+ 'Renderer.setElementProperty()',
+ 'Renderer.setElementStyle()',
+ 'Renderer.setEventDispatcher()',
+ 'Renderer.setText()',
+ */
+ 'ResolvedBinding:dart',
+ 'ResolvedProvider:dart',
+ 'ResolvedProvider.key:dart',
+ 'ResolvedProvider.key=:dart',
+ 'ResolvedProvider.multiProvider:dart',
+ 'ResolvedProvider.multiProvider=:dart',
+ 'ResolvedProvider.resolvedFactories:dart',
+ 'ResolvedProvider.resolvedFactories=:dart',
+ 'ResolvedFactory',
+ 'ResolvedFactory.dependencies',
+ 'ResolvedFactory.dependencies=',
+ 'ResolvedFactory.factory',
+ 'ResolvedFactory.factory=',
+ 'Scope#all()',
+ 'Scope#light()',
+ 'Scope#view()',
+ 'Scope',
+ 'SelectControlValueAccessor',
+ 'SelectControlValueAccessor.onChange',
+ 'SelectControlValueAccessor.onChange=',
+ 'SelectControlValueAccessor.onTouched',
+ 'SelectControlValueAccessor.onTouched=',
+ 'SelectControlValueAccessor.registerOnChange()',
+ 'SelectControlValueAccessor.registerOnTouched()',
+ 'SelectControlValueAccessor.value',
+ 'SelectControlValueAccessor.value=',
+ 'SelectControlValueAccessor.writeValue()',
+ 'Self',
+ 'SelfMetadata',
+ 'SkipSelf',
+ 'SkipSelfMetadata',
+ 'SlicePipe',
+ 'SlicePipe.supports()',
+ 'SlicePipe.transform()',
+ 'SimpleChange',
+ 'SimpleChange.currentValue',
+ 'SimpleChange.currentValue=',
+ 'SimpleChange.previousValue',
+ 'SimpleChange.previousValue=',
+ 'SimpleChange.isFirstChange()',
+ 'TemplateRef',
+ 'TemplateRef.elementRef',
+ 'TemplateRef.elementRef=',
+ /*
+ Abstract method
+ 'TemplateRef.hasLocal()',
+ */
+ 'Type:js',
+ 'Title',
+ 'Title.getTitle()',
+ 'Title.setTitle()',
+ 'TypeLiteral',
+ 'TypeLiteral.type',
+ 'UpperCasePipe',
+ 'UpperCasePipe.transform()',
+ 'UrlResolver',
+ 'UrlResolver.resolve()',
+ 'Validators#compose()',
+ 'Validators#composeAsync()',
+ 'Validators#nullValidator()',
+ 'Validators#required()',
+ 'Validators#minLength()',
+ 'Validators#maxLength()',
+ 'Validators',
+ 'View',
+ 'View.directives',
+ 'View.encapsulation',
+ 'View.pipes',
+ 'View.styleUrls',
+ 'View.styles',
+ 'View.template',
+ 'View.templateUrl',
+ 'ViewChild',
+ 'ViewChild.descendants',
+ 'ViewChild.first',
+ 'ViewChild.isVarBindingQuery',
+ 'ViewChild.isViewQuery',
+ 'ViewChild.selector',
+ 'ViewChild.token',
+ 'ViewChild.varBindings',
+ 'ViewChildMetadata',
+ 'ViewChildMetadata.descendants',
+ 'ViewChildMetadata.first',
+ 'ViewChildMetadata.isVarBindingQuery',
+ 'ViewChildMetadata.isViewQuery',
+ 'ViewChildMetadata.selector',
+ 'ViewChildMetadata.token',
+ 'ViewChildMetadata.varBindings',
+ 'ViewChildren',
+ 'ViewChildren.descendants',
+ 'ViewChildren.first',
+ 'ViewChildren.isVarBindingQuery',
+ 'ViewChildren.isViewQuery',
+ 'ViewChildren.selector',
+ 'ViewChildren.token',
+ 'ViewChildren.varBindings',
+ 'ViewChildrenMetadata',
+ 'ViewChildrenMetadata.descendants',
+ 'ViewChildrenMetadata.first',
+ 'ViewChildrenMetadata.isVarBindingQuery',
+ 'ViewChildrenMetadata.isViewQuery',
+ 'ViewChildrenMetadata.selector',
+ 'ViewChildrenMetadata.token',
+ 'ViewChildrenMetadata.varBindings',
+ 'ViewContainerRef',
+ 'ViewContainerRef.clear()',
+ /*
+ Abstract methods
+ 'ViewContainerRef.createEmbeddedView()',
+ 'ViewContainerRef.createHostView()',
+ 'ViewContainerRef.detach()',
+ */
+ 'ViewContainerRef.element',
+ 'ViewContainerRef.element=',
+ /*
+ 'ViewContainerRef.get()',
+ 'ViewContainerRef.indexOf()',
+ 'ViewContainerRef.insert()',
+ */
+ 'ViewContainerRef.length',
+ 'ViewEncapsulation#Emulated',
+ 'ViewEncapsulation#Native',
+ 'ViewEncapsulation#None',
+ 'ViewEncapsulation#values',
+ 'ViewEncapsulation',
+ 'ViewEncapsulation.index',
+ 'ViewMetadata',
+ 'ViewMetadata.directives',
+ 'ViewMetadata.encapsulation',
+ 'ViewMetadata.pipes',
+ 'ViewMetadata.styleUrls',
+ 'ViewMetadata.styles',
+ 'ViewMetadata.template',
+ 'ViewMetadata.templateUrl',
+ 'ViewQuery',
+ 'ViewQuery.descendants',
+ 'ViewQuery.first',
+ 'ViewQuery.isVarBindingQuery',
+ 'ViewQuery.isViewQuery',
+ 'ViewQuery.selector',
+ 'ViewQuery.token',
+ 'ViewQuery.varBindings',
+ 'ViewQueryMetadata',
+ 'ViewQueryMetadata.descendants',
+ 'ViewQueryMetadata.first',
+ 'ViewQueryMetadata.isVarBindingQuery',
+ 'ViewQueryMetadata.isViewQuery',
+ 'ViewQueryMetadata.selector',
+ 'ViewQueryMetadata.token',
+ 'ViewQueryMetadata.varBindings',
+ 'ViewRef',
+ 'ViewRef.changeDetectorRef',
+ 'ViewRef.changeDetectorRef=',
+ /*
+ Abstract method
+ 'ViewRef.setLocal()',
+ */
+ 'ViewResolver',
+ 'ViewResolver.resolve()',
+ 'WrappedException',
+ 'WrappedException.context',
+ 'WrappedException.message',
+ 'WrappedException.stackTrace',
+ 'WrappedException.wrapperMessage',
+ 'WrappedValue#wrap()',
+ 'WrappedValue',
+ 'WrappedValue.wrapped',
+ 'WrappedValue.wrapped=',
+ 'WtfScopeFn:dart',
+ 'ZeroArgFunction:dart',
+ 'applicationCommonProviders()',
+ 'asNativeElements()',
+ 'bind()',
+ 'provide()',
+ 'bootstrap():js',
+ 'createNgZone()',
+ 'forwardRef():js',
+ 'inspectElement()',
+ 'inspectNativeElement()',
+ 'platform():js',
+ 'platformProviders()',
+ 'platformCommon()',
+ 'resolveForwardRef():js',
+ 'wtfCreateScope():js',
+ 'wtfCreateScope:dart',
+ 'wtfEndTimeRange():js',
+ 'wtfEndTimeRange:dart',
+ 'wtfLeave():js',
+ 'wtfLeave:dart',
+ 'wtfStartTimeRange():js',
+ 'wtfStartTimeRange:dart',
+ 'AfterContentChecked:dart',
+ 'AfterContentInit:dart',
+ 'AfterViewChecked:dart',
+ 'AfterViewInit:dart',
+ 'ControlValueAccessor:dart',
+ 'DoCheck:dart',
+ 'Form:dart',
+ 'HostViewRef:dart',
+ 'HostViewRef.changeDetectorRef',
+ 'HostViewRef.changeDetectorRef=',
+ 'IterableDifferFactory:dart',
+ 'IterableDiffer:dart',
+ 'KeyValueDifferFactory:dart',
+ 'KeyValueDiffer:dart',
+ 'OnChanges:dart',
+ 'OnDestroy:dart',
+ 'OnInit:dart',
+ 'PipeOnDestroy:dart',
+ 'PipeTransform:dart',
+ 'RenderBeginCmd:dart',
+ 'RenderBeginCmd.isBound',
+ 'RenderBeginCmd.ngContentIndex',
+ 'RenderBeginComponentCmd:dart',
+ 'RenderBeginComponentCmd.attrNameAndValues',
+ 'RenderBeginComponentCmd.eventTargetAndNames',
+ 'RenderBeginComponentCmd.isBound',
+ 'RenderBeginComponentCmd.name',
+ 'RenderBeginComponentCmd.ngContentIndex',
+ 'RenderBeginComponentCmd.templateId',
+ 'RenderBeginElementCmd:dart',
+ 'RenderBeginElementCmd.attrNameAndValues',
+ 'RenderBeginElementCmd.isBound',
+ 'RenderBeginElementCmd.eventTargetAndNames',
+ 'RenderBeginElementCmd.name',
+ 'RenderBeginElementCmd.ngContentIndex',
+ 'RenderCommandVisitor:dart',
+ 'RenderEmbeddedTemplateCmd:dart',
+ 'RenderEmbeddedTemplateCmd.attrNameAndValues',
+ 'RenderEmbeddedTemplateCmd.children',
+ 'RenderEmbeddedTemplateCmd.eventTargetAndNames',
+ 'RenderEmbeddedTemplateCmd.isBound',
+ 'RenderEmbeddedTemplateCmd.isMerged',
+ 'RenderEmbeddedTemplateCmd.name',
+ 'RenderEmbeddedTemplateCmd.ngContentIndex',
+ 'RenderNgContentCmd:dart',
+ 'RenderNgContentCmd.ngContentIndex',
+ 'RenderTemplateCmd:dart',
+ 'RenderTextCmd:dart',
+ 'RenderTextCmd.isBound',
+ 'RenderTextCmd.ngContentIndex',
+ 'RenderTextCmd.value',
+ 'RenderElementRef:dart',
+ 'RenderElementRef.boundElementIndex',
+ 'RenderElementRef.boundElementIndex=',
+ 'RenderElementRef.renderView',
+ 'RenderElementRef.renderView=',
+ 'RenderEventDispatcher:dart',
+ 'RenderNgContentCmd.index',
+ 'Stream:dart',
+ 'Stream.any():dart',
+ 'Stream.asBroadcastStream():dart',
+ 'Stream.asyncExpand():dart',
+ 'Stream.asyncMap():dart',
+ 'Stream.contains():dart',
+ 'Stream.distinct():dart',
+ 'Stream.drain():dart',
+ 'Stream.elementAt():dart',
+ 'Stream.every():dart',
+ 'Stream.expand():dart',
+ 'Stream.first:dart',
+ 'Stream.firstWhere():dart',
+ 'Stream.fold():dart',
+ 'Stream.forEach():dart',
+ 'Stream.handleError():dart',
+ 'Stream.isBroadcast:dart',
+ 'Stream.isEmpty:dart',
+ 'Stream.join():dart',
+ 'Stream.last:dart',
+ 'Stream.lastWhere():dart',
+ 'Stream.length:dart',
+ 'Stream.map():dart',
+ 'Stream.pipe():dart',
+ 'Stream.reduce():dart',
+ 'Stream.single:dart',
+ 'Stream.singleWhere():dart',
+ 'Stream.skip():dart',
+ 'Stream.skipWhile():dart',
+ 'Stream.take():dart',
+ 'Stream.takeWhile():dart',
+ 'Stream.timeout():dart',
+ 'Stream.toList():dart',
+ 'Stream.toSet():dart',
+ 'Stream.transform():dart',
+ 'Stream.where():dart',
+];
+var NG_UPGRADE = [
+ 'UpgradeAdapter:js',
+ 'UpgradeAdapter.addProvider():js',
+ 'UpgradeAdapter.bootstrap():js',
+ 'UpgradeAdapter.compileNg2Components():js',
+ 'UpgradeAdapter.downgradeNg2Component():js',
+ 'UpgradeAdapter.downgradeNg2Provider():js',
+ 'UpgradeAdapter.upgradeNg1Component():js',
+ 'UpgradeAdapter.upgradeNg1Provider():js',
+ 'UpgradeAdapterRef:js',
+ 'UpgradeAdapterRef.dispose():js',
+ 'UpgradeAdapterRef.ready():js'
+];
+var NG_API = [].concat(NG_ALL).concat(NG_UPGRADE);
+function main() {
+ /**
+ var x = getSymbolsFromLibrary('ng');
+ x.sort();
+ var parts = [];
+ x.forEach((i) => parts.push(`'${i'`));
+ print(`[ ${parts.join(',
+ ')} ]`);
+ */
+ testing_internal_1.describe('public API', function () {
+ testing_internal_1.it('should fail if public API has changed', function () { testing_internal_1.expect(new symbol_differ_1.SymbolsDiff(symbol_inspector_1.getSymbolsFromLibrary('ng'), NG_API).errors).toEqual([]); });
+ });
+}
+exports.main = main;
+//# sourceMappingURL=public_api_spec.js.map
\ No newline at end of file
diff --git a/test/router/integration/lifecycle_hook_spec.js b/test/router/integration/lifecycle_hook_spec.js
new file mode 100644
index 00000000000..e9ea709439a
--- /dev/null
+++ b/test/router/integration/lifecycle_hook_spec.js
@@ -0,0 +1,589 @@
+var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") return Reflect.decorate(decorators, target, key, desc);
+ switch (arguments.length) {
+ case 2: return decorators.reduceRight(function(o, d) { return (d && d(o)) || o; }, target);
+ case 3: return decorators.reduceRight(function(o, d) { return (d && d(target, key)), void 0; }, void 0);
+ case 4: return decorators.reduceRight(function(o, d) { return (d && d(target, key, o)) || o; }, desc);
+ }
+};
+var __metadata = (this && this.__metadata) || function (k, v) {
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
+};
+var testing_internal_1 = require('angular2/testing_internal');
+var core_1 = require('angular2/core');
+var lang_1 = require('angular2/src/facade/lang');
+var async_1 = require('angular2/src/facade/async');
+var router_1 = require('angular2/src/router/router');
+var router_2 = require('angular2/router');
+var route_config_decorator_1 = require('angular2/src/router/route_config_decorator');
+var location_mock_1 = require('angular2/src/mock/location_mock');
+var location_1 = require('angular2/src/router/location');
+var route_registry_1 = require('angular2/src/router/route_registry');
+var lifecycle_annotations_1 = require('angular2/src/router/lifecycle_annotations');
+var directive_resolver_1 = require('angular2/src/core/linker/directive_resolver');
+var cmpInstanceCount;
+var log;
+var eventBus;
+var completer;
+function main() {
+ testing_internal_1.describe('Router lifecycle hooks', function () {
+ var tcb;
+ var fixture;
+ var rtr;
+ testing_internal_1.beforeEachBindings(function () { return [
+ route_registry_1.RouteRegistry,
+ directive_resolver_1.DirectiveResolver,
+ core_1.provide(location_1.Location, { useClass: location_mock_1.SpyLocation }),
+ core_1.provide(router_2.Router, {
+ useFactory: function (registry, location) { return new router_1.RootRouter(registry, location, MyComp); },
+ deps: [route_registry_1.RouteRegistry, location_1.Location]
+ })
+ ]; });
+ testing_internal_1.beforeEach(testing_internal_1.inject([testing_internal_1.TestComponentBuilder, router_2.Router], function (tcBuilder, router) {
+ tcb = tcBuilder;
+ rtr = router;
+ cmpInstanceCount = 0;
+ log = [];
+ eventBus = new async_1.EventEmitter();
+ }));
+ function compile(template) {
+ if (template === void 0) { template = ""; }
+ return tcb.overrideView(MyComp, new core_1.View({
+ template: ('