fix(testing): let DOM adapter dictate XHR implementation for tests
The test injector now uses an XHR implementation based on DOM.getXHR, which allows the current DOM adapter to dictate which XHR impl should be used. To prevent the changes to DOM adapter from introducing undesired new dependencies into the benchmarks, separate the async facade into a promise facade which is reexported by facade/async. See #4539
This commit is contained in:
parent
65c737fc95
commit
d7ab5d44a5
|
@ -1,9 +1,7 @@
|
|||
import {Injectable} from 'angular2/src/core/di';
|
||||
import {Promise, PromiseWrapper, PromiseCompleter} from 'angular2/src/core/facade/async';
|
||||
import {Promise, PromiseWrapper, PromiseCompleter} from 'angular2/src/core/facade/promise';
|
||||
import {isPresent} from 'angular2/src/core/facade/lang';
|
||||
import {XHR} from './xhr';
|
||||
|
||||
@Injectable()
|
||||
export class XHRImpl extends XHR {
|
||||
get(url: string): Promise<string> {
|
||||
var completer: PromiseCompleter < string >= PromiseWrapper.completer();
|
||||
|
|
|
@ -5,6 +5,7 @@ import 'package:html/dom.dart';
|
|||
|
||||
import 'dom_adapter.dart';
|
||||
import 'emulated_css.dart';
|
||||
import '../compiler/xhr.dart';
|
||||
|
||||
const _attrToPropMap = const {
|
||||
'innerHtml': 'innerHTML',
|
||||
|
@ -66,6 +67,9 @@ abstract class AbstractHtml5LibAdapter implements DomAdapter {
|
|||
throw 'not implemented';
|
||||
}
|
||||
|
||||
@override
|
||||
Type getXHR() => XHR;
|
||||
|
||||
Element parse(String templateHtml) => parser.parse(templateHtml).firstChild;
|
||||
query(selector) {
|
||||
throw 'not implemented';
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import {isBlank} from 'angular2/src/core/facade/lang';
|
||||
import {isBlank, Type} from 'angular2/src/core/facade/lang';
|
||||
|
||||
export var DOM: DomAdapter;
|
||||
|
||||
|
@ -23,6 +23,8 @@ export abstract class DomAdapter {
|
|||
abstract logGroup(error);
|
||||
abstract logGroupEnd();
|
||||
|
||||
abstract getXHR(): Type;
|
||||
|
||||
/**
|
||||
* Maps attribute names to their corresponding property names for cases
|
||||
* where attribute name doesn't match property name.
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
import {ListWrapper, StringMapWrapper} from 'angular2/src/core/facade/collection';
|
||||
import {isPresent, isFunction, StringWrapper} from 'angular2/src/core/facade/lang';
|
||||
import {isPresent, isFunction, StringWrapper, Type} from 'angular2/src/core/facade/lang';
|
||||
import {DomAdapter} from './dom_adapter';
|
||||
import {XHRImpl} from 'angular2/src/core/compiler/xhr_impl';
|
||||
|
||||
|
||||
/**
|
||||
* Provides DOM operations in any browser environment.
|
||||
|
@ -39,6 +41,8 @@ export abstract class GenericBrowserDomAdapter extends DomAdapter {
|
|||
this._transitionEnd = null;
|
||||
}
|
||||
}
|
||||
|
||||
getXHR(): Type { return XHRImpl; }
|
||||
getDistributedNodes(el: HTMLElement): Node[] { return (<any>el).getDistributedNodes(); }
|
||||
resolveAndSetHref(el: HTMLAnchorElement, baseUrl: string, href: string) {
|
||||
el.href = href == null ? baseUrl : baseUrl + '/../' + href;
|
||||
|
|
|
@ -11,11 +11,13 @@ import {
|
|||
isPresent,
|
||||
isBlank,
|
||||
global,
|
||||
Type,
|
||||
setValueOnPath,
|
||||
DateWrapper
|
||||
} from 'angular2/src/core/facade/lang';
|
||||
import {BaseException, WrappedException} from 'angular2/src/core/facade/exceptions';
|
||||
import {SelectorMatcher, CssSelector} from 'angular2/src/core/compiler/selector';
|
||||
import {XHR} from 'angular2/src/core/compiler/xhr';
|
||||
|
||||
var _attrToPropMap: {[key: string]: string} = {
|
||||
'class': 'className',
|
||||
|
@ -61,6 +63,8 @@ export class Parse5DomAdapter extends DomAdapter {
|
|||
|
||||
logGroupEnd() {}
|
||||
|
||||
getXHR(): Type { return XHR; }
|
||||
|
||||
get attrToPropMap() { return _attrToPropMap; }
|
||||
|
||||
query(selector) { throw _notImplemented('query'); }
|
||||
|
|
|
@ -1,37 +1,9 @@
|
|||
library angular2.core.facade.async;
|
||||
|
||||
import 'dart:async';
|
||||
export 'dart:async' show Future, Stream, StreamController, StreamSubscription;
|
||||
export 'dart:async' show Stream, StreamController, StreamSubscription;
|
||||
|
||||
class PromiseWrapper {
|
||||
static Future resolve(obj) => new Future.value(obj);
|
||||
|
||||
static Future reject(obj, stackTrace) => new Future.error(obj,
|
||||
stackTrace != null ? stackTrace : obj is Error ? obj.stackTrace : null);
|
||||
|
||||
static Future<List> all(List<dynamic> promises) {
|
||||
return Future
|
||||
.wait(promises.map((p) => p is Future ? p : new Future.value(p)));
|
||||
}
|
||||
|
||||
static Future then(Future promise, success(value), [Function onError]) {
|
||||
if (success == null) return promise.catchError(onError);
|
||||
return promise.then(success, onError: onError);
|
||||
}
|
||||
|
||||
static Future wrap(Function fn) {
|
||||
return new Future(fn);
|
||||
}
|
||||
|
||||
// Note: We can't rename this method to `catch`, as this is not a valid
|
||||
// method name in Dart.
|
||||
static Future catchError(Future promise, Function onError) {
|
||||
return promise.catchError(onError);
|
||||
}
|
||||
|
||||
static PromiseCompleter<dynamic> completer() =>
|
||||
new PromiseCompleter(new Completer());
|
||||
}
|
||||
export 'promise.dart';
|
||||
|
||||
class TimerWrapper {
|
||||
static Timer setTimeout(fn(), int millis) =>
|
||||
|
@ -105,22 +77,3 @@ class EventEmitter extends Stream {
|
|||
_controller.close();
|
||||
}
|
||||
}
|
||||
|
||||
class PromiseCompleter<T> {
|
||||
final Completer<T> c;
|
||||
|
||||
PromiseCompleter(this.c);
|
||||
|
||||
Future get promise => c.future;
|
||||
|
||||
void resolve(v) {
|
||||
c.complete(v);
|
||||
}
|
||||
|
||||
void reject(error, stack) {
|
||||
if (stack == null && error is Error) {
|
||||
stack = error.stackTrace;
|
||||
}
|
||||
c.completeError(error, stack);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,60 +1,11 @@
|
|||
import {global, isPresent} from 'angular2/src/core/facade/lang';
|
||||
// We make sure promises are in a separate file so that we can use promises
|
||||
// without depending on rxjs.
|
||||
import {PromiseWrapper, Promise, PromiseCompleter} from 'angular2/src/core/facade/promise';
|
||||
export {PromiseWrapper, Promise, PromiseCompleter} from 'angular2/src/core/facade/promise';
|
||||
// TODO(jeffbcross): use ES6 import once typings are available
|
||||
var Subject = require('@reactivex/rxjs/dist/cjs/Subject');
|
||||
|
||||
export {Promise};
|
||||
|
||||
export interface PromiseCompleter<R> {
|
||||
promise: Promise<R>;
|
||||
resolve: (value?: R | PromiseLike<R>) => void;
|
||||
reject: (error?: any, stackTrace?: string) => void;
|
||||
}
|
||||
|
||||
export class PromiseWrapper {
|
||||
static resolve<T>(obj: T): Promise<T> { return Promise.resolve(obj); }
|
||||
|
||||
static reject(obj: any, _): Promise<any> { return Promise.reject(obj); }
|
||||
|
||||
// Note: We can't rename this method into `catch`, as this is not a valid
|
||||
// method name in Dart.
|
||||
static catchError<T>(promise: Promise<T>,
|
||||
onError: (error: any) => T | PromiseLike<T>): Promise<T> {
|
||||
return promise.catch(onError);
|
||||
}
|
||||
|
||||
static all(promises: any[]): Promise<any> {
|
||||
if (promises.length == 0) return Promise.resolve([]);
|
||||
return Promise.all(promises);
|
||||
}
|
||||
|
||||
static then<T, U>(promise: Promise<T>, success: (value: T) => U | PromiseLike<U>,
|
||||
rejection?: (error: any, stack?: any) => U | PromiseLike<U>): Promise<U> {
|
||||
return promise.then(success, rejection);
|
||||
}
|
||||
|
||||
static wrap<T>(computation: () => T): Promise<T> {
|
||||
return new Promise((res, rej) => {
|
||||
try {
|
||||
res(computation());
|
||||
} catch (e) {
|
||||
rej(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
static completer(): PromiseCompleter<any> {
|
||||
var resolve;
|
||||
var reject;
|
||||
|
||||
var p = new Promise(function(res, rej) {
|
||||
resolve = res;
|
||||
reject = rej;
|
||||
});
|
||||
|
||||
return {promise: p, resolve: resolve, reject: reject};
|
||||
}
|
||||
}
|
||||
|
||||
export namespace NodeJS {
|
||||
export interface Timer {}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,53 @@
|
|||
library angular2.core.facade.promise;
|
||||
|
||||
import 'dart:async';
|
||||
export 'dart:async' show Future;
|
||||
|
||||
class PromiseWrapper {
|
||||
static Future resolve(obj) => new Future.value(obj);
|
||||
|
||||
static Future reject(obj, stackTrace) => new Future.error(obj,
|
||||
stackTrace != null ? stackTrace : obj is Error ? obj.stackTrace : null);
|
||||
|
||||
static Future<List> all(List<dynamic> promises) {
|
||||
return Future
|
||||
.wait(promises.map((p) => p is Future ? p : new Future.value(p)));
|
||||
}
|
||||
|
||||
static Future then(Future promise, success(value), [Function onError]) {
|
||||
if (success == null) return promise.catchError(onError);
|
||||
return promise.then(success, onError: onError);
|
||||
}
|
||||
|
||||
static Future wrap(Function fn) {
|
||||
return new Future(fn);
|
||||
}
|
||||
|
||||
// Note: We can't rename this method to `catch`, as this is not a valid
|
||||
// method name in Dart.
|
||||
static Future catchError(Future promise, Function onError) {
|
||||
return promise.catchError(onError);
|
||||
}
|
||||
|
||||
static PromiseCompleter<dynamic> completer() =>
|
||||
new PromiseCompleter(new Completer());
|
||||
}
|
||||
|
||||
class PromiseCompleter<T> {
|
||||
final Completer<T> c;
|
||||
|
||||
PromiseCompleter(this.c);
|
||||
|
||||
Future get promise => c.future;
|
||||
|
||||
void resolve(v) {
|
||||
c.complete(v);
|
||||
}
|
||||
|
||||
void reject(error, stack) {
|
||||
if (stack == null && error is Error) {
|
||||
stack = error.stackTrace;
|
||||
}
|
||||
c.completeError(error, stack);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
// Promises are put into their own facade file so that they can be used without
|
||||
// introducing a dependency on rxjs. They are re-exported through facade/async.
|
||||
export {Promise};
|
||||
|
||||
export interface PromiseCompleter<R> {
|
||||
promise: Promise<R>;
|
||||
resolve: (value?: R | PromiseLike<R>) => void;
|
||||
reject: (error?: any, stackTrace?: string) => void;
|
||||
}
|
||||
|
||||
export class PromiseWrapper {
|
||||
static resolve<T>(obj: T): Promise<T> { return Promise.resolve(obj); }
|
||||
|
||||
static reject(obj: any, _): Promise<any> { return Promise.reject(obj); }
|
||||
|
||||
// Note: We can't rename this method into `catch`, as this is not a valid
|
||||
// method name in Dart.
|
||||
static catchError<T>(promise: Promise<T>,
|
||||
onError: (error: any) => T | PromiseLike<T>): Promise<T> {
|
||||
return promise.catch(onError);
|
||||
}
|
||||
|
||||
static all(promises: any[]): Promise<any> {
|
||||
if (promises.length == 0) return Promise.resolve([]);
|
||||
return Promise.all(promises);
|
||||
}
|
||||
|
||||
static then<T, U>(promise: Promise<T>, success: (value: T) => U | PromiseLike<U>,
|
||||
rejection?: (error: any, stack?: any) => U | PromiseLike<U>): Promise<U> {
|
||||
return promise.then(success, rejection);
|
||||
}
|
||||
|
||||
static wrap<T>(computation: () => T): Promise<T> {
|
||||
return new Promise((res, rej) => {
|
||||
try {
|
||||
res(computation());
|
||||
} catch (e) {
|
||||
rej(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
static completer(): PromiseCompleter<any> {
|
||||
var resolve;
|
||||
var reject;
|
||||
|
||||
var p = new Promise(function(res, rej) {
|
||||
resolve = res;
|
||||
reject = rej;
|
||||
});
|
||||
|
||||
return {promise: p, resolve: resolve, reject: reject};
|
||||
}
|
||||
}
|
|
@ -115,7 +115,7 @@ function _getAppBindings() {
|
|||
PipeResolver,
|
||||
provide(ExceptionHandler, {useValue: new ExceptionHandler(DOM)}),
|
||||
provide(LocationStrategy, {useClass: MockLocationStrategy}),
|
||||
XHR,
|
||||
provide(XHR, {useClass: DOM.getXHR()}),
|
||||
TestComponentBuilder,
|
||||
provide(NgZone, {useClass: MockNgZone}),
|
||||
provide(AnimationBuilder, {useClass: MockAnimationBuilder}),
|
||||
|
|
|
@ -16,6 +16,8 @@ import {
|
|||
|
||||
import {Injectable, NgIf, bind} from 'angular2/core';
|
||||
import {Directive, Component, View, ViewMetadata} from 'angular2/angular2';
|
||||
import {XHR} from 'angular2/src/core/compiler/xhr';
|
||||
import {XHRImpl} from 'angular2/src/core/compiler/xhr_impl';
|
||||
|
||||
// Services, and components for the tests.
|
||||
|
||||
|
@ -118,6 +120,9 @@ export function main() {
|
|||
}, 0);
|
||||
});
|
||||
|
||||
it('provides a real XHR instance',
|
||||
inject([XHR], (xhr) => { expect(xhr).toBeAnInstanceOf(XHRImpl); }));
|
||||
|
||||
describe('setting up Providers', () => {
|
||||
beforeEachProviders(() => [bind(FancyService).toValue(new FancyService())]);
|
||||
|
||||
|
|
|
@ -20,9 +20,6 @@ import {MdButton, MdAnchor} from 'angular2_material/src/components/button/button
|
|||
|
||||
import {TestUrlResolver} from './test_url_resolver';
|
||||
|
||||
import {XHR} from 'angular2/src/core/compiler/xhr';
|
||||
import {XHRImpl} from 'angular2/src/core/compiler/xhr_impl';
|
||||
|
||||
|
||||
export function main() {
|
||||
describe('MdButton', () => {
|
||||
|
@ -33,11 +30,6 @@ export function main() {
|
|||
// with both JS and Dart output.
|
||||
bind(UrlResolver)
|
||||
.toValue(new TestUrlResolver()),
|
||||
|
||||
// Need to use the real XHR implementation (instead of the mock) so we can actually request
|
||||
// the template files, since Angular 2 doesn't have anything like $templateCache. This should
|
||||
// eventually be replaced with a preprocessor that inlines templates.
|
||||
provide(XHR, {useClass: XHRImpl})
|
||||
]);
|
||||
|
||||
beforeEach(inject([TestComponentBuilder], (tcb) => { builder = tcb; }));
|
||||
|
|
Loading…
Reference in New Issue