build(aio): switch from `@angular/http` to `@angular/common/http`

```
$ ls -l dist/*.js

 14942            dist/0.b19e913fbdd6507d346b.chunk.js
  1535            dist/inline.a1b446562b36eebb766d.bundle.js
524385  (+  682)  dist/main.19fec4390ff7837ee6ef.bundle.js
 37402            dist/polyfills.9f7e0e53bce2a6c8326e.bundle.js
 54001            dist/worker-basic.min.js

632265  (+  682)  total
```
This commit is contained in:
Georgios Kalpakas 2017-08-11 20:16:55 +03:00 committed by Hans
parent 3efd4a15d6
commit 38addacda0
20 changed files with 279 additions and 398 deletions

View File

@ -2,7 +2,7 @@ import { NO_ERRORS_SCHEMA, DebugElement } from '@angular/core';
import { async, inject, ComponentFixture, TestBed, fakeAsync, tick } from '@angular/core/testing'; import { async, inject, ComponentFixture, TestBed, fakeAsync, tick } from '@angular/core/testing';
import { Title } from '@angular/platform-browser'; import { Title } from '@angular/platform-browser';
import { APP_BASE_HREF } from '@angular/common'; import { APP_BASE_HREF } from '@angular/common';
import { Http } from '@angular/http'; import { HttpClient } from '@angular/common/http';
import { MdProgressBar, MdSidenav } from '@angular/material'; import { MdProgressBar, MdSidenav } from '@angular/material';
import { By } from '@angular/platform-browser'; import { By } from '@angular/platform-browser';
@ -650,7 +650,7 @@ describe('AppComponent', () => {
describe('footer', () => { describe('footer', () => {
it('should have version number', () => { it('should have version number', () => {
const versionEl: HTMLElement = fixture.debugElement.query(By.css('aio-footer')).nativeElement; const versionEl: HTMLElement = fixture.debugElement.query(By.css('aio-footer')).nativeElement;
expect(versionEl.textContent).toContain(TestHttp.versionInfo.full); expect(versionEl.textContent).toContain(TestHttpClient.versionInfo.full);
}); });
}); });
@ -1027,7 +1027,7 @@ function createTestingModule(initialUrl: string, mode: string = 'stable') {
providers: [ providers: [
{ provide: APP_BASE_HREF, useValue: '/' }, { provide: APP_BASE_HREF, useValue: '/' },
{ provide: GaService, useClass: TestGaService }, { provide: GaService, useClass: TestGaService },
{ provide: Http, useClass: TestHttp }, { provide: HttpClient, useClass: TestHttpClient },
{ provide: LocationService, useFactory: () => mockLocationService }, { provide: LocationService, useFactory: () => mockLocationService },
{ provide: Logger, useClass: MockLogger }, { provide: Logger, useClass: MockLogger },
{ provide: SearchService, useClass: MockSearchService }, { provide: SearchService, useClass: MockSearchService },
@ -1049,7 +1049,7 @@ class TestSearchService {
loadIndex = jasmine.createSpy('loadIndex'); loadIndex = jasmine.createSpy('loadIndex');
} }
class TestHttp { class TestHttpClient {
static versionInfo = { static versionInfo = {
raw: '4.0.0-rc.6', raw: '4.0.0-rc.6',
@ -1105,9 +1105,9 @@ class TestHttp {
"tooltip": "Details of the Angular classes and values." "tooltip": "Details of the Angular classes and values."
} }
], ],
"docVersions": TestHttp.docVersions, "docVersions": TestHttpClient.docVersions,
"__versionInfo": TestHttp.versionInfo, "__versionInfo": TestHttpClient.versionInfo,
}; };
get(url: string) { get(url: string) {
@ -1123,6 +1123,6 @@ class TestHttp {
const contents = `${h1}<h2 id="#somewhere">Some heading</h2>`; const contents = `${h1}<h2 id="#somewhere">Some heading</h2>`;
data = { id, contents }; data = { id, contents };
} }
return of({ json: () => data }); return of(data);
} }
} }

View File

