refactor(views): clean up creating views in place and extract view_hydrator
Major changes: - `compiler.compileRoot(el, type)` -> `compiler.compileInHost(type) + viewHydrator.hydrateHostViewInPlace(el, view)` - move all `hydrate`/`dehydrate` methods out of `View` and `ViewContainer` into a standalone class `view_hydrator` as private methods and provide new public methods dedicated to the individual use cases. Note: This PR does not change the current functionality, only moves it into different places. See design discussion in #1351, in preparation for imperative views.
This commit is contained in:
+5
-5
@@ -361,7 +361,7 @@ export function main() {
|
||||
});
|
||||
}));
|
||||
|
||||
it('should create root proto views', inject([AsyncTestCompleter], (async) => {
|
||||
it('should create host proto views', inject([AsyncTestCompleter], (async) => {
|
||||
tplResolver.setView(MainComponent, new View({template: '<div></div>'}));
|
||||
var rootProtoView = createProtoView([
|
||||
createComponentElementBinder(reader, MainComponent)
|
||||
@@ -373,7 +373,7 @@ export function main() {
|
||||
],
|
||||
[rootProtoView, mainProtoView]
|
||||
);
|
||||
compiler.compileRoot(null, MainComponent).then( (protoView) => {
|
||||
compiler.compileInHost(MainComponent).then( (protoView) => {
|
||||
expect(protoView).toBe(rootProtoView);
|
||||
expect(rootProtoView.elementBinders[0].nestedProtoView).toBe(mainProtoView);
|
||||
async.done();
|
||||
@@ -388,7 +388,7 @@ function createDirectiveBinding(reader, type) {
|
||||
}
|
||||
|
||||
function createProtoView(elementBinders = null) {
|
||||
var pv = new AppProtoView(null, null, null);
|
||||
var pv = new AppProtoView(null, null);
|
||||
if (isBlank(elementBinders)) {
|
||||
elementBinders = [];
|
||||
}
|
||||
@@ -497,7 +497,7 @@ class FakeRenderer extends renderApi.Renderer {
|
||||
return PromiseWrapper.resolve(ListWrapper.removeAt(this._results, 0));
|
||||
}
|
||||
|
||||
createRootProtoView(elementOrSelector, componentId):Promise<renderApi.ProtoViewDto> {
|
||||
createHostProtoView(componentId):Promise<renderApi.ProtoViewDto> {
|
||||
return PromiseWrapper.resolve(
|
||||
createRenderProtoView([createRenderComponentElementBinder(0)])
|
||||
);
|
||||
@@ -545,7 +545,7 @@ class FakeProtoViewFactory extends ProtoViewFactory {
|
||||
_results:List;
|
||||
|
||||
constructor(results) {
|
||||
super(null, null);
|
||||
super(null);
|
||||
this.requests = [];
|
||||
this._results = results;
|
||||
}
|
||||
|
||||
@@ -24,26 +24,32 @@ import {ElementRef, ElementInjector, ProtoElementInjector, PreBuiltObjects} from
|
||||
import {Compiler} from 'angular2/src/core/compiler/compiler';
|
||||
import {AppProtoView, AppView} from 'angular2/src/core/compiler/view';
|
||||
import {ViewFactory} from 'angular2/src/core/compiler/view_factory'
|
||||
import {Renderer} from 'angular2/src/render/api';
|
||||
import {AppViewHydrator} from 'angular2/src/core/compiler/view_hydrator';
|
||||
|
||||
export function main() {
|
||||
describe("DynamicComponentLoader", () => {
|
||||
var compiler;
|
||||
var viewFactory;
|
||||
var directiveMetadataReader;
|
||||
var renderer;
|
||||
var viewHydrator;
|
||||
var loader;
|
||||
|
||||
beforeEach( () => {
|
||||
compiler = new SpyCompiler();
|
||||
viewFactory = new SpyViewFactory();
|
||||
renderer = new SpyRenderer();
|
||||
viewHydrator = new SpyAppViewHydrator();
|
||||
directiveMetadataReader = new DirectiveMetadataReader();
|
||||
loader = new DynamicComponentLoader(compiler, directiveMetadataReader, renderer, viewFactory);;
|
||||
loader = new DynamicComponentLoader(compiler, directiveMetadataReader, viewFactory, viewHydrator);
|
||||
});
|
||||
|
||||
function createProtoView() {
|
||||
return new AppProtoView(null, null, null);
|
||||
return new AppProtoView(null, null);
|
||||
}
|
||||
|
||||
function createEmptyView() {
|
||||
var view = new AppView(null, createProtoView(), MapWrapper.create());
|
||||
view.init(null, [], [], [], [], []);
|
||||
return view;
|
||||
}
|
||||
|
||||
function createElementRef(view, boundElementIndex) {
|
||||
@@ -67,23 +73,25 @@ export function main() {
|
||||
});
|
||||
});
|
||||
|
||||
it('should add the child view into the host view', inject([AsyncTestCompleter], (async) => {
|
||||
it('should compile, create and hydrate the view', inject([AsyncTestCompleter], (async) => {
|
||||
var log = [];
|
||||
var hostView = new SpyAppView();
|
||||
var childView = new SpyAppView();
|
||||
hostView.spy('setDynamicComponentChildView').andCallFake( (boundElementIndex, childView) => {
|
||||
ListWrapper.push(log, ['setDynamicComponentChildView', boundElementIndex, childView]);
|
||||
var protoView = createProtoView();
|
||||
var hostView = createEmptyView();
|
||||
var childView = createEmptyView();
|
||||
viewHydrator.spy('hydrateDynamicComponentView').andCallFake( (hostView, boundElementIndex,
|
||||
componentView, componentDirective, injector) => {
|
||||
ListWrapper.push(log, ['hydrateDynamicComponentView', hostView, boundElementIndex, componentView]);
|
||||
});
|
||||
childView.spy('hydrate').andCallFake( (appInjector, hostElementInjector, context, locals) => {
|
||||
ListWrapper.push(log, 'hydrate');
|
||||
viewFactory.spy('getView').andCallFake( (protoView) => {
|
||||
ListWrapper.push(log, ['getView', protoView]);
|
||||
return childView;
|
||||
});
|
||||
compiler.spy('compile').andCallFake( (_) => PromiseWrapper.resolve(createProtoView()));
|
||||
viewFactory.spy('getView').andCallFake( (_) => childView);
|
||||
compiler.spy('compile').andCallFake( (_) => PromiseWrapper.resolve(protoView));
|
||||
|
||||
var elementRef = createElementRef(hostView, 23);
|
||||
loader.loadIntoExistingLocation(SomeComponent, elementRef).then( (componentRef) => {
|
||||
expect(log[0]).toEqual('hydrate');
|
||||
expect(log[1]).toEqual(['setDynamicComponentChildView', 23, childView]);
|
||||
expect(log[0]).toEqual(['getView', protoView]);
|
||||
expect(log[1]).toEqual(['hydrateDynamicComponentView', hostView, 23, childView]);
|
||||
async.done();
|
||||
});
|
||||
}));
|
||||
@@ -112,8 +120,8 @@ class SpyCompiler extends SpyObject {noSuchMethod(m){return super.noSuchMethod(m
|
||||
class SpyViewFactory extends SpyObject {noSuchMethod(m){return super.noSuchMethod(m)}}
|
||||
|
||||
@proxy
|
||||
@IMPLEMENTS(Renderer)
|
||||
class SpyRenderer extends SpyObject {noSuchMethod(m){return super.noSuchMethod(m)}}
|
||||
@IMPLEMENTS(AppViewHydrator)
|
||||
class SpyAppViewHydrator extends SpyObject {noSuchMethod(m){return super.noSuchMethod(m)}}
|
||||
|
||||
@proxy
|
||||
@IMPLEMENTS(AppView)
|
||||
|
||||
+15
-13
@@ -614,7 +614,7 @@ export function main() {
|
||||
});
|
||||
|
||||
it('should return viewContainer', function () {
|
||||
var viewContainer = new ViewContainer(null, null, null, null);
|
||||
var viewContainer = new ViewContainer(null, null, null, null, null);
|
||||
var inj = injector([], null, null, new PreBuiltObjects(null, null, viewContainer, null));
|
||||
|
||||
expect(inj.get(ViewContainer)).toEqual(viewContainer);
|
||||
@@ -631,21 +631,21 @@ export function main() {
|
||||
describe("dynamicallyCreateComponent", () => {
|
||||
it("should create a component dynamically", () => {
|
||||
var inj = injector([]);
|
||||
inj.dynamicallyCreateComponent(SimpleDirective, null, null);
|
||||
inj.dynamicallyCreateComponent(DirectiveBinding.createFromType(SimpleDirective, null), null);
|
||||
expect(inj.getDynamicallyLoadedComponent()).toBeAnInstanceOf(SimpleDirective);
|
||||
expect(inj.get(SimpleDirective)).toBeAnInstanceOf(SimpleDirective);
|
||||
});
|
||||
|
||||
it("should inject parent dependencies into the dynamically-loaded component", () => {
|
||||
var inj = parentChildInjectors([SimpleDirective], []);
|
||||
inj.dynamicallyCreateComponent(NeedDirectiveFromAncestor, null, null);
|
||||
inj.dynamicallyCreateComponent(DirectiveBinding.createFromType(NeedDirectiveFromAncestor, null), null);
|
||||
expect(inj.getDynamicallyLoadedComponent()).toBeAnInstanceOf(NeedDirectiveFromAncestor);
|
||||
expect(inj.getDynamicallyLoadedComponent().dependency).toBeAnInstanceOf(SimpleDirective);
|
||||
});
|
||||
|
||||
it("should not inject the proxy component into the children of the dynamically-loaded component", () => {
|
||||
var injWithDynamicallyLoadedComponent = injector([SimpleDirective]);
|
||||
injWithDynamicallyLoadedComponent.dynamicallyCreateComponent(SomeOtherDirective, null, null);
|
||||
injWithDynamicallyLoadedComponent.dynamicallyCreateComponent(DirectiveBinding.createFromType(SomeOtherDirective, null), null);
|
||||
|
||||
var shadowDomProtoInjector = new ProtoElementInjector(null, 0, [NeedDirectiveFromAncestor], false);
|
||||
var shadowDomInj = shadowDomProtoInjector.instantiate(null);
|
||||
@@ -658,14 +658,14 @@ export function main() {
|
||||
it("should not inject the dynamically-loaded component into directives on the same element", () => {
|
||||
var proto = new ProtoElementInjector(null, 0, [NeedsDirective], false);
|
||||
var inj = proto.instantiate(null);
|
||||
inj.dynamicallyCreateComponent(SimpleDirective, null, null);
|
||||
inj.dynamicallyCreateComponent(DirectiveBinding.createFromType(SimpleDirective, null), null);
|
||||
|
||||
expect(() => inj.instantiateDirectives(null, null, null, null)).toThrowError();
|
||||
});
|
||||
|
||||
it("should inject the dynamically-loaded component into the children of the dynamically-loaded component", () => {
|
||||
var injWithDynamicallyLoadedComponent = injector([]);
|
||||
injWithDynamicallyLoadedComponent.dynamicallyCreateComponent(SimpleDirective, null, null);
|
||||
injWithDynamicallyLoadedComponent.dynamicallyCreateComponent(DirectiveBinding.createFromType(SimpleDirective, null), null);
|
||||
|
||||
var shadowDomProtoInjector = new ProtoElementInjector(null, 0, [NeedDirectiveFromAncestor], false);
|
||||
var shadowDomInjector = shadowDomProtoInjector.instantiate(null);
|
||||
@@ -678,8 +678,10 @@ export function main() {
|
||||
it("should remove the dynamically-loaded component when dehydrating", () => {
|
||||
var inj = injector([]);
|
||||
inj.dynamicallyCreateComponent(
|
||||
DirectiveWithDestroy,
|
||||
new DummyDirective({lifecycle: [onDestroy]}),
|
||||
DirectiveBinding.createFromType(
|
||||
DirectiveWithDestroy,
|
||||
new DummyDirective({lifecycle: [onDestroy]})
|
||||
),
|
||||
null);
|
||||
var dir = inj.getDynamicallyLoadedComponent();
|
||||
|
||||
@@ -696,7 +698,7 @@ export function main() {
|
||||
it("should inject services of the dynamically-loaded component", () => {
|
||||
var inj = injector([]);
|
||||
var appInjector = Injector.resolveAndCreate([bind("service").toValue("Service")]);
|
||||
inj.dynamicallyCreateComponent(NeedsService, null, appInjector);
|
||||
inj.dynamicallyCreateComponent(DirectiveBinding.createFromType(NeedsService, null), appInjector);
|
||||
expect(inj.getDynamicallyLoadedComponent().service).toEqual("Service");
|
||||
});
|
||||
});
|
||||
@@ -706,13 +708,13 @@ export function main() {
|
||||
function createpreBuildObject(eventName, eventHandler) {
|
||||
var handlers = StringMapWrapper.create();
|
||||
StringMapWrapper.set(handlers, eventName, eventHandler);
|
||||
var pv = new AppProtoView(null, null, null);
|
||||
var pv = new AppProtoView(null, null);
|
||||
pv.bindElement(null, 0, null, null, null);
|
||||
var eventBindings = ListWrapper.create();
|
||||
ListWrapper.push(eventBindings, new EventBinding(eventName, new Parser(new Lexer()).parseAction('handler()', '')));
|
||||
pv.bindEvent(eventBindings);
|
||||
|
||||
var view = new AppView(pv, MapWrapper.create());
|
||||
var view = new AppView(null, pv, MapWrapper.create());
|
||||
view.context = new ContextWithHandler(eventHandler);
|
||||
return new PreBuiltObjects(view, null, null, null);
|
||||
}
|
||||
@@ -751,8 +753,8 @@ export function main() {
|
||||
|
||||
beforeEach( () => {
|
||||
renderer = new FakeRenderer();
|
||||
var protoView = new AppProtoView(renderer, null, null);
|
||||
view = new AppView(protoView, MapWrapper.create());
|
||||
var protoView = new AppProtoView(null, null);
|
||||
view = new AppView(renderer, protoView, MapWrapper.create());
|
||||
view.render = new ViewRef();
|
||||
});
|
||||
|
||||
|
||||
+1
-2
@@ -300,7 +300,6 @@ export function main() {
|
||||
}));
|
||||
|
||||
tb.createView(MyComp, {context: ctx}).then((view) => {
|
||||
|
||||
view.detectChanges();
|
||||
|
||||
var childNodesOfWrapper = view.rootNodes[0].childNodes;
|
||||
@@ -582,7 +581,7 @@ export function main() {
|
||||
dispatchEvent(DOM.getGlobalEventTarget("document"), 'domEvent');
|
||||
expect(listener.eventType).toEqual('document_domEvent');
|
||||
|
||||
view.rawView.dehydrate();
|
||||
view.destroy();
|
||||
listener = injector.get(DecoratorListeningDomEvent);
|
||||
dispatchEvent(DOM.getGlobalEventTarget("body"), 'domEvent');
|
||||
expect(listener.eventType).toEqual('');
|
||||
|
||||
+12
-2
@@ -16,6 +16,7 @@ import {
|
||||
} from 'angular2/test_lib';
|
||||
import {IMPLEMENTS, isBlank} from 'angular2/src/facade/lang';
|
||||
import {ViewFactory} from 'angular2/src/core/compiler/view_factory';
|
||||
import {Renderer, ViewRef} from 'angular2/src/render/api';
|
||||
import {AppProtoView, AppView} from 'angular2/src/core/compiler/view';
|
||||
import {DirectiveBinding, ElementInjector} from 'angular2/src/core/compiler/element_injector';
|
||||
import {DirectiveMetadataReader} from 'angular2/src/core/compiler/directive_metadata_reader';
|
||||
@@ -26,13 +27,15 @@ import {ChangeDetector, ProtoChangeDetector} from 'angular2/change_detection';
|
||||
export function main() {
|
||||
describe('AppViewFactory', () => {
|
||||
var reader;
|
||||
var renderer;
|
||||
|
||||
beforeEach( () => {
|
||||
renderer = new SpyRenderer();
|
||||
reader = new DirectiveMetadataReader();
|
||||
});
|
||||
|
||||
function createViewFactory({capacity}):ViewFactory {
|
||||
return new ViewFactory(capacity);
|
||||
return new ViewFactory(capacity, renderer);
|
||||
}
|
||||
|
||||
function createProtoChangeDetector() {
|
||||
@@ -47,7 +50,7 @@ export function main() {
|
||||
if (isBlank(binders)) {
|
||||
binders = [];
|
||||
}
|
||||
var pv = new AppProtoView(null, null, createProtoChangeDetector());
|
||||
var pv = new AppProtoView(null, createProtoChangeDetector());
|
||||
pv.elementBinders = binders;
|
||||
return pv;
|
||||
}
|
||||
@@ -154,6 +157,13 @@ export function main() {
|
||||
@Component({ selector: 'someComponent' })
|
||||
class SomeComponent {}
|
||||
|
||||
@proxy
|
||||
@IMPLEMENTS(Renderer)
|
||||
class SpyRenderer extends SpyObject {
|
||||
constructor(){super(Renderer);}
|
||||
noSuchMethod(m){return super.noSuchMethod(m)}
|
||||
}
|
||||
|
||||
@proxy
|
||||
@IMPLEMENTS(ChangeDetector)
|
||||
class SpyChangeDetector extends SpyObject {
|
||||
|
||||
+45
-33
@@ -24,15 +24,18 @@ import {ElementBinder} from 'angular2/src/core/compiler/element_binder';
|
||||
import {DirectiveBinding, ElementInjector} from 'angular2/src/core/compiler/element_injector';
|
||||
import {DirectiveMetadataReader} from 'angular2/src/core/compiler/directive_metadata_reader';
|
||||
import {Component} from 'angular2/src/core/annotations/annotations';
|
||||
import {AppViewHydrator} from 'angular2/src/core/compiler/view_hydrator';
|
||||
|
||||
export function main() {
|
||||
describe('AppView', () => {
|
||||
describe('AppViewHydrator', () => {
|
||||
var renderer;
|
||||
var reader;
|
||||
var hydrator;
|
||||
|
||||
beforeEach( () => {
|
||||
renderer = new SpyRenderer();
|
||||
reader = new DirectiveMetadataReader();
|
||||
hydrator = new AppViewHydrator(renderer);
|
||||
});
|
||||
|
||||
function createDirectiveBinding(type) {
|
||||
@@ -61,7 +64,7 @@ export function main() {
|
||||
if (isBlank(binders)) {
|
||||
binders = [];
|
||||
}
|
||||
var res = new AppProtoView(renderer, null, null);
|
||||
var res = new AppProtoView(null, null);
|
||||
res.elementBinders = binders;
|
||||
return res;
|
||||
}
|
||||
@@ -75,8 +78,15 @@ export function main() {
|
||||
]);
|
||||
}
|
||||
|
||||
function createEmptyView() {
|
||||
var view = new AppView(renderer, createProtoView(), MapWrapper.create());
|
||||
var changeDetector = new SpyChangeDetector();
|
||||
view.init(changeDetector, [], [], [], [], []);
|
||||
return view;
|
||||
}
|
||||
|
||||
function createHostView(pv, shadowView, componentInstance) {
|
||||
var view = new AppView(pv, MapWrapper.create());
|
||||
var view = new AppView(renderer, pv, MapWrapper.create());
|
||||
var changeDetector = new SpyChangeDetector();
|
||||
var eij = createElementInjector();
|
||||
eij.spy('getComponent').andCallFake( () => componentInstance );
|
||||
@@ -85,84 +95,93 @@ export function main() {
|
||||
return view;
|
||||
}
|
||||
|
||||
describe('setDynamicComponentChildView', () => {
|
||||
function hydrate(view) {
|
||||
hydrator.hydrateInPlaceHostView(null, null, view, null);
|
||||
}
|
||||
|
||||
function dehydrate(view) {
|
||||
hydrator.dehydrateInPlaceHostView(null, view);
|
||||
}
|
||||
|
||||
describe('hydrateDynamicComponentView', () => {
|
||||
|
||||
it('should not allow to use non component indices', () => {
|
||||
var pv = createProtoView([createEmptyElBinder()]);
|
||||
var view = createHostView(pv, null, null);
|
||||
var shadowView = new FakeAppView();
|
||||
var shadowView = createEmptyView();
|
||||
expect(
|
||||
() => view.setDynamicComponentChildView(0, shadowView)
|
||||
() => hydrator.hydrateDynamicComponentView(view, 0, shadowView, null, null)
|
||||
).toThrowError('There is no dynamic component directive at element 0');
|
||||
});
|
||||
|
||||
it('should not allow to use static component indices', () => {
|
||||
var pv = createHostProtoView(createProtoView());
|
||||
var view = createHostView(pv, null, null);
|
||||
var shadowView = new FakeAppView();
|
||||
var shadowView = createEmptyView();
|
||||
expect(
|
||||
() => view.setDynamicComponentChildView(0, shadowView)
|
||||
() => hydrator.hydrateDynamicComponentView(view, 0, shadowView, null, null)
|
||||
).toThrowError('There is no dynamic component directive at element 0');
|
||||
});
|
||||
|
||||
it('should not allow to overwrite an existing component', () => {
|
||||
var pv = createHostProtoView(null);
|
||||
var shadowView = new FakeAppView();
|
||||
var shadowView = createEmptyView();
|
||||
var view = createHostView(pv, null, null);
|
||||
view.setDynamicComponentChildView(0, shadowView);
|
||||
renderer.spy('createDynamicComponentView').andCallFake( (a,b,c) => {
|
||||
return [new ViewRef(), new ViewRef()];
|
||||
});
|
||||
hydrator.hydrateDynamicComponentView(view, 0, shadowView, createDirectiveBinding(SomeComponent), null);
|
||||
expect(
|
||||
() => view.setDynamicComponentChildView(0, shadowView)
|
||||
() => hydrator.hydrateDynamicComponentView(view, 0, shadowView, null, null)
|
||||
).toThrowError('There already is a bound component at element 0');
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('hydrate', () => {
|
||||
describe('hydrate... shared functionality', () => {
|
||||
|
||||
it('should hydrate existing child components', () => {
|
||||
var hostPv = createHostProtoView(createProtoView());
|
||||
var componentInstance = {};
|
||||
var shadowView = new FakeAppView();
|
||||
var shadowView = createEmptyView();
|
||||
var hostView = createHostView(hostPv, shadowView, componentInstance);
|
||||
renderer.spy('createView').andCallFake( (_) => {
|
||||
renderer.spy('createInPlaceHostView').andCallFake( (a,b,c) => {
|
||||
return [new ViewRef(), new ViewRef()];
|
||||
});
|
||||
|
||||
hostView.hydrate(null, null, null, null);
|
||||
hydrate(hostView);
|
||||
|
||||
expect(shadowView.spy('hydrate')).not.toHaveBeenCalled();
|
||||
expect(shadowView.spy('internalHydrateRecurse')).toHaveBeenCalled();
|
||||
expect(shadowView.hydrated()).toBe(true);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('dehydrate', () => {
|
||||
describe('dehydrate... shared functionality', () => {
|
||||
var hostView;
|
||||
var shadowView;
|
||||
|
||||
function createAndHydrate(nestedProtoView) {
|
||||
var componentInstance = {};
|
||||
shadowView = new FakeAppView();
|
||||
shadowView = createEmptyView();
|
||||
var hostPv = createHostProtoView(nestedProtoView);
|
||||
hostView = createHostView(hostPv, shadowView, componentInstance);
|
||||
renderer.spy('createView').andCallFake( (_) => {
|
||||
renderer.spy('createInPlaceHostView').andCallFake( (a,b,c) => {
|
||||
return [new ViewRef(), new ViewRef()];
|
||||
});
|
||||
|
||||
hostView.hydrate(null, null, null, null);
|
||||
hydrate(hostView);
|
||||
}
|
||||
|
||||
it('should dehydrate child components', () => {
|
||||
createAndHydrate(createProtoView());
|
||||
hostView.dehydrate();
|
||||
dehydrate(hostView);
|
||||
|
||||
expect(shadowView.spy('dehydrate')).not.toHaveBeenCalled();
|
||||
expect(shadowView.spy('internalDehydrateRecurse')).toHaveBeenCalled();
|
||||
expect(shadowView.hydrated()).toBe(false);
|
||||
});
|
||||
|
||||
it('should not clear static child components', () => {
|
||||
createAndHydrate(createProtoView());
|
||||
hostView.dehydrate();
|
||||
dehydrate(hostView);
|
||||
|
||||
expect(hostView.componentChildViews[0]).toBe(shadowView);
|
||||
expect(hostView.changeDetector.spy('removeShadowDomChild')).not.toHaveBeenCalled();
|
||||
@@ -170,7 +189,7 @@ export function main() {
|
||||
|
||||
it('should clear dynamic child components', () => {
|
||||
createAndHydrate(null);
|
||||
hostView.dehydrate();
|
||||
dehydrate(hostView);
|
||||
|
||||
expect(hostView.componentChildViews[0]).toBe(null);
|
||||
expect(hostView.changeDetector.spy('removeShadowDomChild')).toHaveBeenCalledWith(shadowView.changeDetector);
|
||||
@@ -204,10 +223,3 @@ class SpyElementInjector extends SpyObject {
|
||||
constructor(){super(ElementInjector);}
|
||||
noSuchMethod(m){return super.noSuchMethod(m)}
|
||||
}
|
||||
|
||||
@proxy
|
||||
@IMPLEMENTS(AppView)
|
||||
class FakeAppView extends SpyObject {
|
||||
constructor(){super(AppView);}
|
||||
noSuchMethod(m){return super.noSuchMethod(m)}
|
||||
}
|
||||
Reference in New Issue
Block a user