feat(web-workers) Add WebWorker Renderer
Allows angular apps to be rendered from the webworker! Closes #3052, #3053, and #3097
This commit is contained in:
@ -58,7 +58,8 @@ export function main() {
|
||||
|
||||
protoViewFactory = new FakeProtoViewFactory(protoViewFactoryResults);
|
||||
return new Compiler(directiveResolver, new CompilerCache(), tplResolver, cmpUrlMapper,
|
||||
urlResolver, renderCompiler, protoViewFactory, new FakeAppRootUrl());
|
||||
urlResolver, renderCompiler, protoViewFactory,
|
||||
new AppRootUrl("http://www.app.com"));
|
||||
}
|
||||
|
||||
beforeEach(() => {
|
||||
@ -398,8 +399,9 @@ export function main() {
|
||||
var reader: any = new SpyDirectiveResolver();
|
||||
|
||||
// create the compiler
|
||||
var compiler = new Compiler(reader, cache, tplResolver, cmpUrlMapper, new UrlResolver(),
|
||||
renderCompiler, protoViewFactory, new FakeAppRootUrl());
|
||||
var compiler =
|
||||
new Compiler(reader, cache, tplResolver, cmpUrlMapper, new UrlResolver(),
|
||||
renderCompiler, protoViewFactory, new AppRootUrl("http://www.app.com"));
|
||||
compiler.compileInHost(MainComponent)
|
||||
.then((protoViewRef) => {
|
||||
// the test should have failed if the resolver was called, so we're good
|
||||
@ -669,10 +671,6 @@ class SpyDirectiveResolver extends SpyObject {
|
||||
noSuchMethod(m) { return super.noSuchMethod(m) }
|
||||
}
|
||||
|
||||
class FakeAppRootUrl extends AppRootUrl {
|
||||
get value() { return 'http://www.app.com'; }
|
||||
}
|
||||
|
||||
class FakeViewResolver extends ViewResolver {
|
||||
_cmpViews: Map<Type, viewAnn.View> = new Map();
|
||||
|
||||
|
@ -276,5 +276,5 @@ export function main() {
|
||||
});
|
||||
}
|
||||
|
||||
var someComponent = DirectiveMetadata.create(
|
||||
export var someComponent = DirectiveMetadata.create(
|
||||
{id: 'someComponent', type: DirectiveMetadata.COMPONENT_TYPE, selector: 'some-comp'});
|
||||
|
@ -68,7 +68,7 @@ export class DomTestbed {
|
||||
@Inject(DOCUMENT_TOKEN) document) {
|
||||
this.renderer = renderer;
|
||||
this.compiler = compiler;
|
||||
this.rootEl = el('<div id="root"></div>');
|
||||
this.rootEl = el('<div id="root" class="rootElem"></div>');
|
||||
var oldRoots = DOM.querySelectorAll(document, '#root');
|
||||
for (var i = 0; i < oldRoots.length; i++) {
|
||||
DOM.remove(oldRoots[i]);
|
||||
|
@ -0,0 +1,24 @@
|
||||
import {AsyncTestCompleter, inject, describe, it, expect} from "angular2/test_lib";
|
||||
import {RenderProtoViewRef} from "angular2/src/render/api";
|
||||
import {RenderProtoViewRefStore} from "angular2/src/web-workers/shared/render_proto_view_ref_store";
|
||||
|
||||
export function main() {
|
||||
describe("RenderProtoViewRefStore", () => {
|
||||
it("should store and return the correct reference", () => {
|
||||
var store = new RenderProtoViewRefStore(true);
|
||||
var ref1 = new RenderProtoViewRef();
|
||||
var index1 = store.storeRenderProtoViewRef(ref1);
|
||||
expect(store.retreiveRenderProtoViewRef(index1)).toBe(ref1);
|
||||
var ref2 = new RenderProtoViewRef();
|
||||
var index2 = store.storeRenderProtoViewRef(ref2);
|
||||
expect(store.retreiveRenderProtoViewRef(index2)).toBe(ref2);
|
||||
});
|
||||
|
||||
it("should cache index numbers", () => {
|
||||
var store = new RenderProtoViewRefStore(true);
|
||||
var ref = new RenderProtoViewRef();
|
||||
var index = store.storeRenderProtoViewRef(ref);
|
||||
expect(store.storeRenderProtoViewRef(ref)).toEqual(index);
|
||||
});
|
||||
});
|
||||
}
|
@ -0,0 +1,120 @@
|
||||
import {AsyncTestCompleter, beforeEach, inject, describe, it, expect} from "angular2/test_lib";
|
||||
import {RenderViewWithFragments, RenderViewRef, RenderFragmentRef} from "angular2/src/render/api";
|
||||
import {
|
||||
RenderViewWithFragmentsStore,
|
||||
WorkerRenderViewRef,
|
||||
WorkerRenderFragmentRef
|
||||
} from "angular2/src/web-workers/shared/render_view_with_fragments_store";
|
||||
import {List, ListWrapper} from "angular2/src/facade/collection";
|
||||
|
||||
export function main() {
|
||||
describe("RenderViewWithFragmentsStore", () => {
|
||||
describe("on WebWorker", () => {
|
||||
var store;
|
||||
beforeEach(() => { store = new RenderViewWithFragmentsStore(true); });
|
||||
|
||||
it("should allocate fragmentCount + 1 refs", () => {
|
||||
var view: RenderViewWithFragments = store.allocate(10);
|
||||
|
||||
var viewRef: WorkerRenderViewRef = <WorkerRenderViewRef>view.viewRef;
|
||||
expect(viewRef.refNumber).toEqual(0);
|
||||
|
||||
var fragmentRefs: List<WorkerRenderFragmentRef> =
|
||||
<List<WorkerRenderFragmentRef>>view.fragmentRefs;
|
||||
expect(fragmentRefs.length).toEqual(10);
|
||||
|
||||
for (var i = 0; i < fragmentRefs.length; i++) {
|
||||
expect(fragmentRefs[i].refNumber).toEqual(i + 1);
|
||||
}
|
||||
});
|
||||
|
||||
it("should not reuse a reference", () => {
|
||||
store.allocate(10);
|
||||
var view = store.allocate(0);
|
||||
var viewRef = <WorkerRenderViewRef>view.viewRef;
|
||||
expect(viewRef.refNumber).toEqual(11);
|
||||
});
|
||||
|
||||
it("should be serializable", () => {
|
||||
var view = store.allocate(1);
|
||||
expect(store.deserializeViewWithFragments(store.serializeViewWithFragments(view)))
|
||||
.toEqual(view);
|
||||
});
|
||||
});
|
||||
|
||||
describe("on UI", () => {
|
||||
var store;
|
||||
beforeEach(() => { store = new RenderViewWithFragmentsStore(false); });
|
||||
function createMockRenderViewWithFragments(): RenderViewWithFragments {
|
||||
var view = new MockRenderViewRef();
|
||||
var fragments = ListWrapper.createGrowableSize(20);
|
||||
for (var i = 0; i < 20; i++) {
|
||||
fragments[i] = new MockRenderFragmentRef();
|
||||
}
|
||||
|
||||
return new RenderViewWithFragments(view, fragments);
|
||||
}
|
||||
it("should associate views with the correct references", () => {
|
||||
var renderViewWithFragments = createMockRenderViewWithFragments();
|
||||
|
||||
store.store(renderViewWithFragments, 100);
|
||||
expect(store.retreive(100)).toBe(renderViewWithFragments.viewRef);
|
||||
|
||||
for (var i = 0; i < renderViewWithFragments.fragmentRefs.length; i++) {
|
||||
expect(store.retreive(101 + i)).toBe(renderViewWithFragments.fragmentRefs[i]);
|
||||
}
|
||||
});
|
||||
|
||||
describe("RenderViewWithFragments", () => {
|
||||
it("should be serializable", () => {
|
||||
var renderViewWithFragments = createMockRenderViewWithFragments();
|
||||
store.store(renderViewWithFragments, 0);
|
||||
|
||||
var deserialized = store.deserializeViewWithFragments(
|
||||
store.serializeViewWithFragments(renderViewWithFragments));
|
||||
expect(deserialized.viewRef).toBe(renderViewWithFragments.viewRef);
|
||||
|
||||
expect(deserialized.fragmentRefs.length)
|
||||
.toEqual(renderViewWithFragments.fragmentRefs.length);
|
||||
|
||||
for (var i = 0; i < deserialized.fragmentRefs.length; i++) {
|
||||
var val = deserialized.fragmentRefs[i];
|
||||
expect(val).toBe(renderViewWithFragments.fragmentRefs[i]);
|
||||
};
|
||||
});
|
||||
});
|
||||
|
||||
describe("RenderViewRef", () => {
|
||||
it("should be serializable", () => {
|
||||
var renderViewWithFragments = createMockRenderViewWithFragments();
|
||||
store.store(renderViewWithFragments, 0);
|
||||
|
||||
var deserialized = store.deserializeRenderViewRef(
|
||||
store.serializeRenderViewRef(renderViewWithFragments.viewRef));
|
||||
expect(deserialized).toBe(renderViewWithFragments.viewRef);
|
||||
});
|
||||
});
|
||||
|
||||
describe("RenderFragmentRef", () => {
|
||||
it("should be serializable", () => {
|
||||
var renderViewWithFragments = createMockRenderViewWithFragments();
|
||||
store.store(renderViewWithFragments, 0);
|
||||
|
||||
var serialized =
|
||||
store.serializeRenderFragmentRef(renderViewWithFragments.fragmentRefs[0]);
|
||||
var deserialized = store.deserializeRenderFragmentRef(serialized);
|
||||
|
||||
expect(deserialized).toBe(renderViewWithFragments.fragmentRefs[0]);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
class MockRenderViewRef extends RenderViewRef {
|
||||
constructor() { super(); }
|
||||
}
|
||||
|
||||
class MockRenderFragmentRef extends RenderFragmentRef {
|
||||
constructor() { super(); }
|
||||
}
|
343
modules/angular2/test/web-workers/worker/renderer_spec.ts
Normal file
343
modules/angular2/test/web-workers/worker/renderer_spec.ts
Normal file
@ -0,0 +1,343 @@
|
||||
import {
|
||||
AsyncTestCompleter,
|
||||
inject,
|
||||
describe,
|
||||
it,
|
||||
expect,
|
||||
beforeEach,
|
||||
createTestInjector,
|
||||
beforeEachBindings
|
||||
} from "angular2/test_lib";
|
||||
import {DOM} from 'angular2/src/dom/dom_adapter';
|
||||
import {DomTestbed, TestRootView, elRef} from '../../render/dom/dom_testbed';
|
||||
import {bind} from 'angular2/di';
|
||||
import {WorkerCompiler, WorkerRenderer} from "angular2/src/web-workers/worker/renderer";
|
||||
import {MessageBroker, UiArguments, FnArg} from "angular2/src/web-workers/worker/broker";
|
||||
import {Serializer} from "angular2/src/web-workers/shared/serializer";
|
||||
import {isPresent, isBlank, BaseException, Type} from "angular2/src/facade/lang";
|
||||
import {MapWrapper, ListWrapper} from "angular2/src/facade/collection";
|
||||
import {
|
||||
DirectiveMetadata,
|
||||
ProtoViewDto,
|
||||
RenderProtoViewRef,
|
||||
RenderViewWithFragments,
|
||||
ViewDefinition,
|
||||
RenderProtoViewMergeMapping,
|
||||
RenderViewRef,
|
||||
RenderFragmentRef
|
||||
} from "angular2/src/render/api";
|
||||
import {
|
||||
MessageBus,
|
||||
MessageBusSource,
|
||||
MessageBusSink,
|
||||
SourceListener
|
||||
} from "angular2/src/web-workers/shared/message_bus";
|
||||
import {
|
||||
RenderProtoViewRefStore,
|
||||
WebworkerRenderProtoViewRef
|
||||
} from "angular2/src/web-workers/shared/render_proto_view_ref_store";
|
||||
import {
|
||||
RenderViewWithFragmentsStore,
|
||||
WorkerRenderViewRef
|
||||
} from 'angular2/src/web-workers/shared/render_view_with_fragments_store';
|
||||
import {resolveInternalDomProtoView} from 'angular2/src/render/dom/view/proto_view';
|
||||
import {someComponent} from '../../render/dom/dom_renderer_integration_spec';
|
||||
import {WebWorkerMain} from 'angular2/src/web-workers/ui/impl';
|
||||
import {AnchorBasedAppRootUrl} from 'angular2/src/services/anchor_based_app_root_url';
|
||||
|
||||
export function main() {
|
||||
function createBroker(workerSerializer: Serializer, uiSerializer: Serializer, tb: DomTestbed,
|
||||
uiRenderViewStore: RenderViewWithFragmentsStore,
|
||||
workerRenderViewStore: RenderViewWithFragmentsStore): MessageBroker {
|
||||
// set up the two message buses to pass messages to each other
|
||||
var uiMessageBus = new MockMessageBus(new MockMessageBusSink(), new MockMessageBusSource());
|
||||
var workerMessageBus = new MockMessageBus(new MockMessageBusSink(), new MockMessageBusSource());
|
||||
uiMessageBus.attachToBus(workerMessageBus);
|
||||
workerMessageBus.attachToBus(uiMessageBus);
|
||||
|
||||
// set up the worker side
|
||||
var broker = new MessageBroker(workerMessageBus, workerSerializer);
|
||||
|
||||
// set up the ui side
|
||||
var webWorkerMain = new WebWorkerMain(tb.compiler, tb.renderer, uiRenderViewStore, uiSerializer,
|
||||
new AnchorBasedAppRootUrl());
|
||||
webWorkerMain.attachToWorker(uiMessageBus);
|
||||
return broker;
|
||||
}
|
||||
|
||||
function createWorkerRenderer(workerSerializer: Serializer, uiSerializer: Serializer,
|
||||
tb: DomTestbed, uiRenderViewStore: RenderViewWithFragmentsStore,
|
||||
workerRenderViewStore: RenderViewWithFragmentsStore):
|
||||
WorkerRenderer {
|
||||
var broker =
|
||||
createBroker(workerSerializer, uiSerializer, tb, uiRenderViewStore, workerRenderViewStore);
|
||||
return new WorkerRenderer(broker, workerRenderViewStore);
|
||||
}
|
||||
|
||||
function createWorkerCompiler(workerSerializer: Serializer, uiSerializer: Serializer,
|
||||
tb: DomTestbed): WorkerCompiler {
|
||||
var broker = createBroker(workerSerializer, uiSerializer, tb, null, null);
|
||||
return new WorkerCompiler(broker);
|
||||
}
|
||||
|
||||
describe("Web Worker Compiler", function() {
|
||||
var workerSerializer: Serializer;
|
||||
var uiSerializer: Serializer;
|
||||
var workerRenderProtoViewRefStore: RenderProtoViewRefStore;
|
||||
var uiRenderProtoViewRefStore: RenderProtoViewRefStore;
|
||||
var tb: DomTestbed;
|
||||
|
||||
beforeEach(() => {
|
||||
workerRenderProtoViewRefStore = new RenderProtoViewRefStore(true);
|
||||
uiRenderProtoViewRefStore = new RenderProtoViewRefStore(false);
|
||||
workerSerializer = createSerializer(workerRenderProtoViewRefStore, null);
|
||||
uiSerializer = createSerializer(uiRenderProtoViewRefStore, null);
|
||||
tb = createTestInjector([DomTestbed]).get(DomTestbed);
|
||||
});
|
||||
|
||||
function resolveWebWorkerRef(ref: RenderProtoViewRef) {
|
||||
var refNumber = (<WebworkerRenderProtoViewRef>ref).refNumber;
|
||||
return resolveInternalDomProtoView(uiRenderProtoViewRefStore.deserialize(refNumber));
|
||||
}
|
||||
|
||||
it('should build the proto view', inject([AsyncTestCompleter], (async) => {
|
||||
var compiler: WorkerCompiler = createWorkerCompiler(workerSerializer, uiSerializer, tb);
|
||||
|
||||
var dirMetadata = DirectiveMetadata.create(
|
||||
{id: 'id', selector: 'CUSTOM', type: DirectiveMetadata.COMPONENT_TYPE});
|
||||
compiler.compileHost(dirMetadata)
|
||||
.then((protoView) => {
|
||||
expect(DOM.tagName(DOM.firstChild(
|
||||
DOM.content(resolveWebWorkerRef(protoView.render).rootElement))))
|
||||
.toEqual('CUSTOM');
|
||||
expect(protoView).not.toBeNull();
|
||||
async.done();
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
describe("Web Worker Renderer", () => {
|
||||
beforeEachBindings(() => [DomTestbed]);
|
||||
var renderer: WorkerRenderer;
|
||||
var workerSerializer: Serializer;
|
||||
var workerRenderViewStore: RenderViewWithFragmentsStore;
|
||||
var uiRenderViewStore: RenderViewWithFragmentsStore;
|
||||
var uiSerializer: Serializer;
|
||||
var tb: DomTestbed;
|
||||
|
||||
/**
|
||||
* Seriliazes the given obj with the uiSerializer and then returns the version that
|
||||
* the worker would deserialize
|
||||
*/
|
||||
function serialize(obj: any, type: Type): any {
|
||||
var serialized = uiSerializer.serialize(obj, type);
|
||||
return workerSerializer.deserialize(serialized, type);
|
||||
}
|
||||
|
||||
beforeEach(() => {
|
||||
workerRenderViewStore = new RenderViewWithFragmentsStore(true);
|
||||
tb = createTestInjector([DomTestbed]).get(DomTestbed);
|
||||
uiRenderViewStore = new RenderViewWithFragmentsStore(false);
|
||||
workerSerializer = createSerializer(new RenderProtoViewRefStore(true), workerRenderViewStore);
|
||||
uiSerializer = createSerializer(new RenderProtoViewRefStore(false), uiRenderViewStore);
|
||||
renderer = createWorkerRenderer(workerSerializer, uiSerializer, tb, uiRenderViewStore,
|
||||
workerRenderViewStore);
|
||||
});
|
||||
|
||||
|
||||
it('should create and destroy root host views while using the given elements in place',
|
||||
inject([AsyncTestCompleter], (async) => {
|
||||
tb.compiler.compileHost(someComponent)
|
||||
.then((hostProtoViewDto: any) => {
|
||||
hostProtoViewDto = serialize(hostProtoViewDto, ProtoViewDto);
|
||||
var viewWithFragments =
|
||||
renderer.createRootHostView(hostProtoViewDto.render, 1, '#root');
|
||||
var view = new WorkerTestRootView(viewWithFragments, uiRenderViewStore);
|
||||
|
||||
expect(tb.rootEl.parentNode).toBeTruthy();
|
||||
expect(view.hostElement).toBe(tb.rootEl);
|
||||
|
||||
renderer.detachFragment(viewWithFragments.fragmentRefs[0]);
|
||||
renderer.destroyView(viewWithFragments.viewRef);
|
||||
expect(tb.rootEl.parentNode).toBeFalsy();
|
||||
|
||||
async.done();
|
||||
});
|
||||
}));
|
||||
|
||||
it('should update text nodes', inject([AsyncTestCompleter], (async) => {
|
||||
tb.compileAndMerge(
|
||||
someComponent,
|
||||
[
|
||||
new ViewDefinition(
|
||||
{componentId: 'someComponent', template: '{{a}}', directives: []})
|
||||
])
|
||||
.then((protoViewMergeMappings) => {
|
||||
protoViewMergeMappings =
|
||||
serialize(protoViewMergeMappings, RenderProtoViewMergeMapping);
|
||||
var rootView = renderer.createView(protoViewMergeMappings.mergedProtoViewRef, 1);
|
||||
renderer.hydrateView(rootView.viewRef);
|
||||
|
||||
renderer.setText(rootView.viewRef, 0, 'hello');
|
||||
var view = new WorkerTestRootView(rootView, uiRenderViewStore);
|
||||
expect(view.hostElement).toHaveText('hello');
|
||||
async.done();
|
||||
});
|
||||
}));
|
||||
|
||||
|
||||
it('should update any element property/attributes/class/style independent of the compilation on the root element and other elements',
|
||||
inject([AsyncTestCompleter], (async) => {
|
||||
tb.compileAndMerge(someComponent,
|
||||
[
|
||||
new ViewDefinition({
|
||||
componentId: 'someComponent',
|
||||
template: '<input [title]="y" style="position:absolute">',
|
||||
directives: []
|
||||
})
|
||||
])
|
||||
.then((protoViewMergeMappings) => {
|
||||
protoViewMergeMappings =
|
||||
serialize(protoViewMergeMappings, RenderProtoViewMergeMapping);
|
||||
|
||||
var checkSetters = (elr, el) => {
|
||||
renderer.setElementProperty(elr, 'tabIndex', 1);
|
||||
expect((<HTMLInputElement>el).tabIndex).toEqual(1);
|
||||
|
||||
renderer.setElementClass(elr, 'a', true);
|
||||
expect(DOM.hasClass(el, 'a')).toBe(true);
|
||||
renderer.setElementClass(elr, 'a', false);
|
||||
expect(DOM.hasClass(el, 'a')).toBe(false);
|
||||
|
||||
renderer.setElementStyle(elr, 'width', '10px');
|
||||
expect(DOM.getStyle(el, 'width')).toEqual('10px');
|
||||
renderer.setElementStyle(elr, 'width', null);
|
||||
expect(DOM.getStyle(el, 'width')).toEqual('');
|
||||
|
||||
renderer.setElementAttribute(elr, 'someAttr', 'someValue');
|
||||
expect(DOM.getAttribute(el, 'some-attr')).toEqual('someValue');
|
||||
};
|
||||
|
||||
var rootViewWithFragments =
|
||||
renderer.createView(protoViewMergeMappings.mergedProtoViewRef, 1);
|
||||
renderer.hydrateView(rootViewWithFragments.viewRef);
|
||||
|
||||
var rootView = new WorkerTestRootView(rootViewWithFragments, uiRenderViewStore);
|
||||
// root element
|
||||
checkSetters(elRef(rootViewWithFragments.viewRef, 0), rootView.hostElement);
|
||||
// nested elements
|
||||
checkSetters(elRef(rootViewWithFragments.viewRef, 1),
|
||||
DOM.firstChild(rootView.hostElement));
|
||||
|
||||
async.done();
|
||||
});
|
||||
}));
|
||||
|
||||
it('should add and remove empty fragments', inject([AsyncTestCompleter], (async) => {
|
||||
tb.compileAndMerge(someComponent,
|
||||
[
|
||||
new ViewDefinition({
|
||||
componentId: 'someComponent',
|
||||
template: '<template></template><template></template>',
|
||||
directives: []
|
||||
})
|
||||
])
|
||||
.then((protoViewMergeMappings) => {
|
||||
protoViewMergeMappings =
|
||||
serialize(protoViewMergeMappings, RenderProtoViewMergeMapping);
|
||||
var rootViewWithFragments =
|
||||
renderer.createView(protoViewMergeMappings.mergedProtoViewRef, 3);
|
||||
|
||||
var elr = elRef(rootViewWithFragments.viewRef, 1);
|
||||
var rootView = new WorkerTestRootView(rootViewWithFragments, uiRenderViewStore);
|
||||
expect(rootView.hostElement).toHaveText('');
|
||||
var fragment = rootViewWithFragments.fragmentRefs[1];
|
||||
var fragment2 = rootViewWithFragments.fragmentRefs[2];
|
||||
renderer.attachFragmentAfterElement(elr, fragment);
|
||||
renderer.attachFragmentAfterFragment(fragment, fragment2);
|
||||
renderer.detachFragment(fragment);
|
||||
renderer.detachFragment(fragment2);
|
||||
expect(rootView.hostElement).toHaveText('');
|
||||
|
||||
async.done();
|
||||
});
|
||||
}));
|
||||
|
||||
if (DOM.supportsDOMEvents()) {
|
||||
it('should call actions on the element independent of the compilation',
|
||||
inject([AsyncTestCompleter], (async) => {
|
||||
tb.compileAndMerge(someComponent,
|
||||
[
|
||||
new ViewDefinition({
|
||||
componentId: 'someComponent',
|
||||
template: '<input [title]="y"></input>',
|
||||
directives: []
|
||||
})
|
||||
])
|
||||
.then((protoViewMergeMappings) => {
|
||||
protoViewMergeMappings =
|
||||
serialize(protoViewMergeMappings, RenderProtoViewMergeMapping);
|
||||
var rootViewWithFragments =
|
||||
renderer.createView(protoViewMergeMappings.mergedProtoViewRef, 1);
|
||||
var rootView = new WorkerTestRootView(rootViewWithFragments, uiRenderViewStore);
|
||||
|
||||
renderer.invokeElementMethod(elRef(rootViewWithFragments.viewRef, 1),
|
||||
'setAttribute', ['a', 'b']);
|
||||
|
||||
expect(DOM.getAttribute(DOM.childNodes(rootView.hostElement)[0], 'a'))
|
||||
.toEqual('b');
|
||||
async.done();
|
||||
});
|
||||
}));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
class WorkerTestRootView extends TestRootView {
|
||||
constructor(workerViewWithFragments: RenderViewWithFragments, uiRenderViewStore) {
|
||||
super(new RenderViewWithFragments(
|
||||
uiRenderViewStore.retreive(
|
||||
(<WorkerRenderViewRef>workerViewWithFragments.viewRef).refNumber),
|
||||
ListWrapper.map(workerViewWithFragments.fragmentRefs,
|
||||
(val) => { return uiRenderViewStore.retreive(val.refNumber); })));
|
||||
}
|
||||
}
|
||||
|
||||
function createSerializer(protoViewRefStore: RenderProtoViewRefStore,
|
||||
renderViewStore: RenderViewWithFragmentsStore): Serializer {
|
||||
var injector = createTestInjector([
|
||||
bind(RenderProtoViewRefStore)
|
||||
.toValue(protoViewRefStore),
|
||||
bind(RenderViewWithFragmentsStore).toValue(renderViewStore)
|
||||
]);
|
||||
return injector.get(Serializer);
|
||||
}
|
||||
|
||||
class MockMessageBusSource implements MessageBusSource {
|
||||
private _listenerStore: Map<int, SourceListener> = new Map<int, SourceListener>();
|
||||
private _numListeners: number = 0;
|
||||
|
||||
addListener(fn: SourceListener): int {
|
||||
this._listenerStore.set(++this._numListeners, fn);
|
||||
return this._numListeners;
|
||||
}
|
||||
|
||||
removeListener(index: int): void { MapWrapper.delete(this._listenerStore, index); }
|
||||
|
||||
receive(message: Object): void {
|
||||
MapWrapper.forEach(this._listenerStore, (fn: SourceListener, key: int) => { fn(message); });
|
||||
}
|
||||
}
|
||||
|
||||
class MockMessageBusSink implements MessageBusSink {
|
||||
private _sendTo: MockMessageBusSource;
|
||||
|
||||
send(message: Object): void { this._sendTo.receive({'data': message}); }
|
||||
|
||||
attachToSource(source: MockMessageBusSource) { this._sendTo = source; }
|
||||
}
|
||||
|
||||
class MockMessageBus implements MessageBus {
|
||||
constructor(public sink: MockMessageBusSink, public source: MockMessageBusSource) {}
|
||||
attachToBus(bus: MockMessageBus) { this.sink.attachToSource(bus.source); }
|
||||
}
|
Reference in New Issue
Block a user