@ -1,6 +1,6 @@
import { BrowserModule } from '@angular/platform-browser'; import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core'; import { NgModule } from '@angular/core';
import { HttpModule } from '@angular/http'; import { HttpClientModule } from '@angular/common/http';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { Location, LocationStrategy, PathLocationStrategy } from '@angular/common'; import { Location, LocationStrategy, PathLocationStrategy } from '@angular/common';
@ -75,7 +75,7 @@ export const svgIconProviders = [
imports: [ imports: [
BrowserModule, BrowserModule,
EmbeddedModule, EmbeddedModule,
HttpModule, HttpClientModule,
BrowserAnimationsModule, BrowserAnimationsModule,
MdButtonModule, MdButtonModule,
MdIconModule, MdIconModule,

View File

@ -1,11 +1,11 @@
import { ReflectiveInjector } from '@angular/core'; import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing';
import { Http, ConnectionBackend, RequestOptions, BaseRequestOptions, Response, ResponseOptions } from '@angular/http'; import { Injector } from '@angular/core';
import { TestBed } from '@angular/core/testing';
import { Observable } from 'rxjs/Observable'; import { Observable } from 'rxjs/Observable';
import { Subscription } from 'rxjs/Subscription'; import { Subscription } from 'rxjs/Subscription';
import { BehaviorSubject } from 'rxjs/BehaviorSubject'; import { BehaviorSubject } from 'rxjs/BehaviorSubject';
import { MockBackend } from '@angular/http/testing';
import { LocationService } from 'app/shared/location.service'; import { LocationService } from 'app/shared/location.service';
import { MockLocationService } from 'testing/location.service'; import { MockLocationService } from 'testing/location.service';
import { Logger } from 'app/shared/logger.service'; import { Logger } from 'app/shared/logger.service';
@ -16,113 +16,123 @@ import { DocumentService, DocumentContents,
const CONTENT_URL_PREFIX = 'generated/docs/'; const CONTENT_URL_PREFIX = 'generated/docs/';
function createResponse(body: any) {
return new Response(new ResponseOptions({ body: JSON.stringify(body) }));
}
function createInjector(initialUrl: string) {
return ReflectiveInjector.resolveAndCreate([
DocumentService,
{ provide: LocationService, useFactory: () => new MockLocationService(initialUrl) },
{ provide: ConnectionBackend, useClass: MockBackend },
{ provide: RequestOptions, useClass: BaseRequestOptions },
{ provide: Logger, useClass: MockLogger },
Http,
]);
}
function getServices(initialUrl: string = '') {
const injector = createInjector(initialUrl);
return {
backend: injector.get(ConnectionBackend) as MockBackend,
locationService: injector.get(LocationService) as MockLocationService,
docService: injector.get(DocumentService) as DocumentService,
logger: injector.get(Logger) as MockLogger
};
}
describe('DocumentService', () => { describe('DocumentService', () => {
it('should be creatable', () => { let httpMock: HttpTestingController;
const { docService } = getServices();
expect(docService).toBeTruthy(); function createInjector(initialUrl: string) {
}); return TestBed.configureTestingModule({
imports: [HttpClientTestingModule],
providers: [
DocumentService,
{ provide: LocationService, useFactory: () => new MockLocationService(initialUrl) },
{ provide: Logger, useClass: MockLogger },
]
});
}
function getServices(initialUrl: string = '') {
const injector = createInjector(initialUrl);
httpMock = injector.get(HttpTestingController) as HttpTestingController;
return {
locationService: injector.get(LocationService) as MockLocationService,
docService: injector.get(DocumentService) as DocumentService,
logger: injector.get(Logger) as MockLogger
};
}
afterEach(() => httpMock.verify());
describe('currentDocument', () => { describe('currentDocument', () => {
it('should fetch a document for the initial location', () => { it('should fetch a document for the initial location', () => {
const { docService, backend } = getServices('initial/doc'); const { docService } = getServices('initial/doc');
const connections = backend.connectionsArray;
docService.currentDocument.subscribe(); docService.currentDocument.subscribe();
expect(connections.length).toEqual(1); httpMock.expectOne(CONTENT_URL_PREFIX + 'initial/doc.json');
expect(connections[0].request.url).toEqual(CONTENT_URL_PREFIX + 'initial/doc.json');
expect(backend.connectionsArray[0].request.url).toEqual(CONTENT_URL_PREFIX + 'initial/doc.json');
}); });
it('should emit a document each time the location changes', () => { it('should emit a document each time the location changes', () => {
let latestDocument: DocumentContents; let latestDocument: DocumentContents;
const doc0 = { contents: 'doc 0', id: 'initial/doc' }; const doc0 = { contents: 'doc 0', id: 'initial/doc' };
const doc1 = { contents: 'doc 1', id: 'new/doc' }; const doc1 = { contents: 'doc 1', id: 'new/doc' };
const { docService, backend, locationService } = getServices('initial/doc'); const { docService, locationService } = getServices('initial/doc');
const connections = backend.connectionsArray;
docService.currentDocument.subscribe(doc => latestDocument = doc); docService.currentDocument.subscribe(doc => latestDocument = doc);
expect(latestDocument).toBeUndefined(); expect(latestDocument).toBeUndefined();
connections[0].mockRespond(createResponse(doc0)); httpMock.expectOne({}).flush(doc0);
expect(latestDocument).toEqual(doc0); expect(latestDocument).toEqual(doc0);
locationService.go('new/doc'); locationService.go('new/doc');
connections[1].mockRespond(createResponse(doc1)); httpMock.expectOne({}).flush(doc1);
expect(latestDocument).toEqual(doc1); expect(latestDocument).toEqual(doc1);
}); });
it('should emit the not-found document if the document is not found on the server', () => { it('should emit the not-found document if the document is not found on the server', () => {
const { docService, backend } = getServices('missing/doc');
const connections = backend.connectionsArray;
let currentDocument: DocumentContents; let currentDocument: DocumentContents;
const notFoundDoc = { id: FILE_NOT_FOUND_ID, contents: '<h1>Page Not Found</h1>' };
const { docService } = getServices('missing/doc');
docService.currentDocument.subscribe(doc => currentDocument = doc); docService.currentDocument.subscribe(doc => currentDocument = doc);
connections[0].mockError(new Response(new ResponseOptions({ status: 404, statusText: 'NOT FOUND'})) as any); // Initial request return 404.
expect(connections.length).toEqual(2); httpMock.expectOne({}).flush(null, {status: 404, statusText: 'NOT FOUND'});
expect(connections[1].request.url).toEqual(CONTENT_URL_PREFIX + 'file-not-found.json');
const fileNotFoundDoc = { id: FILE_NOT_FOUND_ID, contents: '<h1>Page Not Found</h1>' }; // Subsequent request for not-found document.
connections[1].mockRespond(createResponse(fileNotFoundDoc)); httpMock.expectOne(CONTENT_URL_PREFIX + 'file-not-found.json').flush(notFoundDoc);
expect(currentDocument).toEqual(fileNotFoundDoc);
expect(currentDocument).toEqual(notFoundDoc);
}); });
it('should emit a hard-coded not-found document if the not-found document is not found on the server', () => { it('should emit a hard-coded not-found document if the not-found document is not found on the server', () => {
let currentDocument: DocumentContents; let currentDocument: DocumentContents;
const notFoundDoc: DocumentContents = { contents: 'Document not found', id: FILE_NOT_FOUND_ID }; const hardCodedNotFoundDoc = { contents: 'Document not found', id: FILE_NOT_FOUND_ID };
const nextDoc = { contents: 'Next Doc', id: 'new/doc' }; const nextDoc = { contents: 'Next Doc', id: 'new/doc' };
const { docService, backend, locationService } = getServices(FILE_NOT_FOUND_ID); const { docService, locationService } = getServices(FILE_NOT_FOUND_ID);
const connections = backend.connectionsArray;
docService.currentDocument.subscribe(doc => currentDocument = doc); docService.currentDocument.subscribe(doc => currentDocument = doc);
connections[0].mockError(new Response(new ResponseOptions({ status: 404, statusText: 'NOT FOUND'})) as any); httpMock.expectOne({}).flush(null, { status: 404, statusText: 'NOT FOUND'});
expect(connections.length).toEqual(1); expect(currentDocument).toEqual(hardCodedNotFoundDoc);
expect(currentDocument).toEqual(notFoundDoc);
// now check that we haven't killed the currentDocument observable sequence // now check that we haven't killed the currentDocument observable sequence
locationService.go('new/doc'); locationService.go('new/doc');
connections[1].mockRespond(createResponse(nextDoc)); httpMock.expectOne({}).flush(nextDoc);
expect(currentDocument).toEqual(nextDoc); expect(currentDocument).toEqual(nextDoc);
}); });
it('should use a hard-coded error doc if the request fails (but not cache it)', () => {
let latestDocument: DocumentContents;
const doc1 = { contents: 'doc 1' };
const doc2 = { contents: 'doc 2' };
const { docService, locationService } = getServices('initial/doc');
docService.currentDocument.subscribe(doc => latestDocument = doc);
httpMock.expectOne({}).flush(null, {status: 500, statusText: 'Server Error'});
expect(latestDocument.id).toEqual(FETCHING_ERROR_ID);
locationService.go('new/doc');
httpMock.expectOne({}).flush(doc1);
expect(latestDocument).toEqual(jasmine.objectContaining(doc1));
locationService.go('initial/doc');
httpMock.expectOne({}).flush(doc2);
expect(latestDocument).toEqual(jasmine.objectContaining(doc2));
});
it('should not crash the app if the response is invalid JSON', () => { it('should not crash the app if the response is invalid JSON', () => {
let latestDocument: DocumentContents; let latestDocument: DocumentContents;
const { docService, backend, locationService} = getServices('initial/doc'); const doc1 = { contents: 'doc 1' };
const connections = backend.connectionsArray; const { docService, locationService } = getServices('initial/doc');
docService.currentDocument.subscribe(doc => latestDocument = doc); docService.currentDocument.subscribe(doc => latestDocument = doc);
connections[0].mockRespond(new Response(new ResponseOptions({ body: 'this is invalid JSON' }))); httpMock.expectOne({}).flush('this is invalid JSON');
expect(latestDocument.id).toEqual(FETCHING_ERROR_ID); expect(latestDocument.id).toEqual(FETCHING_ERROR_ID);
const doc1 = { contents: 'doc 1' };
locationService.go('new/doc'); locationService.go('new/doc');
connections[1].mockRespond(createResponse(doc1)); httpMock.expectOne({}).flush(doc1);
expect(latestDocument).toEqual(jasmine.objectContaining(doc1)); expect(latestDocument).toEqual(jasmine.objectContaining(doc1));
}); });
@ -132,37 +142,30 @@ describe('DocumentService', () => {
const doc0 = { contents: 'doc 0' }; const doc0 = { contents: 'doc 0' };
const doc1 = { contents: 'doc 1' }; const doc1 = { contents: 'doc 1' };
const { docService, backend, locationService} = getServices('url/0'); const { docService, locationService } = getServices('url/0');
const connections = backend.connectionsArray;
subscription = docService.currentDocument.subscribe(doc => latestDocument = doc); subscription = docService.currentDocument.subscribe(doc => latestDocument = doc);
expect(connections.length).toEqual(1); httpMock.expectOne({}).flush(doc0);
connections[0].mockRespond(createResponse(doc0));
expect(latestDocument).toEqual(jasmine.objectContaining(doc0)); expect(latestDocument).toEqual(jasmine.objectContaining(doc0));
subscription.unsubscribe(); subscription.unsubscribe();
// modify the response so we can check that future subscriptions do not trigger another request
connections[0].response.next(createResponse({ contents: 'error 0' }));
subscription = docService.currentDocument.subscribe(doc => latestDocument = doc); subscription = docService.currentDocument.subscribe(doc => latestDocument = doc);
locationService.go('url/1'); locationService.go('url/1');
expect(connections.length).toEqual(2); httpMock.expectOne({}).flush(doc1);
connections[1].mockRespond(createResponse(doc1));
expect(latestDocument).toEqual(jasmine.objectContaining(doc1)); expect(latestDocument).toEqual(jasmine.objectContaining(doc1));
subscription.unsubscribe(); subscription.unsubscribe();
// modify the response so we can check that future subscriptions do not trigger another request // This should not trigger a new request.
connections[1].response.next(createResponse({ contents: 'error 1' }));
subscription = docService.currentDocument.subscribe(doc => latestDocument = doc); subscription = docService.currentDocument.subscribe(doc => latestDocument = doc);
locationService.go('url/0'); locationService.go('url/0');
expect(connections.length).toEqual(2); httpMock.expectNone({});
expect(latestDocument).toEqual(jasmine.objectContaining(doc0)); expect(latestDocument).toEqual(jasmine.objectContaining(doc0));
subscription.unsubscribe(); subscription.unsubscribe();
// This should not trigger a new request.
subscription = docService.currentDocument.subscribe(doc => latestDocument = doc); subscription = docService.currentDocument.subscribe(doc => latestDocument = doc);
locationService.go('url/1'); locationService.go('url/1');
expect(connections.length).toEqual(2); httpMock.expectNone({});
expect(latestDocument).toEqual(jasmine.objectContaining(doc1)); expect(latestDocument).toEqual(jasmine.objectContaining(doc1));
subscription.unsubscribe(); subscription.unsubscribe();
}); });
@ -171,17 +174,18 @@ describe('DocumentService', () => {
describe('computeMap', () => { describe('computeMap', () => {
it('should map the "empty" location to the correct document request', () => { it('should map the "empty" location to the correct document request', () => {
let latestDocument: DocumentContents; let latestDocument: DocumentContents;
const { docService, backend } = getServices(); const { docService } = getServices();
docService.currentDocument.subscribe(doc => latestDocument = doc); docService.currentDocument.subscribe(doc => latestDocument = doc);
expect(backend.connectionsArray[0].request.url).toEqual(CONTENT_URL_PREFIX + 'index.json'); httpMock.expectOne(CONTENT_URL_PREFIX + 'index.json');
}); });
it('should map the "folder" locations to the correct document request', () => { it('should map the "folder" locations to the correct document request', () => {
const { docService, backend, locationService} = getServices('guide'); const { docService } = getServices('guide');
docService.currentDocument.subscribe(); docService.currentDocument.subscribe();
expect(backend.connectionsArray[0].request.url).toEqual(CONTENT_URL_PREFIX + 'guide.json'); httpMock.expectOne(CONTENT_URL_PREFIX + 'guide.json');
}); });
}); });
}); });

View File

@ -1,11 +1,10 @@
import { Injectable } from '@angular/core'; import { Injectable } from '@angular/core';
import { Http, Response } from '@angular/http'; import { HttpClient, HttpErrorResponse } from '@angular/common/http';
import { Observable } from 'rxjs/Observable'; import { Observable } from 'rxjs/Observable';
import { AsyncSubject } from 'rxjs/AsyncSubject'; import { AsyncSubject } from 'rxjs/AsyncSubject';
import { of } from 'rxjs/observable/of'; import { of } from 'rxjs/observable/of';
import 'rxjs/add/operator/catch'; import 'rxjs/add/operator/catch';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/switchMap'; import 'rxjs/add/operator/switchMap';
import { DocumentContents } from './document-contents'; import { DocumentContents } from './document-contents';
@ -41,7 +40,7 @@ export class DocumentService {
constructor( constructor(
private logger: Logger, private logger: Logger,
private http: Http, private http: HttpClient,
location: LocationService) { location: LocationService) {
// Whenever the URL changes we try to get the appropriate doc // Whenever the URL changes we try to get the appropriate doc
this.currentDocument = location.currentPath.switchMap(path => this.getDocument(path)); this.currentDocument = location.currentPath.switchMap(path => this.getDocument(path));
@ -58,15 +57,22 @@ export class DocumentService {
private fetchDocument(id: string): Observable<DocumentContents> { private fetchDocument(id: string): Observable<DocumentContents> {
const requestPath = `${DOC_CONTENT_URL_PREFIX}${id}.json`; const requestPath = `${DOC_CONTENT_URL_PREFIX}${id}.json`;
const subject = new AsyncSubject<DocumentContents>();
this.logger.log('fetching document from', requestPath); this.logger.log('fetching document from', requestPath);
const subject = new AsyncSubject();
this.http this.http
.get(requestPath) .get<DocumentContents>(requestPath, {responseType: 'json'})
.map(response => response.json()) .do(data => {
.catch((error: Response) => { if (!data || typeof data !== 'object') {
this.logger.log('received invalid data:', data);
throw Error('Invalid data');
}
})
.catch((error: HttpErrorResponse) => {
return error.status === 404 ? this.getFileNotFoundDoc(id) : this.getErrorDoc(id, error); return error.status === 404 ? this.getFileNotFoundDoc(id) : this.getErrorDoc(id, error);
}) })
.subscribe(subject); .subscribe(subject);
return subject.asObservable(); return subject.asObservable();
} }
@ -83,7 +89,7 @@ export class DocumentService {
} }
} }
private getErrorDoc(id: string, error: Response): Observable<DocumentContents> { private getErrorDoc(id: string, error: HttpErrorResponse): Observable<DocumentContents> {
this.logger.error('Error fetching document', error); this.logger.error('Error fetching document', error);
this.cache.delete(id); this.cache.delete(id);
return Observable.of({ return Observable.of({

View File

@ -26,10 +26,6 @@ describe('ApiListComponent', () => {
sections = getApiSections(); sections = getApiSections();
}); });
it('should be creatable', () => {
expect(component).toBeDefined();
});
/** /**
* Expectation Utility: Assert that filteredSections has the expected result for this test * Expectation Utility: Assert that filteredSections has the expected result for this test
* @param itemTest - return true if the item passes the match test * @param itemTest - return true if the item passes the match test

View File

@ -1,6 +1,6 @@
import { ReflectiveInjector } from '@angular/core'; import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing';
import { Http, ConnectionBackend, RequestOptions, BaseRequestOptions, Response, ResponseOptions } from '@angular/http'; import { Injector } from '@angular/core';
import { MockBackend, MockConnection } from '@angular/http/testing'; import { TestBed, inject } from '@angular/core/testing';
import { Logger } from 'app/shared/logger.service'; import { Logger } from 'app/shared/logger.service';
@ -8,35 +8,27 @@ import { ApiService } from './api.service';
describe('ApiService', () => { describe('ApiService', () => {
let injector: ReflectiveInjector; let injector: Injector;
let service: ApiService; let service: ApiService;
let backend: MockBackend; let httpMock: HttpTestingController;
function createResponse(body: any) {
return new Response(new ResponseOptions({ body: JSON.stringify(body) }));
}
beforeEach(() => { beforeEach(() => {
injector = ReflectiveInjector.resolveAndCreate([ injector = TestBed.configureTestingModule({
ApiService, imports: [HttpClientTestingModule],
{ provide: ConnectionBackend, useClass: MockBackend }, providers: [
{ provide: RequestOptions, useClass: BaseRequestOptions }, ApiService,
Http, { provide: Logger, useClass: TestLogger }
{ provide: Logger, useClass: TestLogger } ]
]); });
});
beforeEach(() => {
backend = injector.get(ConnectionBackend);
service = injector.get(ApiService); service = injector.get(ApiService);
httpMock = injector.get(HttpTestingController);
}); });
it('should be creatable', () => { afterEach(() => httpMock.verify());
expect(service).toBeTruthy();
});
it('should not immediately connect to the server', () => { it('should not immediately connect to the server', () => {
expect(backend.connectionsArray.length).toEqual(0); httpMock.expectNone({});
}); });
it('subscribers should be completed/unsubscribed when service destroyed', () => { it('subscribers should be completed/unsubscribed when service destroyed', () => {
@ -50,9 +42,13 @@ describe('ApiService', () => {
service.ngOnDestroy(); service.ngOnDestroy();
expect(completed).toBe(true); expect(completed).toBe(true);
// Stop `httpMock.verify()` from complaining.
httpMock.expectOne({});
}); });
describe('#sections', () => { describe('#sections', () => {
it('first subscriber should fetch sections', () => { it('first subscriber should fetch sections', () => {
const data = [{name: 'a', title: 'A', items: []}, {name: 'b', title: 'B', items: []}]; const data = [{name: 'a', title: 'A', items: []}, {name: 'b', title: 'B', items: []}];
@ -60,7 +56,7 @@ describe('ApiService', () => {
expect(sections).toEqual(data); expect(sections).toEqual(data);
}); });
backend.connectionsArray[0].mockRespond(createResponse(data)); httpMock.expectOne({}).flush(data);
}); });
it('second subscriber should get previous sections and NOT trigger refetch', () => { it('second subscriber should get previous sections and NOT trigger refetch', () => {
@ -77,27 +73,20 @@ describe('ApiService', () => {
expect(sections).toEqual(data); expect(sections).toEqual(data);
}); });
backend.connectionsArray[0].mockRespond(createResponse(data)); httpMock.expectOne({}).flush(data);
expect(backend.connectionsArray.length).toBe(1, 'server connections');
expect(subscriptions).toBe(2, 'subscriptions');
}); });
}); });
describe('#fetchSections', () => { describe('#fetchSections', () => {
it('should connect to the server w/ expected URL', () => { it('should connect to the server w/ expected URL', () => {
service.fetchSections(); service.fetchSections();
expect(backend.connectionsArray.length).toEqual(1); httpMock.expectOne('generated/docs/api/api-list.json');
expect(backend.connectionsArray[0].request.url).toEqual('generated/docs/api/api-list.json');
}); });
it('should refresh the #sections observable w/ new content on second call', () => { it('should refresh the #sections observable w/ new content on second call', () => {
let call = 0; let call = 0;
let connection: MockConnection;
backend.connections.subscribe(c => connection = c);
let data = [{name: 'a', title: 'A', items: []}, {name: 'b', title: 'B', items: []}]; let data = [{name: 'a', title: 'A', items: []}, {name: 'b', title: 'B', items: []}];
@ -107,12 +96,13 @@ describe('ApiService', () => {
// (2) after refresh // (2) after refresh
expect(sections).toEqual(data, 'call ' + call++); expect(sections).toEqual(data, 'call ' + call++);
}); });
connection.mockRespond(createResponse(data));
httpMock.expectOne({}).flush(data);
// refresh/refetch // refresh/refetch
data = [{name: 'c', title: 'C', items: []}]; data = [{name: 'c', title: 'C', items: []}];
service.fetchSections(); service.fetchSections();
connection.mockRespond(createResponse(data)); httpMock.expectOne({}).flush(data);
expect(call).toBe(2, 'should be called twice'); expect(call).toBe(2, 'should be called twice');
}); });

View File

@ -1,5 +1,5 @@
import { Injectable, OnDestroy } from '@angular/core'; import { Injectable, OnDestroy } from '@angular/core';
import { Http } from '@angular/http'; import { HttpClient, HttpErrorResponse } from '@angular/common/http';
import { ReplaySubject } from 'rxjs/ReplaySubject'; import { ReplaySubject } from 'rxjs/ReplaySubject';
import { Subject } from 'rxjs/Subject'; import { Subject } from 'rxjs/Subject';
@ -54,7 +54,7 @@ export class ApiService implements OnDestroy {
return this._sections; return this._sections;
}; };
constructor(private http: Http, private logger: Logger) { } constructor(private http: HttpClient, private logger: Logger) { }
ngOnDestroy() { ngOnDestroy() {
this.onDestroy.next(); this.onDestroy.next();
@ -70,13 +70,12 @@ export class ApiService implements OnDestroy {
fetchSections(src?: string) { fetchSections(src?: string) {
// TODO: get URL by configuration? // TODO: get URL by configuration?
const url = this.apiBase + (src || this.apiListJsonDefault); const url = this.apiBase + (src || this.apiListJsonDefault);
this.http.get(url) this.http.get<ApiSection[]>(url)
.takeUntil(this.onDestroy) .takeUntil(this.onDestroy)
.map(response => response.json())
.do(() => this.logger.log(`Got API sections from ${url}`)) .do(() => this.logger.log(`Got API sections from ${url}`))
.subscribe( .subscribe(
sections => this.sectionsSubject.next(sections), sections => this.sectionsSubject.next(sections),
err => { (err: HttpErrorResponse) => {
// Todo: handle error // Todo: handle error
this.logger.error(err); this.logger.error(err);
throw err; // rethrow for now. throw err; // rethrow for now.

View File

@ -1,39 +1,33 @@
import { ReflectiveInjector } from '@angular/core'; import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing';
import { Http, ConnectionBackend, RequestOptions, BaseRequestOptions, Response, ResponseOptions } from '@angular/http'; import { Injector } from '@angular/core';
import { MockBackend } from '@angular/http/testing'; import { TestBed } from '@angular/core/testing';
import { ContributorService } from './contributor.service'; import { ContributorService } from './contributor.service';
import { Contributor, ContributorGroup } from './contributors.model'; import { Contributor, ContributorGroup } from './contributors.model';
describe('ContributorService', () => { describe('ContributorService', () => {
let injector: ReflectiveInjector; let injector: Injector;
let backend: MockBackend;
let contribService: ContributorService; let contribService: ContributorService;
let httpMock: HttpTestingController;
function createResponse(body: any) {
return new Response(new ResponseOptions({ body: JSON.stringify(body) }));
}
beforeEach(() => { beforeEach(() => {
injector = ReflectiveInjector.resolveAndCreate([ injector = TestBed.configureTestingModule({
ContributorService, imports: [HttpClientTestingModule],
{ provide: ConnectionBackend, useClass: MockBackend }, providers: [
{ provide: RequestOptions, useClass: BaseRequestOptions }, ContributorService
Http ]
]); });
backend = injector.get(ConnectionBackend);
contribService = injector.get(ContributorService); contribService = injector.get(ContributorService);
httpMock = injector.get(HttpTestingController);
}); });
it('should be creatable', () => { afterEach(() => httpMock.verify());
expect(contribService).toBeTruthy();
});
it('should make a single connection to the server', () => { it('should make a single connection to the server', () => {
expect(backend.connectionsArray.length).toEqual(1); const req = httpMock.expectOne({});
expect(backend.connectionsArray[0].request.url).toEqual('generated/contributors.json'); expect(req.request.url).toBe('generated/contributors.json');
}); });
describe('#contributors', () => { describe('#contributors', () => {
@ -43,7 +37,7 @@ describe('ContributorService', () => {
beforeEach(() => { beforeEach(() => {
testData = getTestContribs(); testData = getTestContribs();
backend.connectionsArray[0].mockRespond(createResponse(testData)); httpMock.expectOne({}).flush(testData);
contribService.contributors.subscribe(results => contribs = results); contribService.contributors.subscribe(results => contribs = results);
}); });
@ -70,55 +64,54 @@ describe('ContributorService', () => {
}); });
function getTestContribs() { function getTestContribs() {
// tslint:disable:quotemark
return { return {
"kapunahelewong": { kapunahelewong: {
"name": "Kapunahele Wong", name: 'Kapunahele Wong',
"picture": "kapunahelewong.jpg", picture: 'kapunahelewong.jpg',
"website": " https://github.com/kapunahelewong", website: 'https://github.com/kapunahelewong',
"twitter": "kapunahele", twitter: 'kapunahele',
"bio": "Kapunahele is a front-end developer and contributor to angular.io", bio: 'Kapunahele is a front-end developer and contributor to angular.io',
"group": "GDE" group: 'GDE'
}, },
"misko": { misko: {
"name": "Miško Hevery", name: 'Miško Hevery',
"picture": "misko.jpg", picture: 'misko.jpg',
"twitter": "mhevery", twitter: 'mhevery',
"website": "http://misko.hevery.com", website: 'http://misko.hevery.com',
"bio": "Miško Hevery is the creator of AngularJS framework.", bio: 'Miško Hevery is the creator of AngularJS framework.',
"group": "Angular" group: 'Angular'
}, },
"igor": { igor: {
"name": "Igor Minar", name: 'Igor Minar',
"picture": "igor-minar.jpg", picture: 'igor-minar.jpg',
"twitter": "IgorMinar", twitter: 'IgorMinar',
"website": "https://google.com/+IgorMinar", website: 'https://google.com/+IgorMinar',
"bio": "Igor is a software engineer at Angular.", bio: 'Igor is a software engineer at Angular.',
"group": "Angular" group: 'Angular'
}, },
"kara": { kara: {
"name": "Kara Erickson", name: 'Kara Erickson',
"picture": "kara-erickson.jpg", picture: 'kara-erickson.jpg',
"twitter": "karaforthewin", twitter: 'karaforthewin',
"website": "https://github.com/kara", website: 'https://github.com/kara',
"bio": "Kara is a software engineer on the Angular team at Angular and a co-organizer of the Angular-SF Meetup. ", bio: 'Kara is a software engineer on the Angular team at Angular and a co-organizer of the Angular-SF Meetup. ',
"group": "Angular" group: 'Angular'
}, },
"jeffcross": { jeffcross: {
"name": "Jeff Cross", name: 'Jeff Cross',
"picture": "jeff-cross.jpg", picture: 'jeff-cross.jpg',
"twitter": "jeffbcross", twitter: 'jeffbcross',
"website": "https://twitter.com/jeffbcross", website: 'https://twitter.com/jeffbcross',
"bio": "Jeff was one of the earliest core team members on AngularJS.", bio: 'Jeff was one of the earliest core team members on AngularJS.',
"group": "GDE" group: 'GDE'
}, },
"naomi": { naomi: {
"name": "Naomi Black", name: 'Naomi Black',
"picture": "naomi.jpg", picture: 'naomi.jpg',
"twitter": "naomitraveller", twitter: 'naomitraveller',
"website": "http://google.com/+NaomiBlack", website: 'http://google.com/+NaomiBlack',
"bio": "Naomi is Angular's TPM generalist and jack-of-all-trades.", bio: 'Naomi is Angular\'s TPM generalist and jack-of-all-trades.',
"group": "Angular" group: 'Angular'
} }
}; };
} }

View File

@ -1,5 +1,5 @@
import { Injectable } from '@angular/core'; import { Injectable } from '@angular/core';
import { Http } from '@angular/http'; import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs/Observable'; import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/map'; import 'rxjs/add/operator/map';
@ -15,14 +15,12 @@ const knownGroups = ['Angular', 'GDE'];
export class ContributorService { export class ContributorService {
contributors: Observable<ContributorGroup[]>; contributors: Observable<ContributorGroup[]>;
constructor(private http: Http) { constructor(private http: HttpClient) {
this.contributors = this.getContributors(); this.contributors = this.getContributors();
} }
private getContributors() { private getContributors() {
const contributors = this.http.get(contributorsPath) const contributors = this.http.get<{[key: string]: Contributor}>(contributorsPath)
.map(res => res.json())
// Create group map // Create group map
.map(contribs => { .map(contribs => {
const contribMap = new Map<string, Contributor[]>(); const contribMap = new Map<string, Contributor[]>();

View File

@ -1,39 +1,33 @@
import { ReflectiveInjector } from '@angular/core'; import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing';
import { Http, ConnectionBackend, RequestOptions, BaseRequestOptions, Response, ResponseOptions } from '@angular/http'; import { Injector } from '@angular/core';
import { MockBackend } from '@angular/http/testing'; import { TestBed } from '@angular/core/testing';
import { ResourceService } from './resource.service'; import { ResourceService } from './resource.service';
import { Category, SubCategory, Resource } from './resource.model'; import { Category, SubCategory, Resource } from './resource.model';
describe('ResourceService', () => { describe('ResourceService', () => {
let injector: ReflectiveInjector; let injector: Injector;
let backend: MockBackend;
let resourceService: ResourceService; let resourceService: ResourceService;
let httpMock: HttpTestingController;
function createResponse(body: any) {
return new Response(new ResponseOptions({ body: JSON.stringify(body) }));
}
beforeEach(() => { beforeEach(() => {
injector = ReflectiveInjector.resolveAndCreate([ injector = TestBed.configureTestingModule({
ResourceService, imports: [HttpClientTestingModule],
{ provide: ConnectionBackend, useClass: MockBackend }, providers: [
{ provide: RequestOptions, useClass: BaseRequestOptions }, ResourceService
Http ]
]); });
backend = injector.get(ConnectionBackend);
resourceService = injector.get(ResourceService); resourceService = injector.get(ResourceService);
httpMock = injector.get(HttpTestingController);
}); });
it('should be creatable', () => { afterEach(() => httpMock.verify());
expect(resourceService).toBeTruthy();
});
it('should make a single connection to the server', () => { it('should make a single connection to the server', () => {
expect(backend.connectionsArray.length).toEqual(1); const req = httpMock.expectOne({});
expect(backend.connectionsArray[0].request.url).toEqual('generated/resources.json'); expect(req.request.url).toBe('generated/resources.json');
}); });
describe('#categories', () => { describe('#categories', () => {
@ -43,7 +37,7 @@ describe('ResourceService', () => {
beforeEach(() => { beforeEach(() => {
testData = getTestResources(); testData = getTestResources();
backend.connectionsArray[0].mockRespond(createResponse(testData)); httpMock.expectOne({}).flush(testData);
resourceService.categories.subscribe(results => categories = results); resourceService.categories.subscribe(results => categories = results);
}); });

View File

@ -1,5 +1,5 @@
import { Injectable } from '@angular/core'; import { Injectable } from '@angular/core';
import { Http } from '@angular/http'; import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs/Observable'; import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/map'; import 'rxjs/add/operator/map';
@ -14,14 +14,13 @@ const resourcesPath = CONTENT_URL_PREFIX + 'resources.json';
export class ResourceService { export class ResourceService {
categories: Observable<Category[]>; categories: Observable<Category[]>;
constructor(private http: Http) { constructor(private http: HttpClient) {
this.categories = this.getCategories(); this.categories = this.getCategories();
} }
private getCategories(): Observable<Category[]> { private getCategories(): Observable<Category[]> {
const categories = this.http.get(resourcesPath) const categories = this.http.get<any>(resourcesPath)
.map(res => res.json())
.map(data => mkCategories(data)) .map(data => mkCategories(data))
.publishLast(); .publishLast();

View File

@ -1,44 +1,37 @@
import { ReflectiveInjector } from '@angular/core'; import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing';
import { Http, ConnectionBackend, RequestOptions, BaseRequestOptions, Response, ResponseOptions } from '@angular/http'; import { Injector } from '@angular/core';
import { MockBackend } from '@angular/http/testing'; import { TestBed } from '@angular/core/testing';
import { CurrentNodes, NavigationService, NavigationViews, NavigationNode, VersionInfo } from 'app/navigation/navigation.service'; import { CurrentNodes, NavigationService, NavigationViews, NavigationNode, VersionInfo } from 'app/navigation/navigation.service';
import { LocationService } from 'app/shared/location.service'; import { LocationService } from 'app/shared/location.service';
import { MockLocationService } from 'testing/location.service'; import { MockLocationService } from 'testing/location.service';
describe('NavigationService', () => { describe('NavigationService', () => {
let injector: ReflectiveInjector; let injector: Injector;
let backend: MockBackend;
let navService: NavigationService; let navService: NavigationService;
let httpMock: HttpTestingController;
function createResponse(body: any) {
return new Response(new ResponseOptions({ body: JSON.stringify(body) }));
}
beforeEach(() => { beforeEach(() => {
injector = ReflectiveInjector.resolveAndCreate([ injector = TestBed.configureTestingModule({
imports: [HttpClientTestingModule],
providers: [
NavigationService, NavigationService,
{ provide: LocationService, useFactory: () => new MockLocationService('a') }, { provide: LocationService, useFactory: () => new MockLocationService('a') }
{ provide: ConnectionBackend, useClass: MockBackend }, ]
{ provide: RequestOptions, useClass: BaseRequestOptions }, });
Http
]);
});
beforeEach(() => {
backend = injector.get(ConnectionBackend);
navService = injector.get(NavigationService); navService = injector.get(NavigationService);
httpMock = injector.get(HttpTestingController);
}); });
it('should be creatable', () => { afterEach(() => httpMock.verify());
expect(navService).toBeTruthy();
});
describe('navigationViews', () => { describe('navigationViews', () => {
it('should make a single connection to the server', () => { it('should make a single connection to the server', () => {
expect(backend.connectionsArray.length).toEqual(1); const req = httpMock.expectOne({});
expect(backend.connectionsArray[0].request.url).toEqual('generated/navigation.json'); expect(req.request.url).toBe('generated/navigation.json');
}); });
it('should expose the server response', () => { it('should expose the server response', () => {
@ -46,7 +39,7 @@ describe('NavigationService', () => {
navService.navigationViews.subscribe(views => viewsEvents.push(views)); navService.navigationViews.subscribe(views => viewsEvents.push(views));
expect(viewsEvents).toEqual([]); expect(viewsEvents).toEqual([]);
backend.connectionsArray[0].mockRespond(createResponse({ TopBar: [ { url: 'a' }] })); httpMock.expectOne({}).flush({ TopBar: [ { url: 'a' }] });
expect(viewsEvents).toEqual([{ TopBar: [ { url: 'a' }] }]); expect(viewsEvents).toEqual([{ TopBar: [ { url: 'a' }] }]);
}); });
@ -54,6 +47,9 @@ describe('NavigationService', () => {
let completed = false; let completed = false;
navService.navigationViews.subscribe(null, null, () => completed = true); navService.navigationViews.subscribe(null, null, () => completed = true);
expect(true).toBe(true, 'observable completed'); expect(true).toBe(true, 'observable completed');
// Stop `$httpMock.verify()` from complaining.
httpMock.expectOne({});
}); });
it('should return the same object to all subscribers', () => { it('should return the same object to all subscribers', () => {
@ -63,16 +59,16 @@ describe('NavigationService', () => {
let views2: NavigationViews; let views2: NavigationViews;
navService.navigationViews.subscribe(views => views2 = views); navService.navigationViews.subscribe(views => views2 = views);
backend.connectionsArray[0].mockRespond(createResponse({ TopBar: [{ url: 'a' }] })); httpMock.expectOne({}).flush({ TopBar: [{ url: 'a' }] });
// modify the response so we can check that future subscriptions do not trigger another request
backend.connectionsArray[0].response.next(createResponse({ TopBar: [{ url: 'error 1' }] }));
let views3: NavigationViews; let views3: NavigationViews;
navService.navigationViews.subscribe(views => views3 = views); navService.navigationViews.subscribe(views => views3 = views);
expect(views2).toBe(views1); expect(views2).toBe(views1);
expect(views3).toBe(views1); expect(views3).toBe(views1);
// Verfy that subsequent subscriptions did not trigger another request.
httpMock.expectNone({});
}); });
it('should do WHAT(?) if the request fails'); it('should do WHAT(?) if the request fails');
@ -90,7 +86,7 @@ describe('NavigationService', () => {
beforeEach(() => { beforeEach(() => {
navService.navigationViews.subscribe(views => view = views['sideNav']); navService.navigationViews.subscribe(views => view = views['sideNav']);
backend.connectionsArray[0].mockRespond(createResponse({sideNav})); httpMock.expectOne({}).flush({sideNav});
}); });
it('should have the supplied tooltip', () => { it('should have the supplied tooltip', () => {
@ -135,9 +131,9 @@ describe('NavigationService', () => {
}; };
beforeEach(() => { beforeEach(() => {
locationService = injector.get(LocationService); locationService = injector.get(LocationService) as any as MockLocationService;
navService.currentNodes.subscribe(selected => currentNodes = selected); navService.currentNodes.subscribe(selected => currentNodes = selected);
backend.connectionsArray[0].mockRespond(createResponse(navJson)); httpMock.expectOne({}).flush(navJson);
}); });
it('should list the side navigation node that matches the current location, and all its ancestors', () => { it('should list the side navigation node that matches the current location, and all its ancestors', () => {
@ -231,9 +227,9 @@ describe('NavigationService', () => {
beforeEach(() => { beforeEach(() => {
navService.versionInfo.subscribe(info => versionInfo = info); navService.versionInfo.subscribe(info => versionInfo = info);
backend.connectionsArray[0].mockRespond(createResponse({ httpMock.expectOne({}).flush({
__versionInfo: expectedVersionInfo __versionInfo: expectedVersionInfo
})); });
}); });
it('should extract the version info', () => { it('should extract the version info', () => {
@ -261,7 +257,7 @@ describe('NavigationService', () => {
}); });
it('should extract the docVersions', () => { it('should extract the docVersions', () => {
backend.connectionsArray[0].mockRespond(createResponse({ docVersions })); httpMock.expectOne({}).flush({ docVersions });
expect(actualDocVersions).toEqual(expectedDocVersions); expect(actualDocVersions).toEqual(expectedDocVersions);
}); });
}); });

View File

@ -1,5 +1,5 @@
import { Injectable } from '@angular/core'; import { Injectable } from '@angular/core';
import { Http } from '@angular/http'; import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs/Observable'; import { Observable } from 'rxjs/Observable';
import { AsyncSubject } from 'rxjs/AsyncSubject'; import { AsyncSubject } from 'rxjs/AsyncSubject';
@ -36,7 +36,7 @@ export class NavigationService {
*/ */
currentNodes: Observable<CurrentNodes>; currentNodes: Observable<CurrentNodes>;
constructor(private http: Http, private location: LocationService) { constructor(private http: HttpClient, private location: LocationService) {
const navigationInfo = this.fetchNavigationInfo(); const navigationInfo = this.fetchNavigationInfo();
this.navigationViews = this.getNavigationViews(navigationInfo); this.navigationViews = this.getNavigationViews(navigationInfo);
@ -57,8 +57,7 @@ export class NavigationService {
* We are not storing the subscription from connecting as we do not expect this service to be destroyed. * We are not storing the subscription from connecting as we do not expect this service to be destroyed.
*/ */
private fetchNavigationInfo(): Observable<NavigationResponse> { private fetchNavigationInfo(): Observable<NavigationResponse> {
const navigationInfo = this.http.get(navigationPath) const navigationInfo = this.http.get<NavigationResponse>(navigationPath)
.map(res => res.json() as NavigationResponse)
.publishLast(); .publishLast();
navigationInfo.connect(); navigationInfo.connect();
return navigationInfo; return navigationInfo;

View File

@ -12,7 +12,7 @@ describe('CustomMdIconRegistry', () => {
]; ];
const registry = new CustomMdIconRegistry(mockHttp, mockSanitizer, svgIcons); const registry = new CustomMdIconRegistry(mockHttp, mockSanitizer, svgIcons);
let svgElement: SVGElement; let svgElement: SVGElement;
registry.getNamedSvgIcon('test_icon', null).subscribe(el => svgElement = el as SVGElement); registry.getNamedSvgIcon('test_icon').subscribe(el => svgElement = el);
expect(svgElement).toEqual(createSvg(svgSrc)); expect(svgElement).toEqual(createSvg(svgSrc));
}); });
@ -27,8 +27,12 @@ describe('CustomMdIconRegistry', () => {
spyOn(MdIconRegistry.prototype, 'getNamedSvgIcon'); spyOn(MdIconRegistry.prototype, 'getNamedSvgIcon');
const registry = new CustomMdIconRegistry(mockHttp, mockSanitizer, svgIcons); const registry = new CustomMdIconRegistry(mockHttp, mockSanitizer, svgIcons);
registry.getNamedSvgIcon('other_icon', null);
expect(MdIconRegistry.prototype.getNamedSvgIcon).toHaveBeenCalledWith('other_icon', null); registry.getNamedSvgIcon('other_icon');
expect(MdIconRegistry.prototype.getNamedSvgIcon).toHaveBeenCalledWith('other_icon', undefined);
registry.getNamedSvgIcon('other_icon', 'foo');
expect(MdIconRegistry.prototype.getNamedSvgIcon).toHaveBeenCalledWith('other_icon', 'foo');
}); });
}); });

View File

@ -1,7 +1,7 @@
import { InjectionToken, Inject, Injectable } from '@angular/core'; import { InjectionToken, Inject, Injectable } from '@angular/core';
import { of } from 'rxjs/observable/of'; import { of } from 'rxjs/observable/of';
import { MdIconRegistry } from '@angular/material'; import { MdIconRegistry } from '@angular/material';
import { Http } from '@angular/http'; import { HttpClient } from '@angular/common/http';
import { DomSanitizer } from '@angular/platform-browser'; import { DomSanitizer } from '@angular/platform-browser';
/** /**
@ -27,6 +27,19 @@ interface SvgIconMap {
[iconName: string]: SVGElement; [iconName: string]: SVGElement;
} }
// <hack-alert>
// @angular/material's `MdIconRegitry` currently (v2.0.0-beta.8) requires an instance of `Http`
// (from @angular/http). It is only used to [get some text content][1], so we can create a wrapper
// around `HttpClient` and pretend it is `Http`.
// [1]: https://github.com/angular/material2/blob/2.0.0-beta.8/src/lib/icon/icon-registry.ts#L465-L466
// </hack-alert>
function createFakeHttp(http: HttpClient): any {
return {
get: (url: string) => http.get(url, {responseType: 'text'})
.map(data => ({text: () => data}))
};
}
/** /**
* A custom replacement for Angular Material's `MdIconRegistry`, which allows * A custom replacement for Angular Material's `MdIconRegistry`, which allows
* us to provide preloaded icon SVG sources. * us to provide preloaded icon SVG sources.
@ -35,14 +48,14 @@ interface SvgIconMap {
export class CustomMdIconRegistry extends MdIconRegistry { export class CustomMdIconRegistry extends MdIconRegistry {
private preloadedSvgElements: SvgIconMap = {}; private preloadedSvgElements: SvgIconMap = {};
constructor(http: Http, sanitizer: DomSanitizer, @Inject(SVG_ICONS) svgIcons: SvgIconInfo[]) { constructor(http: HttpClient, sanitizer: DomSanitizer, @Inject(SVG_ICONS) svgIcons: SvgIconInfo[]) {
super(http, sanitizer); super(createFakeHttp(http), sanitizer);
this.loadSvgElements(svgIcons); this.loadSvgElements(svgIcons);
} }
getNamedSvgIcon(iconName, namespace) { getNamedSvgIcon(iconName: string, namespace?: string) {
if (this.preloadedSvgElements[iconName]) { if (this.preloadedSvgElements[iconName]) {
return of(this.preloadedSvgElements[iconName].cloneNode(true)); return of(this.preloadedSvgElements[iconName].cloneNode(true) as SVGElement);
} }
return super.getNamedSvgIcon(iconName, namespace); return super.getNamedSvgIcon(iconName, namespace);
} }

View File

@ -160,10 +160,6 @@ describe('ScrollSpyService', () => {
}); });
it('should be creatable', () => {
expect(scrollSpyService).toBeTruthy();
});
describe('#spyOn()', () => { describe('#spyOn()', () => {
let getSpiedElemGroups: () => ScrollSpiedElementGroup[]; let getSpiedElemGroups: () => ScrollSpiedElementGroup[];

View File

@ -31,10 +31,6 @@ describe('TocService', () => {
tocService.tocList.subscribe(tocList => lastTocList = tocList); tocService.tocList.subscribe(tocList => lastTocList = tocList);
}); });
it('should be creatable', () => {
expect(tocService).toBeTruthy();
});
describe('tocList', () => { describe('tocList', () => {
it('should emit the latest value to new subscribers', () => { it('should emit the latest value to new subscribers', () => {
const expectedValue1 = tocItem('Heading A'); const expectedValue1 = tocItem('Heading A');

View File

@ -14,19 +14,19 @@ import {
} from '@angular/platform-browser-dynamic/testing'; } from '@angular/platform-browser-dynamic/testing';
// List vendors here to increase test rebuild performance. // List vendors here to increase test rebuild performance.
import '@angular/animations';
import '@angular/common'; import '@angular/common';
import '@angular/common/testing'; import '@angular/common/testing';
import '@angular/common/http';
import '@angular/common/http/testing';
import '@angular/core/'; import '@angular/core/';
import '@angular/core/testing'; import '@angular/core/testing';
import '@angular/material';
import '@angular/platform-browser'; import '@angular/platform-browser';
import '@angular/platform-browser/testing'; import '@angular/platform-browser/testing';
import '@angular/platform-browser/animations'; import '@angular/platform-browser/animations';
import '@angular/platform-browser-dynamic'; import '@angular/platform-browser-dynamic';
import '@angular/platform-browser-dynamic/testing'; import '@angular/platform-browser-dynamic/testing';
import '@angular/http';
import '@angular/http/testing';
import '@angular/animations';
import '@angular/material';
import '@angular/service-worker'; import '@angular/service-worker';
import 'rxjs'; // tslint:disable-line import 'rxjs'; // tslint:disable-line

View File

@ -1,102 +0,0 @@
import { Response } from '@angular/http';
// tslint:disable:quotemark
export function getTestNavMapResponse(): Response {
const navMapJson = { "nodes": [
{
"docId": "guide/quickstart",
"navTitle": "Quickstart",
"tooltip": "A quick look at an Angular app."
},
{
"docId": "guide/cli-quickstart",
"navTitle": "CLI Quickstart",
"tooltip": "A quick look at an Angular app built with the Angular CLI.",
"hide": true // <----- SHOULD BE FILTERED OUT
},
{
"navTitle": "Tutorial",
"children": [
{
"docId": " tutorial/",
"navTitle": "Introduction",
"tooltip": "Introduction to the Tour of Heroes tutorial"
},
{
"docId": "tutorial/toh-pt1",
"navTitle": "The Hero Editor",
"tooltip": "Build a simple hero editor."
}
]
},
{
"navTitle": "Getting started",
"tooltip": "A gentle introduction to Angular",
"children": [
{
"docId": "guide/docs-overview",
"navTitle": "Overview",
"tooltip": "How to read and use this documentation."
},
{
"docId": "guide/setup",
"navTitle": "Setup",
"tooltip": "Install the Angular QuickStart seed for faster, more efficient development on your machine."
}
]
},
{
"navTitle": "Core",
"tooltip": "Learn the core capabilities of Angular",
"children": [
{
"docId": "guide/NgModule",
"navTitle": "Angular Modules (NgModule)",
"tooltip": "Define application modules with @NgModule."
},
{
"docId": "guide/directives",
"navTitle": "Directives",
"tooltip": "Learn how directives modify the layout and behavior of elements.",
"children": [
{
"docId": "guide/attribute-directives",
"navTitle": "Attribute directives",
"tooltip": "Attribute directives attach behavior to elements."
},
{
"docId": "guide/structural-directives",
"navTitle": "Structural directives",
"tooltip": "Structural directives manipulate the layout of the page."
}
]
}
]
},
{
"navTitle": "Empty Heading",
"children": [ ]
},
{
"navTitle": "External",
"children": [
{
"url": "https://gitter.im/angular/angular",
"navTitle": "Gitter",
"tooltip": "Chat about Angular with other birds of a feather"
}
]
}
]};
// tslint:enable:quotemark
return {
status: 200,
json: () => navMapJson
} as Response;
}

View File

@ -168,7 +168,7 @@
base64-js "^1.1.2" base64-js "^1.1.2"
jshashes "^1.0.5" jshashes "^1.0.5"
"@angular/tsc-wrapped@^5.0.0-beta.3": "@angular/tsc-wrapped@5.0.0-beta.3":
version "5.0.0-beta.3" version "5.0.0-beta.3"
resolved "https://registry.yarnpkg.com/@angular/tsc-wrapped/-/tsc-wrapped-5.0.0-beta.3.tgz#d71c607b02eb6fe7091b908ef2ec97180ec52618" resolved "https://registry.yarnpkg.com/@angular/tsc-wrapped/-/tsc-wrapped-5.0.0-beta.3.tgz#d71c607b02eb6fe7091b908ef2ec97180ec52618"
dependencies: dependencies: