${_scriptStart}${_scriptEnd}`);
- content = DOM.firstChild(parent);
- });
-
- it("should insert the nodes", () => {
- var c = new Content(content, '');
- c.init(null);
- c.insert([el("
"), el("
")])
-
- expect(DOM.getInnerHTML(parent))
- .toEqual(`${_scriptStart}
${_scriptEnd}`);
- });
-
- it("should remove the nodes from the previous insertion", () => {
- var c = new Content(content, '');
- c.init(null);
- c.insert([el("
")]);
- c.insert([el("
")]);
-
- expect(DOM.getInnerHTML(parent)).toEqual(`${_scriptStart}
${_scriptEnd}`);
- });
-
- it("should insert empty list", () => {
- var c = new Content(content, '');
- c.init(null);
- c.insert([el("
")]);
- c.insert([]);
-
- expect(DOM.getInnerHTML(parent)).toEqual(`${_scriptStart}${_scriptEnd}`);
- });
- });
-}
diff --git a/modules/angular2/test/render/dom/shadow_dom/emulated_scoped_shadow_dom_strategy_spec.ts b/modules/angular2/test/render/dom/shadow_dom/emulated_scoped_shadow_dom_strategy_spec.ts
index e975d2120f..f3adf95057 100644
--- a/modules/angular2/test/render/dom/shadow_dom/emulated_scoped_shadow_dom_strategy_spec.ts
+++ b/modules/angular2/test/render/dom/shadow_dom/emulated_scoped_shadow_dom_strategy_spec.ts
@@ -32,10 +32,8 @@ export function main() {
resetShadowDomCache();
});
- it('should use the host element as shadow root', () => {
- var host = el('
original content
');
- expect(strategy.prepareShadowRoot(host)).toBe(host);
- });
+ it('should report that this is not the native strategy',
+ () => { expect(strategy.hasNativeContentElement()).toBe(false); });
it('should scope styles', () => {
var styleElement = el('');
diff --git a/modules/angular2/test/render/dom/shadow_dom/emulated_unscoped_shadow_dom_strategy_spec.ts b/modules/angular2/test/render/dom/shadow_dom/emulated_unscoped_shadow_dom_strategy_spec.ts
index ccb98419c6..07974e9f65 100644
--- a/modules/angular2/test/render/dom/shadow_dom/emulated_unscoped_shadow_dom_strategy_spec.ts
+++ b/modules/angular2/test/render/dom/shadow_dom/emulated_unscoped_shadow_dom_strategy_spec.ts
@@ -34,10 +34,8 @@ export function main() {
resetShadowDomCache();
});
- it('should use the host element as shadow root', () => {
- var host = el('
original content
');
- expect(strategy.prepareShadowRoot(host)).toBe(host);
- });
+ it('should report that this is not the native strategy',
+ () => { expect(strategy.hasNativeContentElement()).toBe(false); });
it('should move the style element to the style host', () => {
var compileElement = el('
');
diff --git a/modules/angular2/test/render/dom/shadow_dom/light_dom_spec.ts b/modules/angular2/test/render/dom/shadow_dom/light_dom_spec.ts
deleted file mode 100644
index b9a80c1ffc..0000000000
--- a/modules/angular2/test/render/dom/shadow_dom/light_dom_spec.ts
+++ /dev/null
@@ -1,253 +0,0 @@
-import {
- describe,
- beforeEach,
- it,
- expect,
- ddescribe,
- iit,
- SpyObject,
- el,
- proxy,
- stringifyElement
-} from 'angular2/test_lib';
-import {IMPLEMENTS, isBlank, isPresent} from 'angular2/src/facade/lang';
-import {ListWrapper, MapWrapper} from 'angular2/src/facade/collection';
-import {DOM} from 'angular2/src/dom/dom_adapter';
-import {Content} from 'angular2/src/render/dom/shadow_dom/content_tag';
-import {LightDom} from 'angular2/src/render/dom/shadow_dom/light_dom';
-import {DomView} from 'angular2/src/render/dom/view/view';
-import {DomProtoView} from 'angular2/src/render/dom/view/proto_view';
-import {DomViewContainer} from 'angular2/src/render/dom/view/view_container';
-import {DomElement} from 'angular2/src/render/dom/view/element';
-
-@proxy
-@IMPLEMENTS(DomProtoView)
-class FakeProtoView extends SpyObject {
- constructor(public transitiveContentTagCount: number) { super(DomProtoView); }
-
- noSuchMethod(i) { super.noSuchMethod(i); }
-}
-
-@proxy
-@IMPLEMENTS(DomView)
-class FakeView extends SpyObject {
- boundElements: any[];
- proto;
-
- constructor(containers = null, transitiveContentTagCount: number = 1) {
- super(DomView);
- this.proto = new FakeProtoView(transitiveContentTagCount);
- this.boundElements = [];
- if (isPresent(containers)) {
- ListWrapper.forEach(containers, (c) => {
- var element = null;
- var contentTag = null;
- var vc = null;
- if (c instanceof FakeContentTag) {
- contentTag = c;
- element = c.contentStartElement;
- }
- if (c instanceof FakeViewContainer) {
- vc = c;
- element = c.templateElement;
- }
- var boundElement = new DomElement(null, element, contentTag);
- boundElement.viewContainer = vc;
- this.boundElements.push(boundElement);
- });
- }
- }
-
- noSuchMethod(i) { super.noSuchMethod(i); }
-}
-
-@proxy
-@IMPLEMENTS(DomViewContainer)
-class FakeViewContainer extends SpyObject {
- _nodes;
- _contentTagContainers;
- templateElement;
-
- constructor(templateEl, nodes = null, views = null) {
- super(DomViewContainer);
- this.templateElement = templateEl;
- this._nodes = nodes;
- this._contentTagContainers = views;
- }
-
- nodes() { return this._nodes; }
-
- contentTagContainers() { return this._contentTagContainers; }
-
- noSuchMethod(i) { super.noSuchMethod(i); }
-}
-
-
-@proxy
-@IMPLEMENTS(Content)
-class FakeContentTag extends SpyObject {
- select;
- _nodes;
- contentStartElement;
-
- constructor(contentEl, select = '', nodes = null) {
- super(Content);
- this.contentStartElement = contentEl;
- this.select = select;
- this._nodes = nodes;
- }
-
- insert(nodes) { this._nodes = nodes; }
-
- nodes() { return this._nodes; }
-
- noSuchMethod(i) { super.noSuchMethod(i); }
-}
-
-function createLightDom(hostView, shadowView, el) {
- var lightDom = new LightDom(hostView, el);
- lightDom.attachShadowDomView(shadowView);
- return lightDom;
-}
-
-export function main() {
- describe('LightDom', function() {
- var lightDomView;
-
- beforeEach(() => { lightDomView = new FakeView(); });
-
- describe("contentTags", () => {
- it("should collect unconditional content tags", () => {
- var tag = new FakeContentTag(el(''));
- var shadowDomView = new FakeView([tag]);
-
- var lightDom = createLightDom(lightDomView, shadowDomView, el("
"));
-
- expect(lightDom.contentTags()).toEqual([tag]);
- });
-
- it("should collect content tags from ViewContainers", () => {
- var tag = new FakeContentTag(el(''));
- var vc = new FakeViewContainer(null, null, [new FakeView([tag])]);
- var shadowDomView = new FakeView([vc]);
- var lightDom = createLightDom(lightDomView, shadowDomView, el("
"));
-
- expect(lightDom.contentTags()).toEqual([tag]);
- });
-
- it("should not walk views that can't have content tags", () => {
- var tag = new FakeContentTag(el(''));
- var shadowDomView = new FakeView([tag], 0);
-
- var lightDom = createLightDom(lightDomView, shadowDomView, el("
"));
-
- expect(lightDom.contentTags()).toEqual([]);
- });
- });
-
- describe("expandedDomNodes", () => {
- it("should contain root nodes", () => {
- var lightDomEl = el("
");
- var lightDom = createLightDom(lightDomView, new FakeView(), lightDomEl);
- expect(toHtml(lightDom.expandedDomNodes())).toEqual(["
"]);
- });
-
- it("should include view container nodes", () => {
- var lightDomEl = el("
");
- var lightDom = createLightDom(
- new FakeView([
- new FakeViewContainer(DOM.firstChild(lightDomEl), // template element
- [el('
')] // light DOM nodes of view container
- )
- ]),
- null, lightDomEl);
-
- expect(toHtml(lightDom.expandedDomNodes())).toEqual(["
"]);
- });
-
- it("should include content nodes", () => {
- var lightDomEl = el("
");
- var lightDom =
- createLightDom(new FakeView([
- new FakeContentTag(DOM.firstChild(lightDomEl), // content element
- '', // selector
- [el('
')] // light DOM nodes of content tag
- )
- ]),
- null, lightDomEl);
-
- expect(toHtml(lightDom.expandedDomNodes())).toEqual(["
"]);
- });
-
- it("should work when the element injector array contains nulls", () => {
- var lightDomEl = el("
")
-
- var lightDomView = new FakeView();
-
- var lightDom = createLightDom(lightDomView, new FakeView(), lightDomEl);
-
- expect(toHtml(lightDom.expandedDomNodes())).toEqual(["
"]);
- });
- });
-
- describe("redistribute", () => {
- it("should redistribute nodes between content tags with select property set", () => {
- var contentA = new FakeContentTag(null, "a");
- var contentB = new FakeContentTag(null, "b");
-
- var lightDomEl = el("
")
-
- var lightDom =
- createLightDom(lightDomView, new FakeView([contentA, contentB]), lightDomEl);
-
- lightDom.redistribute();
-
- expect(toHtml(contentA.nodes())).toEqual(["
1", "
3"]);
- expect(toHtml(contentB.nodes())).toEqual(["
2"]);
- });
-
- it("should support wildcard content tags", () => {
- var wildcard = new FakeContentTag(null, '');
- var contentB = new FakeContentTag(null, "b");
-
- var lightDomEl = el("
")
-
- var lightDom =
- createLightDom(lightDomView, new FakeView([wildcard, contentB]), lightDomEl);
-
- lightDom.redistribute();
-
- expect(toHtml(wildcard.nodes())).toEqual(["
1", "
2", "
3"]);
- expect(toHtml(contentB.nodes())).toEqual([]);
- });
-
- it("should remove all nodes if there are no content tags", () => {
- var lightDomEl = el("
")
-
- var lightDom = createLightDom(lightDomView, new FakeView([]), lightDomEl);
-
- lightDom.redistribute();
-
- expect(DOM.childNodes(lightDomEl).length).toBe(0);
- });
-
- it("should remove all not projected nodes", () => {
- var lightDomEl = el("
");
- var bNode = DOM.childNodes(lightDomEl)[1];
-
- var lightDom =
- createLightDom(lightDomView, new FakeView([new FakeContentTag(null, "a")]), lightDomEl);
-
- lightDom.redistribute();
-
- expect(bNode.parentNode).toBe(null);
- });
-
- });
- });
-}
-
-function toHtml(nodes) {
- if (isBlank(nodes)) return [];
- return ListWrapper.map(nodes, stringifyElement);
-}
diff --git a/modules/angular2/test/render/dom/shadow_dom/native_shadow_dom_strategy_spec.ts b/modules/angular2/test/render/dom/shadow_dom/native_shadow_dom_strategy_spec.ts
index 48b0256656..e1645e9250 100644
--- a/modules/angular2/test/render/dom/shadow_dom/native_shadow_dom_strategy_spec.ts
+++ b/modules/angular2/test/render/dom/shadow_dom/native_shadow_dom_strategy_spec.ts
@@ -16,19 +16,13 @@ import {
NativeShadowDomStrategy
} from 'angular2/src/render/dom/shadow_dom/native_shadow_dom_strategy';
-import {DOM} from 'angular2/src/dom/dom_adapter';
-
export function main() {
- var strategy;
+ var strategy: NativeShadowDomStrategy;
describe('NativeShadowDomStrategy', () => {
beforeEach(() => { strategy = new NativeShadowDomStrategy(); });
- if (DOM.supportsNativeShadowDOM()) {
- it('should use the native shadow root', () => {
- var host = el('
original content
');
- expect(strategy.prepareShadowRoot(host)).toBe(DOM.getShadowRoot(host));
- });
- }
+ it('should report that this is the native strategy',
+ () => { expect(strategy.hasNativeContentElement()).toBe(true); });
});
}
diff --git a/modules/angular2/test/render/dom/shadow_dom_emulation_integration_spec.ts b/modules/angular2/test/render/dom/shadow_dom_emulation_integration_spec.ts
deleted file mode 100644
index 9c2c12743b..0000000000
--- a/modules/angular2/test/render/dom/shadow_dom_emulation_integration_spec.ts
+++ /dev/null
@@ -1,555 +0,0 @@
-import {
- AsyncTestCompleter,
- beforeEach,
- ddescribe,
- describe,
- el,
- expect,
- iit,
- inject,
- it,
- xit,
- beforeEachBindings,
- SpyObject,
-} from 'angular2/test_lib';
-
-import {bind} from 'angular2/di';
-import {MapWrapper, ListWrapper, StringMapWrapper} from 'angular2/src/facade/collection';
-import {DOM} from 'angular2/src/dom/dom_adapter';
-
-import {ViewDefinition, DirectiveMetadata} from 'angular2/src/render/api';
-
-import {ShadowDomStrategy} from 'angular2/src/render/dom/shadow_dom/shadow_dom_strategy';
-import {
- EmulatedScopedShadowDomStrategy
-} from 'angular2/src/render/dom/shadow_dom/emulated_scoped_shadow_dom_strategy';
-import {
- EmulatedUnscopedShadowDomStrategy
-} from 'angular2/src/render/dom/shadow_dom/emulated_unscoped_shadow_dom_strategy';
-import {
- NativeShadowDomStrategy
-} from 'angular2/src/render/dom/shadow_dom/native_shadow_dom_strategy';
-
-import {DomTestbed, elRef} from './dom_testbed';
-
-export function main() {
- describe('ShadowDom integration tests', function() {
- var styleHost = DOM.createElement('div');
-
- var strategies = {
- "scoped": bind(ShadowDomStrategy).toValue(new EmulatedScopedShadowDomStrategy(styleHost)),
- "unscoped": bind(ShadowDomStrategy).toValue(new EmulatedUnscopedShadowDomStrategy(styleHost))
- };
- if (DOM.supportsNativeShadowDOM()) {
- StringMapWrapper.set(strategies, "native",
- bind(ShadowDomStrategy).toValue(new NativeShadowDomStrategy()));
- }
-
- StringMapWrapper.forEach(strategies, (strategyBinding, name) => {
- describe(`${name} shadow dom strategy`, () => {
- beforeEachBindings(() => { return [strategyBinding, DomTestbed]; });
-
- // GH-2095 - https://github.com/angular/angular/issues/2095
- // important as we are adding a content end element during compilation,
- // which could skrew up text node indices.
- it('should support text nodes after content tags',
- inject([DomTestbed, AsyncTestCompleter], (tb, async) => {
- tb.compileAll([
- simple,
- new ViewDefinition({
- componentId: 'simple',
- template: '
P,
{{a}}',
- directives: []
- })
- ])
- .then((protoViewDtos) => {
- var rootView = tb.createRootView(protoViewDtos[0]);
- var cmpView = tb.createComponentView(rootView.viewRef, 0, protoViewDtos[1]);
-
- tb.renderer.setText(cmpView.viewRef, 0, 'text');
- expect(tb.rootEl).toHaveText('P,text');
- async.done();
- });
- }));
-
- // important as we are moving style tags around during compilation,
- // which could skrew up text node indices.
- it('should support text nodes after style tags',
- inject([DomTestbed, AsyncTestCompleter], (tb, async) => {
- tb.compileAll([
- simple,
- new ViewDefinition({
- componentId: 'simple',
- template: '
P,
{{a}}',
- directives: []
- })
- ])
- .then((protoViewDtos) => {
- var rootView = tb.createRootView(protoViewDtos[0]);
- var cmpView = tb.createComponentView(rootView.viewRef, 0, protoViewDtos[1]);
-
- tb.renderer.setText(cmpView.viewRef, 0, 'text');
- expect(tb.rootEl).toHaveText('P,text');
- async.done();
- });
- }));
-
- it('should support simple components',
- inject([AsyncTestCompleter, DomTestbed], (async, tb) => {
- tb.compileAll([
- mainDir,
- new ViewDefinition({
- componentId: 'main',
- template: '
' +
- 'A
' +
- '',
- directives: [simple]
- }),
- simpleTemplate
- ])
- .then((protoViews) => {
- tb.createRootViews(protoViews);
-
- expect(tb.rootEl).toHaveText('SIMPLE(A)');
-
- async.done();
- });
- }));
-
- it('should support simple components with text interpolation as direct children',
- inject([AsyncTestCompleter, DomTestbed], (async, tb) => {
- tb.compileAll([
- mainDir,
- new ViewDefinition({
- componentId: 'main',
- template: '
' +
- '{{text}}' +
- '',
- directives: [simple]
- }),
- simpleTemplate
- ])
- .then((protoViews) => {
- var cmpView = tb.createRootViews(protoViews)[1];
- tb.renderer.setText(cmpView.viewRef, 0, 'A');
-
- expect(tb.rootEl).toHaveText('SIMPLE(A)');
-
- async.done();
- });
- }));
-
- it('should not show the light dom even if there is not content tag',
- inject([AsyncTestCompleter, DomTestbed], (async, tb) => {
- tb.compileAll([
- mainDir,
- new ViewDefinition({
- componentId: 'main',
- template: '
' +
- 'A
' +
- '',
- directives: [empty]
- }),
- emptyTemplate
- ])
- .then((protoViews) => {
- tb.createRootViews(protoViews);
-
- expect(tb.rootEl).toHaveText('');
-
- async.done();
- });
- }));
-
- it('should support dynamic components',
- inject([AsyncTestCompleter, DomTestbed], (async, tb) => {
- tb.compileAll([
- mainDir,
- new ViewDefinition({
- componentId: 'main',
- template: '
' +
- 'A
' +
- '',
- directives: [dynamicComponent]
- }),
- simpleTemplate
- ])
- .then((protoViews) => {
- var views = tb.createRootViews(ListWrapper.slice(protoViews, 0, 2));
- tb.createComponentView(views[1].viewRef, 0, protoViews[2]);
-
- expect(tb.rootEl).toHaveText('SIMPLE(A)');
-
- async.done();
- });
- }));
-
- it('should support multiple content tags',
- inject([AsyncTestCompleter, DomTestbed], (async, tb) => {
- tb.compileAll([
- mainDir,
- new ViewDefinition({
- componentId: 'main',
- template: '
' +
- 'B
' +
- 'C
' +
- 'A
' +
- '',
- directives: [multipleContentTagsComponent]
- }),
- multipleContentTagsTemplate
- ])
- .then((protoViews) => {
- tb.createRootViews(protoViews);
-
- expect(tb.rootEl).toHaveText('(A, BC)');
-
- async.done();
- });
- }));
-
- it('should redistribute only direct children',
- inject([AsyncTestCompleter, DomTestbed], (async, tb) => {
- tb.compileAll([
- mainDir,
- new ViewDefinition({
- componentId: 'main',
- template: '
' +
- '' +
- 'C
' +
- '',
- directives: [multipleContentTagsComponent]
- }),
- multipleContentTagsTemplate
- ])
- .then((protoViews) => {
- tb.createRootViews(protoViews);
-
- expect(tb.rootEl).toHaveText('(, BAC)');
-
- async.done();
- });
- }));
-
- it("should redistribute direct child viewcontainers when the light dom changes",
- inject([AsyncTestCompleter, DomTestbed], (async, tb) => {
- tb.compileAll([
- mainDir,
- new ViewDefinition({
- componentId: 'main',
- template: '
' +
- '' +
- 'B
' +
- '',
- directives: [multipleContentTagsComponent, manualViewportDirective]
- }),
- multipleContentTagsTemplate
- ])
- .then((protoViews) => {
- var views = tb.createRootViews(protoViews);
- var childProtoView = protoViews[1].elementBinders[1].nestedProtoView;
- expect(tb.rootEl).toHaveText('(, B)');
-
- var childView = tb.createViewInContainer(views[1].viewRef, 1, 0, childProtoView);
-
- expect(tb.rootEl).toHaveText('(, AB)');
-
- tb.destroyViewInContainer(views[1].viewRef, 1, 0, childView.viewRef);
-
- expect(tb.rootEl).toHaveText('(, B)');
-
- async.done();
- });
- }));
-
- it("should redistribute when the light dom changes",
- inject([AsyncTestCompleter, DomTestbed], (async, tb) => {
- tb.compileAll([
- mainDir,
- new ViewDefinition({
- componentId: 'main',
- template: '
' +
- 'A
' +
- 'B
' +
- '',
- directives: [multipleContentTagsComponent, manualViewportDirective]
- }),
- multipleContentTagsTemplate
- ])
- .then((protoViews) => {
- var views = tb.createRootViews(protoViews);
- var childProtoView = protoViews[1].elementBinders[1].nestedProtoView;
-
- expect(tb.rootEl).toHaveText('(, B)');
-
- var childView = tb.createViewInContainer(views[1].viewRef, 1, 0, childProtoView);
-
- expect(tb.rootEl).toHaveText('(A, B)');
-
- tb.destroyViewInContainer(views[1].viewRef, 1, 0, childView.viewRef);
-
- expect(tb.rootEl).toHaveText('(, B)');
-
- async.done();
- });
- }));
-
- it("should support nested components",
- inject([AsyncTestCompleter, DomTestbed], (async, tb) => {
- tb.compileAll([
- mainDir,
- new ViewDefinition({
- componentId: 'main',
- template: '
' +
- 'A
' +
- 'B
' +
- '',
- directives: [outerWithIndirectNestedComponent]
- }),
- outerWithIndirectNestedTemplate,
- simpleTemplate
- ])
- .then((protoViews) => {
- tb.createRootViews(protoViews);
-
- expect(tb.rootEl).toHaveText('OUTER(SIMPLE(AB))');
-
- async.done();
- });
- }));
-
- it("should support nesting with content being direct child of a nested component",
- inject([AsyncTestCompleter, DomTestbed], (async, tb) => {
- tb.compileAll([
- mainDir,
- new ViewDefinition({
- componentId: 'main',
- template: '
' +
- 'A
' +
- 'B
' +
- 'C
' +
- '',
- directives: [outerComponent, manualViewportDirective]
- }),
- outerTemplate,
- innerTemplate,
- innerInnerTemplate
- ])
- .then((protoViews) => {
- var views = tb.createRootViews(protoViews);
- var childProtoView = protoViews[1].elementBinders[1].nestedProtoView;
-
- expect(tb.rootEl).toHaveText('OUTER(INNER(INNERINNER(,BC)))');
-
- tb.createViewInContainer(views[1].viewRef, 1, 0, childProtoView);
-
- expect(tb.rootEl).toHaveText('OUTER(INNER(INNERINNER(A,BC)))');
- async.done();
- });
- }));
-
- it('should redistribute when the shadow dom changes',
- inject([AsyncTestCompleter, DomTestbed], (async, tb) => {
- tb.compileAll([
- mainDir,
- new ViewDefinition({
- componentId: 'main',
- template: '
' +
- 'A
' +
- 'B
' +
- 'C
' +
- '',
- directives: [conditionalContentComponent]
- }),
- conditionalContentTemplate
- ])
- .then((protoViews) => {
- var views = tb.createRootViews(protoViews);
- var childProtoView = protoViews[2].elementBinders[0].nestedProtoView;
-
- expect(tb.rootEl).toHaveText('(, ABC)');
-
- var childView = tb.createViewInContainer(views[2].viewRef, 0, 0, childProtoView);
-
- expect(tb.rootEl).toHaveText('(A, BC)');
-
- tb.destroyViewInContainer(views[2].viewRef, 0, 0, childView.viewRef);
-
- expect(tb.rootEl).toHaveText('(, ABC)');
-
- async.done();
- });
- }));
-
- it("should support tabs with view caching",
- inject([AsyncTestCompleter, DomTestbed], (async, tb) => {
- tb.compileAll([
- mainDir,
- new ViewDefinition({
- componentId: 'main',
- template: '(
0' +
- '
1' +
- '
2)',
- directives: [tabComponent]
- }),
- tabTemplate
- ])
- .then((protoViews) => {
- var views = tb.createRootViews(ListWrapper.slice(protoViews, 0, 2));
- var tabProtoView = protoViews[2];
- var tabChildProtoView = tabProtoView.elementBinders[0].nestedProtoView;
-
- var tab1View = tb.createComponentView(views[1].viewRef, 0, tabProtoView);
- var tab2View = tb.createComponentView(views[1].viewRef, 1, tabProtoView);
- var tab3View = tb.createComponentView(views[1].viewRef, 2, tabProtoView);
-
- expect(tb.rootEl).toHaveText('()');
-
- var tabChildView =
- tb.createViewInContainer(tab1View.viewRef, 0, 0, tabChildProtoView);
-
- expect(tb.rootEl).toHaveText('(TAB(0))');
-
- tb.renderer.dehydrateView(tabChildView.viewRef);
- tb.renderer.detachViewInContainer(elRef(tab1View.viewRef, 0), 0,
- tabChildView.viewRef);
-
- tb.renderer.attachViewInContainer(elRef(tab2View.viewRef, 0), 0,
- tabChildView.viewRef);
- tb.renderer.hydrateView(tabChildView.viewRef);
-
- expect(tb.rootEl).toHaveText('(TAB(1))');
-
- tb.renderer.dehydrateView(tabChildView.viewRef);
- tb.renderer.detachViewInContainer(elRef(tab2View.viewRef, 0), 0,
- tabChildView.viewRef);
-
- tb.renderer.attachViewInContainer(elRef(tab3View.viewRef, 0), 0,
- tabChildView.viewRef);
- tb.renderer.hydrateView(tabChildView.viewRef);
-
- expect(tb.rootEl).toHaveText('(TAB(2))');
-
- async.done();
- });
- }));
-
- // Implement once ElementRef support changing a class
- // it("should redistribute when a class has been added or removed");
- // it('should not lose focus', () => {
- // var temp = `
aaa bbb`;
- //
- // compile(temp, (view, lc) => {
- // var input = view.rootNodes[1];
- // input.focus();
- //
- // expect(document.activeElement.id).toEqual("focused-input");
- //
- // // update class of input
- //
- // expect(document.activeElement.id).toEqual("focused-input");
- // });
- //});
- });
- });
-
- });
-}
-
-
-var mainDir = DirectiveMetadata.create(
- {selector: 'main', id: 'main', type: DirectiveMetadata.COMPONENT_TYPE});
-
-var simple = DirectiveMetadata.create(
- {selector: 'simple', id: 'simple', type: DirectiveMetadata.COMPONENT_TYPE});
-
-var empty = DirectiveMetadata.create(
- {selector: 'empty', id: 'empty', type: DirectiveMetadata.COMPONENT_TYPE});
-
-var dynamicComponent = DirectiveMetadata.create(
- {selector: 'dynamic', id: 'dynamic', type: DirectiveMetadata.COMPONENT_TYPE});
-
-var multipleContentTagsComponent = DirectiveMetadata.create({
- selector: 'multiple-content-tags',
- id: 'multiple-content-tags',
- type: DirectiveMetadata.COMPONENT_TYPE
-});
-
-var manualViewportDirective = DirectiveMetadata.create(
- {selector: '[manual]', id: 'manual', type: DirectiveMetadata.DIRECTIVE_TYPE});
-
-var outerWithIndirectNestedComponent = DirectiveMetadata.create({
- selector: 'outer-with-indirect-nested',
- id: 'outer-with-indirect-nested',
- type: DirectiveMetadata.COMPONENT_TYPE
-});
-
-var outerComponent = DirectiveMetadata.create(
- {selector: 'outer', id: 'outer', type: DirectiveMetadata.COMPONENT_TYPE});
-
-var innerComponent = DirectiveMetadata.create(
- {selector: 'inner', id: 'inner', type: DirectiveMetadata.COMPONENT_TYPE});
-
-var innerInnerComponent = DirectiveMetadata.create(
- {selector: 'innerinner', id: 'innerinner', type: DirectiveMetadata.COMPONENT_TYPE});
-
-var conditionalContentComponent = DirectiveMetadata.create({
- selector: 'conditional-content',
- id: 'conditional-content',
- type: DirectiveMetadata.COMPONENT_TYPE
-});
-
-var autoViewportDirective = DirectiveMetadata.create(
- {selector: '[auto]', id: 'auto', properties: ['auto'], type: DirectiveMetadata.DIRECTIVE_TYPE});
-
-var tabComponent =
- DirectiveMetadata.create({selector: 'tab', id: 'tab', type: DirectiveMetadata.COMPONENT_TYPE});
-
-var simpleTemplate = new ViewDefinition(
- {componentId: 'simple', template: 'SIMPLE(
)', directives: []});
-
-var emptyTemplate = new ViewDefinition({componentId: 'empty', template: '', directives: []});
-
-var multipleContentTagsTemplate = new ViewDefinition({
- componentId: 'multiple-content-tags',
- template: '(
,
)',
- directives: []
-});
-
-var outerWithIndirectNestedTemplate = new ViewDefinition({
- componentId: 'outer-with-indirect-nested',
- template: 'OUTER(
)',
- directives: [simple]
-});
-
-var outerTemplate = new ViewDefinition({
- componentId: 'outer',
- template: 'OUTER(
)',
- directives: [innerComponent]
-});
-
-var innerTemplate = new ViewDefinition({
- componentId: 'inner',
- template: 'INNER(
)',
- directives: [innerInnerComponent]
-});
-
-var innerInnerTemplate = new ViewDefinition({
- componentId: 'innerinner',
- template: 'INNERINNER(
,
)',
- directives: []
-});
-
-var conditionalContentTemplate = new ViewDefinition({
- componentId: 'conditional-content',
- template:
- '
',
- directives: [autoViewportDirective]
-});
-
-var tabTemplate = new ViewDefinition({
- componentId: 'tab',
- template: '
',
- directives: [autoViewportDirective]
-});
diff --git a/modules/angular2/test/render/dom/view/proto_view_builder_spec.ts b/modules/angular2/test/render/dom/view/proto_view_builder_spec.ts
index ef8d00f854..00efd3a4d7 100644
--- a/modules/angular2/test/render/dom/view/proto_view_builder_spec.ts
+++ b/modules/angular2/test/render/dom/view/proto_view_builder_spec.ts
@@ -14,13 +14,15 @@ import {
import {ProtoViewBuilder} from 'angular2/src/render/dom/view/proto_view_builder';
import {ASTWithSource, AST} from 'angular2/change_detection';
import {PropertyBindingType, ViewType} from 'angular2/src/render/api';
+import {DOM} from 'angular2/src/dom/dom_adapter';
export function main() {
function emptyExpr() { return new ASTWithSource(new AST(), 'empty', 'empty'); }
describe('ProtoViewBuilder', () => {
var builder;
- beforeEach(() => { builder = new ProtoViewBuilder(el('
'), ViewType.EMBEDDED); });
+ beforeEach(
+ () => { builder = new ProtoViewBuilder(DOM.createTemplate(''), ViewType.EMBEDDED); });
if (!IS_DARTIUM) {
describe('verification of properties', () => {
diff --git a/modules/angular2/test/render/dom/view/proto_view_merger_integration_spec.ts b/modules/angular2/test/render/dom/view/proto_view_merger_integration_spec.ts
new file mode 100644
index 0000000000..98756f04ed
--- /dev/null
+++ b/modules/angular2/test/render/dom/view/proto_view_merger_integration_spec.ts
@@ -0,0 +1,291 @@
+import {
+ AsyncTestCompleter,
+ beforeEach,
+ ddescribe,
+ describe,
+ el,
+ expect,
+ iit,
+ inject,
+ it,
+ xit,
+ beforeEachBindings,
+ SpyObject,
+ stringifyElement
+} from 'angular2/test_lib';
+
+import {isPresent} from 'angular2/src/facade/lang';
+
+import {DomTestbed} from '../dom_testbed';
+
+import {
+ ViewDefinition,
+ DirectiveMetadata,
+ RenderProtoViewMergeMapping
+} from 'angular2/src/render/api';
+import {bind} from 'angular2/di';
+
+import {DOM} from 'angular2/src/dom/dom_adapter';
+import {cloneAndQueryProtoView} from 'angular2/src/render/dom/util';
+import {resolveInternalDomProtoView} from 'angular2/src/render/dom/view/proto_view';
+
+import {ShadowDomStrategy, NativeShadowDomStrategy} from 'angular2/render';
+
+export function main() {
+ describe('ProtoViewMerger integration test', () => {
+ beforeEachBindings(() => [DomTestbed]);
+
+ describe('component views', () => {
+ it('should merge a component view',
+ runAndAssert('root', ['a'], ['
a']));
+
+ it('should merge component views with interpolation at root level',
+ runAndAssert('root', ['{{a}}'], ['
{0}']));
+
+ it('should merge component views with interpolation not at root level',
+ runAndAssert('root', ['
{{a}}
'], [
+ '
{0}
'
+ ]));
+
+ it('should merge component views with bound elements',
+ runAndAssert('root', ['
'], [
+ '
'
+ ]));
+ });
+
+ describe('embedded views', () => {
+
+ it('should merge embedded views as fragments',
+ runAndAssert('root', ['
a'], [
+ '
',
+ 'a'
+ ]));
+
+ it('should merge embedded views with interpolation at root level',
+ runAndAssert('root', ['
{{a}}'], [
+ '
',
+ '{0}'
+ ]));
+
+ it('should merge embedded views with interpolation not at root level',
+ runAndAssert('root', ['
{{a}}
'], [
+ '
',
+ '
{0}
'
+ ]));
+
+ it('should merge embedded views with bound elements',
+ runAndAssert('root', ['
'], [
+ '
',
+ '
'
+ ]));
+
+ });
+
+ describe('projection', () => {
+
+ it('should remove text nodes if there is no ng-content',
+ runAndAssert(
+ 'root', ['
b', ''],
+ ['
']));
+
+ it('should project static text',
+ runAndAssert(
+ 'root', ['
b', 'A(
)'],
+ ['
A(b)']));
+
+ it('should project text interpolation',
+ runAndAssert(
+ 'root', ['
{{b}}', 'A(
)'],
+ ['
A({0})']));
+
+ it('should project elements',
+ runAndAssert('root', ['
', 'A(
)'], [
+ '
A()'
+ ]));
+
+ it('should project elements using the selector',
+ runAndAssert(
+ 'root',
+ [
+ '
a
b
',
+ 'A(
)'
+ ],
+ [
+ '
A(a
b
)'
+ ]));
+
+ it('should reproject',
+ runAndAssert(
+ 'root',
+ ['
x', 'A(
)', 'B(
)'], [
+ '
A(B(x))'
+ ]));
+
+ it('should reproject by combining selectors',
+ runAndAssert(
+ 'root',
+ [
+ '
',
+ 'A(
)',
+ 'B(
)'
+ ],
+ [
+ '
A(B())'
+ ]));
+
+ it('should keep non projected embedded views (so that they can be moved manually)',
+ runAndAssert(
+ 'root', ['
b', ''],
+ ['
', 'b']));
+
+ it('should project embedded views and match the template element',
+ runAndAssert(
+ 'root', ['
b', 'A(
)'], [
+ '
A()',
+ 'b'
+ ]));
+
+ it('should project embedded views and match the single root element',
+ runAndAssert(
+ 'root', ['
', 'A(
)'], [
+ '
A()',
+ '
'
+ ]));
+
+ it('should project nodes using the ng-content in embedded views',
+ runAndAssert('root', ['
b', 'A(
)'], [
+ '
A()',
+ 'b'
+ ]));
+
+ it('should allow to use wildcard selector after embedded view with non wildcard selector',
+ runAndAssert(
+ 'root',
+ [
+ '
a
b',
+ 'A(
,
)'
+ ],
+ [
+ '
A(, b)',
+ '
a
'
+ ]));
+
+ });
+
+ describe('composition', () => {
+ it('should merge multiple component views',
+ runAndAssert('root', ['
', 'c', 'd'], [
+ '
cd'
+ ]));
+
+ it('should merge multiple embedded views as fragments',
+ runAndAssert('root', ['
'], [
+ '
',
+ '
',
+ '
'
+ ]));
+
+ it('should merge nested embedded views as fragments',
+ runAndAssert('root', ['
'], [
+ '
',
+ '
',
+ '
'
+ ]));
+
+ });
+
+ describe('element index mapping should be grouped by view and view depth first', () => {
+
+ it('should map component views correctly',
+ runAndAssert('root', ['
', '
'], [
+ '
'
+ ]));
+
+ it('should map moved projected elements correctly',
+ runAndAssert(
+ 'root',
+ [
+ '
',
+ '
'
+ ],
+ [
+ '
'
+ ]));
+
+ });
+
+ describe('text index mapping should be grouped by view and view depth first', () => {
+
+ it('should map component views correctly', runAndAssert('root', ['
{{b}}', '{{c}}'], [
+ '
{1}{0}'
+ ]));
+
+ it('should map moved projected elements correctly',
+ runAndAssert(
+ 'root',
+ [
+ '
{{x}}
{{y}}
',
+ '
'
+ ],
+ [
+ '
{1}
{0}
'
+ ]));
+
+ });
+
+ describe('native shadow dom support', () => {
+ beforeEachBindings(
+ () => { return [bind(ShadowDomStrategy).toValue(new NativeShadowDomStrategy())]; });
+
+ it('should keep the non projected light dom and wrap the component view into a shadow-root element',
+ runAndAssert('root', ['
b', 'c'], [
+ '
cb'
+ ]));
+
+ });
+
+ });
+}
+
+function runAndAssert(hostElementName: string, componentTemplates: string[],
+ expectedFragments: string[]) {
+ var rootComp = DirectiveMetadata.create(
+ {id: 'rootComp', type: DirectiveMetadata.COMPONENT_TYPE, selector: hostElementName});
+ return inject([AsyncTestCompleter, DomTestbed], (async, tb: DomTestbed) => {
+ tb.compileAndMerge(rootComp, componentTemplates.map(template => new ViewDefinition({
+ componentId: 'someComp',
+ template: template,
+ directives: [aComp, bComp, cComp]
+ })))
+ .then((mergeMappings) => {
+ expect(stringify(mergeMappings[0])).toEqual(expectedFragments);
+ async.done();
+ });
+ });
+}
+
+function stringify(protoViewMergeMapping: RenderProtoViewMergeMapping): string[] {
+ var testView = cloneAndQueryProtoView(
+ resolveInternalDomProtoView(protoViewMergeMapping.mergedProtoViewRef), false);
+ for (var i = 0; i < protoViewMergeMapping.mappedElementIndices.length; i++) {
+ var renderElIdx = protoViewMergeMapping.mappedElementIndices[i];
+ if (isPresent(renderElIdx)) {
+ DOM.setAttribute(testView.boundElements[renderElIdx], 'idx', `${i}`);
+ }
+ }
+ for (var i = 0; i < protoViewMergeMapping.mappedTextIndices.length; i++) {
+ var renderTextIdx = protoViewMergeMapping.mappedTextIndices[i];
+ if (isPresent(renderTextIdx)) {
+ DOM.setText(testView.boundTextNodes[renderTextIdx], `{${i}}`);
+ }
+ }
+ expect(protoViewMergeMapping.fragmentCount).toEqual(testView.fragments.length);
+ return testView.fragments.map(nodes => nodes.map(node => stringifyElement(node)).join(''));
+}
+
+var aComp =
+ DirectiveMetadata.create({id: 'aComp', type: DirectiveMetadata.COMPONENT_TYPE, selector: 'a'});
+var bComp =
+ DirectiveMetadata.create({id: 'bComp', type: DirectiveMetadata.COMPONENT_TYPE, selector: 'b'});
+var cComp =
+ DirectiveMetadata.create({id: 'cComp', type: DirectiveMetadata.COMPONENT_TYPE, selector: 'c'});
diff --git a/modules/angular2/test/render/dom/view/proto_view_merger_spec.ts b/modules/angular2/test/render/dom/view/proto_view_merger_spec.ts
new file mode 100644
index 0000000000..adc0a39496
--- /dev/null
+++ b/modules/angular2/test/render/dom/view/proto_view_merger_spec.ts
@@ -0,0 +1,56 @@
+import {
+ AsyncTestCompleter,
+ beforeEach,
+ ddescribe,
+ describe,
+ el,
+ expect,
+ iit,
+ inject,
+ it,
+ xit,
+ beforeEachBindings,
+ SpyObject,
+ stringifyElement
+} from 'angular2/test_lib';
+
+import {mergeSelectors} from 'angular2/src/render/dom/view/proto_view_merger';
+
+export function main() {
+ describe('ProtoViewMerger test', () => {
+
+ describe('mergeSelectors', () => {
+ it('should merge empty selectors', () => {
+ expect(mergeSelectors('', 'a')).toEqual('a');
+ expect(mergeSelectors('a', '')).toEqual('a');
+ expect(mergeSelectors('', '')).toEqual('');
+ });
+
+ it('should merge wildcard selectors', () => {
+ expect(mergeSelectors('*', 'a')).toEqual('a');
+ expect(mergeSelectors('a', '*')).toEqual('a');
+ expect(mergeSelectors('*', '*')).toEqual('*');
+ });
+
+ it('should merge 2 element selectors',
+ () => { expect(mergeSelectors('a', 'b')).toEqual('_not-matchable_'); });
+
+ it('should merge elements and non element selector', () => {
+ expect(mergeSelectors('a', '.b')).toEqual('a.b');
+ expect(mergeSelectors('.b', 'a')).toEqual('a.b');
+ });
+
+ it('should merge attributes', () => {
+ expect(mergeSelectors('[a]', '[b]')).toEqual('[a][b]');
+ expect(mergeSelectors('[a][b]', '[c][d]')).toEqual('[a][b][c][d]');
+ expect(mergeSelectors('[a=1]', '[b=2]')).toEqual('[a=1][b=2]');
+ });
+
+ it('should merge classes', () => {
+ expect(mergeSelectors('.a', '.b')).toEqual('.a.b');
+ expect(mergeSelectors('.a.b', '.c.d')).toEqual('.a.b.c.d');
+ });
+ });
+
+ });
+}
diff --git a/modules/angular2/test/render/dom/view/view_spec.ts b/modules/angular2/test/render/dom/view/view_spec.ts
index b13692364b..6e6f8faa21 100644
--- a/modules/angular2/test/render/dom/view/view_spec.ts
+++ b/modules/angular2/test/render/dom/view/view_spec.ts
@@ -19,9 +19,8 @@ import {isBlank} from 'angular2/src/facade/lang';
import {ListWrapper} from 'angular2/src/facade/collection';
import {DomProtoView} from 'angular2/src/render/dom/view/proto_view';
-import {ElementBinder} from 'angular2/src/render/dom/view/element_binder';
+import {DomElementBinder} from 'angular2/src/render/dom/view/element_binder';
import {DomView} from 'angular2/src/render/dom/view/view';
-import {DomElement} from 'angular2/src/render/dom/view/element';
import {DOM} from 'angular2/src/dom/dom_adapter';
export function main() {
@@ -30,54 +29,33 @@ export function main() {
if (isBlank(binders)) {
binders = [];
}
- var rootEl = el('
');
- return new DomProtoView({
- element: rootEl,
- elementBinders: binders,
- transitiveContentTagCount: 0,
- boundTextNodeCount: 0
- });
+ var rootEl = DOM.createTemplate('
');
+ return DomProtoView.create(null,
rootEl, [1], [], binders, null, null, null);
}
+ function createElementBinder() { return new DomElementBinder({textNodeIndices: []}); }
+
function createView(pv = null, boundElementCount = 0) {
if (isBlank(pv)) {
- pv = createProtoView(ListWrapper.createFixedSize(boundElementCount));
+ var elementBinders = ListWrapper.createFixedSize(boundElementCount);
+ for (var i = 0; i < boundElementCount; i++) {
+ elementBinders[i] = createElementBinder();
+ }
+ pv = createProtoView(elementBinders);
}
var root = el('');
var boundElements = [];
for (var i = 0; i < boundElementCount; i++) {
- boundElements.push(new DomElement(pv.elementBinders[i], el(' {
-
- it('should return the DomElement of the direct parent', () => {
- var pv = createProtoView([createElementBinder(), createElementBinder(0, 1)]);
- var view = createView(pv, 2);
- expect(view.getDirectParentElement(1)).toBe(view.boundElements[0]);
- });
-
- it('should return null if the direct parent is not bound', () => {
- var pv = createProtoView(
- [createElementBinder(), createElementBinder(), createElementBinder(0, 2)]);
- var view = createView(pv, 3);
- expect(view.getDirectParentElement(2)).toBe(null);
- });
-
- });
-
describe('setElementProperty', () => {
var el, view;
beforeEach(() => {
view = createView(null, 1);
- el = view.boundElements[0].element;
+ el = view.boundElements[0];
});
it('should update the property value', () => {
@@ -91,7 +69,7 @@ export function main() {
var el, view;
beforeEach(() => {
view = createView(null, 1);
- el = view.boundElements[0].element;
+ el = view.boundElements[0];
});
it('should update and remove an attribute', () => {
@@ -111,7 +89,7 @@ export function main() {
var el, view;
beforeEach(() => {
view = createView(null, 1);
- el = view.boundElements[0].element;
+ el = view.boundElements[0];
});
it('should set and remove a class', () => {
@@ -135,7 +113,7 @@ export function main() {
var el, view;
beforeEach(() => {
view = createView(null, 1);
- el = view.boundElements[0].element;
+ el = view.boundElements[0];
});
it('should set and remove styles', () => {
diff --git a/modules/angular2/test/router/outlet_spec.ts b/modules/angular2/test/router/outlet_spec.ts
index 36cc014339..45726627b2 100644
--- a/modules/angular2/test/router/outlet_spec.ts
+++ b/modules/angular2/test/router/outlet_spec.ts
@@ -206,11 +206,9 @@ export function main() {
.then((_) => rtr.navigate('/page/1'))
.then((_) => {
rootTC.detectChanges();
- expect(DOM.getAttribute(rootTC.componentViewChildren[1]
- .componentViewChildren[0]
- .children[0]
- .nativeElement,
- 'href'))
+ expect(DOM.getAttribute(
+ rootTC.componentViewChildren[1].componentViewChildren[0].nativeElement,
+ 'href'))
.toEqual('/page/2');
async.done();
});
@@ -232,7 +230,6 @@ export function main() {
expect(DOM.getAttribute(rootTC.componentViewChildren[1]
.componentViewChildren[2]
.componentViewChildren[0]
- .children[0]
.nativeElement,
'href'))
.toEqual('/book/1984/page/2');
diff --git a/modules/angular2_material/src/components/button/button.html b/modules/angular2_material/src/components/button/button.html
index 1b07d41899..50b58bfd01 100644
--- a/modules/angular2_material/src/components/button/button.html
+++ b/modules/angular2_material/src/components/button/button.html
@@ -1,2 +1,2 @@
-
+
diff --git a/modules/angular2_material/src/components/checkbox/checkbox.html b/modules/angular2_material/src/components/checkbox/checkbox.html
index 91e01a488b..8662a31f80 100644
--- a/modules/angular2_material/src/components/checkbox/checkbox.html
+++ b/modules/angular2_material/src/components/checkbox/checkbox.html
@@ -4,5 +4,5 @@
-
+
diff --git a/modules/angular2_material/src/components/dialog/dialog.ts b/modules/angular2_material/src/components/dialog/dialog.ts
index 10fe1c6a45..27213d5798 100644
--- a/modules/angular2_material/src/components/dialog/dialog.ts
+++ b/modules/angular2_material/src/components/dialog/dialog.ts
@@ -64,7 +64,7 @@ export class MdDialog {
// TODO(jelbourn): Don't use direct DOM access. Need abstraction to create an element
// directly on the document body (also needed for web workers stuff).
// Create a DOM node to serve as a physical host element for the dialog.
- var dialogElement = this.domRenderer.getRootNodes(containerRef.hostView.render)[0];
+ var dialogElement = containerRef.location.nativeElement;
DOM.appendChild(DOM.query('body'), dialogElement);
// TODO(jelbourn): Use hostProperties binding to set these once #1539 is fixed.
@@ -109,7 +109,7 @@ export class MdDialog {
.then((componentRef) => {
// TODO(tbosch): clean this up when we have custom renderers
// (https://github.com/angular/angular/issues/1807)
- var backdropElement = this.domRenderer.getRootNodes(componentRef.hostView.render)[0];
+ var backdropElement = componentRef.location.nativeElement;
DOM.addClass(backdropElement, 'md-backdrop');
DOM.appendChild(DOM.query('body'), backdropElement);
return componentRef;
diff --git a/modules/angular2_material/src/components/grid_list/grid_list.html b/modules/angular2_material/src/components/grid_list/grid_list.html
index 7ec47f33a2..f2b8cfdcd7 100644
--- a/modules/angular2_material/src/components/grid_list/grid_list.html
+++ b/modules/angular2_material/src/components/grid_list/grid_list.html
@@ -5,5 +5,5 @@