feat(WebWorker): Add Router Support for WebWorker Apps

Closes #3563.
This commit is contained in:
Jason Teplitz
2016-01-21 09:58:28 -08:00
committed by Rado Kirov
parent 800c8f196f
commit 8bea667a0b
43 changed files with 839 additions and 153 deletions
@@ -4,7 +4,8 @@ import 'package:angular2/src/platform/server/html_adapter.dart';
import "package:angular2/testing_internal.dart";
import "package:angular2/src/core/reflection/reflection_capabilities.dart";
import "package:angular2/src/core/reflection/reflection.dart";
import "package:angular2/src/platform/worker_app_common.dart" show WORKER_APP_APPLICATION_COMMON;
import "package:angular2/src/platform/worker_app_common.dart"
show WORKER_APP_APPLICATION_COMMON;
import "package:angular2/platform/worker_app.dart" show WORKER_APP_PLATFORM;
import "package:angular2/core.dart";
import "../shared/web_worker_test_util.dart";
@@ -19,7 +20,7 @@ main() {
reflector.reflectionCapabilities = new ReflectionCapabilities();
var buses = createPairedMessageBuses();
platform([WORKER_APP_PLATFORM])
.application([WORKER_APP_APPLICATION_COMMON]);
.application([WORKER_APP_APPLICATION_COMMON]);
});
});
}
@@ -217,7 +217,9 @@ SpySocketWrapper createSocket({Function messageHandler}) {
var socket = new SpyWebSocket();
if (messageHandler != null) {
socket.spy("add").andCallFake(messageHandler);
socket.spy("addStream").andCallFake((Stream stream) => stream.listen(messageHandler));
socket
.spy("addStream")
.andCallFake((Stream stream) => stream.listen(messageHandler));
}
var controller = new StreamController<String>.broadcast();
@@ -1,9 +1,18 @@
import {StringMapWrapper, ListWrapper} from 'angular2/src/facade/collection';
import {PromiseWrapper} from 'angular2/src/facade/async';
import {UiArguments} from 'angular2/src/web_workers/shared/client_message_broker';
import {Type, isPresent} from 'angular2/src/facade/lang';
import {SpyMessageBroker} from '../worker/spies';
import {expect} from 'angular2/testing_internal';
import {
MessageBusSink,
MessageBusSource,
MessageBus
} from 'angular2/src/web_workers/shared/message_bus';
import {
ClientMessageBroker,
ClientMessageBrokerFactory_
} from 'angular2/src/web_workers/shared/client_message_broker';
import {MockEventEmitter} from './mock_event_emitter';
import {BaseException, WrappedException} from 'angular2/src/facade/exceptions';
import {NgZone} from 'angular2/src/core/zone/ng_zone';
@@ -25,6 +34,37 @@ export function createPairedMessageBuses(): PairedMessageBuses {
new MockMessageBus(workerMessageBusSink, workerMessageBusSource));
}
/**
* Spies on the given {@link SpyMessageBroker} and expects a call with the given methodName
* andvalues.
* If a handler is provided it will be called to handle the request.
* Only intended to be called on a given broker instance once.
*/
export function expectBrokerCall(broker: SpyMessageBroker, methodName: string, vals?: Array<any>,
handler?: (..._: any[]) => Promise<any>| void): void {
broker.spy("runOnService")
.andCallFake((args: UiArguments, returnType: Type) => {
expect(args.method).toEqual(methodName);
if (isPresent(vals)) {
expect(args.args.length).toEqual(vals.length);
ListWrapper.forEachWithIndex(vals, (v, i) => {expect(v).toEqual(args.args[i].value)});
}
var promise = null;
if (isPresent(handler)) {
let givenValues = args.args.map((arg) => {arg.value});
if (givenValues.length > 0) {
promise = handler(givenValues);
} else {
promise = handler();
}
}
if (promise == null) {
promise = PromiseWrapper.wrap(() => {});
}
return promise;
});
}
export class PairedMessageBuses {
constructor(public ui: MessageBus, public worker: MessageBus) {}
}
@@ -85,3 +125,8 @@ export class MockMessageBus extends MessageBus {
attachToZone(zone: NgZone) {}
}
export class MockMessageBrokerFactory extends ClientMessageBrokerFactory_ {
constructor(private _messageBroker: ClientMessageBroker) { super(null, null); }
createMessageBroker(channel: string, runInZone = true) { return this._messageBroker; }
}
@@ -0,0 +1,97 @@
import {
AsyncTestCompleter,
inject,
describe,
it,
expect,
beforeEach,
beforeEachProviders
} from 'angular2/testing_internal';
import {SpyMessageBroker} from './spies';
import {WebWorkerPlatformLocation} from 'angular2/src/web_workers/worker/platform_location';
import {LocationType} from 'angular2/src/web_workers/shared/serialized_types';
import {MessageBus} from 'angular2/src/web_workers/shared/message_bus';
import {
createPairedMessageBuses,
MockMessageBrokerFactory,
expectBrokerCall
} from '../shared/web_worker_test_util';
import {UiArguments} from 'angular2/src/web_workers/shared/client_message_broker';
import {Type} from 'angular2/src/facade/lang';
import {PromiseWrapper} from "angular2/src/facade/async";
import {CONST_EXPR} from 'angular2/src/facade/lang';
export function main() {
describe("WebWorkerPlatformLocation", () => {
var uiBus: MessageBus = null;
var workerBus: MessageBus = null;
var broker: any = null;
var TEST_LOCATION =
new LocationType("http://www.example.com", "http", "example.com", "example.com", "80", "/",
"", "", "http://www.example.com");
function createWebWorkerPlatformLocation(loc: LocationType): WebWorkerPlatformLocation {
broker.spy("runOnService")
.andCallFake((args: UiArguments, returnType: Type) => {
if (args.method === 'getLocation') {
return PromiseWrapper.resolve(loc);
}
});
var factory = new MockMessageBrokerFactory(broker);
return new WebWorkerPlatformLocation(factory, workerBus, null);
}
function testPushOrReplaceState(pushState: boolean) {
let platformLocation = createWebWorkerPlatformLocation(null);
const TITLE = "foo";
const URL = "http://www.example.com/foo";
expectBrokerCall(broker, pushState ? "pushState" : "replaceState", [null, TITLE, URL]);
if (pushState) {
platformLocation.pushState(null, TITLE, URL);
} else {
platformLocation.replaceState(null, TITLE, URL);
}
}
beforeEach(() => {
var buses = createPairedMessageBuses();
uiBus = buses.ui;
workerBus = buses.worker;
workerBus.initChannel("ng-Router");
uiBus.initChannel("ng-Router");
broker = new SpyMessageBroker();
});
it("should throw if getBaseHrefFromDOM is called", () => {
let platformLocation = createWebWorkerPlatformLocation(null);
expect(() => platformLocation.getBaseHrefFromDOM()).toThrowError();
});
it("should get location on init", () => {
let platformLocation = createWebWorkerPlatformLocation(null);
expectBrokerCall(broker, "getLocation");
platformLocation.init();
});
it("should throw if set pathname is called before init finishes", () => {
let platformLocation = createWebWorkerPlatformLocation(null);
platformLocation.init();
expect(() => platformLocation.pathname = "TEST").toThrowError();
});
it("should send pathname to render thread", inject([AsyncTestCompleter], (async) => {
let platformLocation = createWebWorkerPlatformLocation(TEST_LOCATION);
platformLocation.init().then((_) => {
let PATHNAME = "/test";
expectBrokerCall(broker, "setPathname", [PATHNAME]);
platformLocation.pathname = PATHNAME;
async.done();
});
}));
it("should send pushState to render thread", () => { testPushOrReplaceState(true); });
it("should send replaceState to render thread", () => { testPushOrReplaceState(false); });
});
}
@@ -8,15 +8,9 @@ import {
beforeEachProviders
} from 'angular2/testing_internal';
import {SpyMessageBroker} from './spies';
import {Type} from 'angular2/src/facade/lang';
import {
ClientMessageBroker,
UiArguments,
ClientMessageBrokerFactory,
ClientMessageBrokerFactory_
} from 'angular2/src/web_workers/shared/client_message_broker';
import {WebWorkerXHRImpl} from "angular2/src/web_workers/worker/xhr_impl";
import {PromiseWrapper} from "angular2/src/facade/async";
import {MockMessageBrokerFactory, expectBrokerCall} from "../shared/web_worker_test_util";
export function main() {
describe("WebWorkerXHRImpl", () => {
@@ -25,16 +19,10 @@ export function main() {
const URL = "http://www.example.com/test";
const RESPONSE = "Example response text";
var messageBroker: any = new SpyMessageBroker();
messageBroker.spy("runOnService")
.andCallFake((args: UiArguments, returnType: Type) => {
expect(args.method).toEqual("get");
expect(args.args.length).toEqual(1);
expect(args.args[0].value).toEqual(URL);
return PromiseWrapper.wrap(() => { return RESPONSE; });
});
var xhrImpl = new WebWorkerXHRImpl(new MockMessageBrokerFactory(messageBroker));
var messageBroker = new SpyMessageBroker();
expectBrokerCall(messageBroker, "get", [URL],
(_) => { return PromiseWrapper.wrap(() => { return RESPONSE; }); });
var xhrImpl = new WebWorkerXHRImpl(new MockMessageBrokerFactory(<any>messageBroker));
xhrImpl.get(URL).then((response) => {
expect(response).toEqual(RESPONSE);
async.done();
@@ -42,8 +30,3 @@ export function main() {
}));
});
}
class MockMessageBrokerFactory extends ClientMessageBrokerFactory_ {
constructor(private _messageBroker: ClientMessageBroker) { super(null, null); }
createMessageBroker(channel: string, runInZone = true) { return this._messageBroker; }
}