feat(aio): add prettier network fail page (#16139)
This commit is contained in:
parent
db4e9ea04a
commit
c390b06da2
|
@ -49,21 +49,21 @@ describe('DocumentService', () => {
|
|||
|
||||
describe('currentDocument', () => {
|
||||
|
||||
it('should fetch a document for the initial location url', () => {
|
||||
const { docService, backend } = getServices('initial/url');
|
||||
it('should fetch a document for the initial location', () => {
|
||||
const { docService, backend } = getServices('initial/doc');
|
||||
const connections = backend.connectionsArray;
|
||||
docService.currentDocument.subscribe();
|
||||
|
||||
expect(connections.length).toEqual(1);
|
||||
expect(connections[0].request.url).toEqual(CONTENT_URL_PREFIX + 'initial/url.json');
|
||||
expect(backend.connectionsArray[0].request.url).toEqual(CONTENT_URL_PREFIX + 'initial/url.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', () => {
|
||||
let latestDocument: DocumentContents;
|
||||
const doc0 = { title: 'doc 0', url: 'initial/url' };
|
||||
const doc1 = { title: 'doc 1', url: 'new/url' };
|
||||
const { docService, backend, locationService } = getServices('initial/url');
|
||||
const doc0 = { title: 'doc 0', id: 'initial/doc' };
|
||||
const doc1 = { title: 'doc 1', id: 'new/doc' };
|
||||
const { docService, backend, locationService } = getServices('initial/doc');
|
||||
const connections = backend.connectionsArray;
|
||||
|
||||
docService.currentDocument.subscribe(doc => latestDocument = doc);
|
||||
|
@ -72,13 +72,13 @@ describe('DocumentService', () => {
|
|||
connections[0].mockRespond(createResponse(doc0));
|
||||
expect(latestDocument).toEqual(doc0);
|
||||
|
||||
locationService.go('new/url');
|
||||
locationService.go('new/doc');
|
||||
connections[1].mockRespond(createResponse(doc1));
|
||||
expect(latestDocument).toEqual(doc1);
|
||||
});
|
||||
|
||||
it('should emit the not-found document if the document is not found on the server', () => {
|
||||
const { docService, backend } = getServices('missing/url');
|
||||
const { docService, backend } = getServices('missing/doc');
|
||||
const connections = backend.connectionsArray;
|
||||
let currentDocument: DocumentContents;
|
||||
docService.currentDocument.subscribe(doc => currentDocument = doc);
|
||||
|
@ -94,7 +94,7 @@ describe('DocumentService', () => {
|
|||
it('should emit a hard-coded not-found document if the not-found document is not found on the server', () => {
|
||||
let currentDocument: DocumentContents;
|
||||
const notFoundDoc: DocumentContents = { title: 'Not Found', contents: 'Document not found', id: 'file-not-found' };
|
||||
const nextDoc = { title: 'Next Doc', url: 'new/url' };
|
||||
const nextDoc = { title: 'Next Doc', id: 'new/doc' };
|
||||
const { docService, backend, locationService } = getServices('file-not-found');
|
||||
const connections = backend.connectionsArray;
|
||||
docService.currentDocument.subscribe(doc => currentDocument = doc);
|
||||
|
@ -104,23 +104,23 @@ describe('DocumentService', () => {
|
|||
expect(currentDocument).toEqual(notFoundDoc);
|
||||
|
||||
// now check that we haven't killed the currentDocument observable sequence
|
||||
locationService.go('new/url');
|
||||
locationService.go('new/doc');
|
||||
connections[1].mockRespond(createResponse(nextDoc));
|
||||
expect(currentDocument).toEqual(nextDoc);
|
||||
});
|
||||
|
||||
it('should not crash the app if the response is not valid JSON', () => {
|
||||
it('should not crash the app if the response is invalid JSON', () => {
|
||||
let latestDocument: DocumentContents;
|
||||
const { docService, backend, locationService} = getServices('initial/url');
|
||||
const { docService, backend, locationService} = getServices('initial/doc');
|
||||
const connections = backend.connectionsArray;
|
||||
|
||||
docService.currentDocument.subscribe(doc => latestDocument = doc);
|
||||
|
||||
connections[0].mockRespond(new Response(new ResponseOptions({ body: 'this is invalid JSON' })));
|
||||
expect(latestDocument.title).toEqual('Error fetching document');
|
||||
expect(latestDocument.title).toMatch('Document retrieval error');
|
||||
|
||||
const doc1 = { title: 'doc 1' };
|
||||
locationService.go('new/url');
|
||||
locationService.go('new/doc');
|
||||
connections[1].mockRespond(createResponse(doc1));
|
||||
expect(latestDocument).toEqual(jasmine.objectContaining(doc1));
|
||||
});
|
||||
|
|
|
@ -14,8 +14,18 @@ export { DocumentContents } from './document-contents';
|
|||
import { LocationService } from 'app/shared/location.service';
|
||||
import { Logger } from 'app/shared/logger.service';
|
||||
|
||||
const FILE_NOT_FOUND_URL = 'file-not-found';
|
||||
const FETCHING_ERROR_URL = 'fetching-error';
|
||||
const CONTENT_URL_PREFIX = 'content/docs/';
|
||||
const FILE_NOT_FOUND_ID = 'file-not-found';
|
||||
const FETCHING_ERROR_ID = 'fetching-error';
|
||||
const FETCHING_ERROR_CONTENTS = `
|
||||
<div class="nf-container l-flex-wrap flex-center">
|
||||
<div class="nf-icon material-icons">error_outline</div>
|
||||
<div class="nf-response l-flex-wrap">
|
||||
<h1>Request for document failed.</h1>
|
||||
<p>We are unable to retrieve the "<current-location></current-location>" page at this time.
|
||||
Please check your connection and try again later.</p>
|
||||
</div></div>
|
||||
`;
|
||||
|
||||
@Injectable()
|
||||
export class DocumentService {
|
||||
|
@ -49,32 +59,33 @@ export class DocumentService {
|
|||
.get(requestPath)
|
||||
.map(response => response.json())
|
||||
.catch((error: Response) => {
|
||||
return error.status === 404 ? this.getFileNotFoundDoc(id) : this.getErrorDoc(error);
|
||||
return error.status === 404 ? this.getFileNotFoundDoc(id) : this.getErrorDoc(id, error);
|
||||
})
|
||||
.subscribe(subject);
|
||||
return subject.asObservable();
|
||||
}
|
||||
|
||||
private getFileNotFoundDoc(url: string): Observable<DocumentContents> {
|
||||
if (url !== FILE_NOT_FOUND_URL) {
|
||||
this.logger.error(`Document file not found at '${url}'`);
|
||||
private getFileNotFoundDoc(id: string): Observable<DocumentContents> {
|
||||
if (id !== FILE_NOT_FOUND_ID) {
|
||||
this.logger.error(`Document file not found at '${id}'`);
|
||||
// using `getDocument` means that we can fetch the 404 doc contents from the server and cache it
|
||||
return this.getDocument(FILE_NOT_FOUND_URL);
|
||||
return this.getDocument(FILE_NOT_FOUND_ID);
|
||||
} else {
|
||||
return of({
|
||||
title: 'Not Found',
|
||||
contents: 'Document not found',
|
||||
id: FILE_NOT_FOUND_URL
|
||||
id: FILE_NOT_FOUND_ID
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private getErrorDoc(error: Response): Observable<DocumentContents> {
|
||||
private getErrorDoc(id: string, error: Response): Observable<DocumentContents> {
|
||||
this.logger.error('Error fetching document', error);
|
||||
this.cache.delete(id);
|
||||
return Observable.of({
|
||||
title: 'Error fetching document',
|
||||
contents: 'Sorry we were not able to fetch that document.',
|
||||
id: FETCHING_ERROR_URL
|
||||
title: 'Document retrieval error',
|
||||
contents: FETCHING_ERROR_CONTENTS,
|
||||
id: FETCHING_ERROR_ID
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#file-not-found {
|
||||
padding: 3rem 3rem 3rem;
|
||||
}
|
||||
}
|
||||
|
||||
.nf-container {
|
||||
align-items: center;
|
||||
|
@ -18,4 +18,10 @@
|
|||
text-transform: uppercase;
|
||||
margin: 8px 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.nf-icon.material-icons {
|
||||
color: $blue;
|
||||
font-size: 100px;
|
||||
position: static;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue