Skip to content

Commit

Permalink
fix: improve error handling and displaying
Browse files Browse the repository at this point in the history
closes #20
  • Loading branch information
toedter committed Feb 21, 2021
1 parent f5538f0 commit 2694846
Show file tree
Hide file tree
Showing 15 changed files with 249 additions and 141 deletions.
4 changes: 2 additions & 2 deletions e2e/src/app.e2e-spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@ describe( 'HAL-Explorer App', () => {
expect(page.getFirstPropertiesSection().isPresent()).toBeFalsy();
expect(page.getFirstLinksSection().isPresent()).toBeFalsy();
expect(page.getEmbeddedSection().isPresent()).toBeFalsy();
expect(page.getResponseStatusSection().isDisplayed()).toBeFalsy();
expect(page.getResponseHeadersSection().isDisplayed()).toBeFalsy();
expect(page.getResponseStatusSection().isPresent()).toBeFalsy();
expect(page.getResponseHeadersSection().isPresent()).toBeFalsy();
expect(page.getResponseBodySection().isPresent()).toBeFalsy();

});
Expand Down
3 changes: 1 addition & 2 deletions src/app/app.service.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import {Injectable} from '@angular/core';
import {Subject} from 'rxjs';
import {Observable} from 'rxjs';
import {Observable, Subject} from 'rxjs';


export class RequestHeader {
Expand Down
4 changes: 2 additions & 2 deletions src/app/json-highlighter/json-highlighter.service.spec.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { inject, TestBed } from '@angular/core/testing';
import {inject, TestBed} from '@angular/core/testing';

import { JsonHighlighterService } from './json-highlighter.service';
import {JsonHighlighterService} from './json-highlighter.service';

describe( 'JsonHighlighterService', () => {
let jsonHighlighterService: JsonHighlighterService;
Expand Down
4 changes: 2 additions & 2 deletions src/app/request/request-validator.directive.spec.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { AbstractControl, FormControl } from '@angular/forms';
import { RequestValidatorDirective } from './request-validator.directive';
import {AbstractControl, FormControl} from '@angular/forms';
import {RequestValidatorDirective} from './request-validator.directive';

describe( 'RequestValidatorDirective', () => {
it( 'should create an instance', () => {
Expand Down
4 changes: 2 additions & 2 deletions src/app/request/request-validator.directive.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Directive, Input } from '@angular/core';
import { AbstractControl, FormControl, NG_VALIDATORS, Validator, Validators } from '@angular/forms';
import {Directive, Input} from '@angular/core';
import {AbstractControl, FormControl, NG_VALIDATORS, Validator, Validators} from '@angular/forms';

@Directive({
selector: '[appHalFormsProperty]',
Expand Down
2 changes: 1 addition & 1 deletion src/app/request/request.component.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import {Component, OnInit} from '@angular/core';
import * as $ from 'jquery';
import * as utpl from 'uri-templates';
import {URITemplate} from 'uri-templates';
import {AppService, RequestHeader} from '../app.service';
import {Command, EventType, HttpRequestEvent, RequestService, UriTemplateParameter} from './request.service';
import {URITemplate} from 'uri-templates';

@Component({
selector: 'app-uri-input',
Expand Down
35 changes: 18 additions & 17 deletions src/app/request/request.service.spec.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
import {TestBed} from '@angular/core/testing';
import {HttpClientTestingModule, HttpTestingController} from '@angular/common/http/testing';
import {Command, HttpRequestEvent, RequestService} from './request.service';
import {Command, HttpRequestEvent, RequestService, Response} from './request.service';
import {AppService, RequestHeader} from '../app.service';
import {HttpClient, HttpHeaders, HttpResponse} from '@angular/common/http';
import {HttpClient, HttpHeaders} from '@angular/common/http';
import {Type} from '@angular/core';
import {Subject} from 'rxjs';

describe('RequestService', () => {
let requestService: RequestService;
Expand Down Expand Up @@ -36,8 +35,8 @@ describe('RequestService', () => {
});

it('should set default accept request header', (done) => {
requestService.getResponseObservable().subscribe((response: HttpResponse<any>) => {
expect(response.body).toBe('body');
requestService.getResponseObservable().subscribe((response: Response) => {
expect(response.httpResponse.body).toBe('body');
done();
});

Expand All @@ -52,8 +51,8 @@ describe('RequestService', () => {
});

it('should not set default accept request header when custom accept header exists', (done) => {
requestService.getResponseObservable().subscribe((response: HttpResponse<any>) => {
expect(response.body).toBe('body');
requestService.getResponseObservable().subscribe((response: Response) => {
expect(response.httpResponse.body).toBe('body');
done();
});

Expand All @@ -72,8 +71,8 @@ describe('RequestService', () => {
});

it('should set Content-Type request header for POST request', (done) => {
requestService.getResponseObservable().subscribe((response: HttpResponse<any>) => {
expect(response.body).toBe('body');
requestService.getResponseObservable().subscribe((response: Response) => {
expect(response.httpResponse.body).toBe('body');
done();
});

Expand All @@ -89,8 +88,8 @@ describe('RequestService', () => {
});

it('should process Get command', (done) => {
requestService.getResponseObservable().subscribe((response: HttpResponse<any>) => {
expect(response.body).toBe('body');
requestService.getResponseObservable().subscribe((response: Response) => {
expect(response.httpResponse.body).toBe('body');
done();
});

Expand Down Expand Up @@ -124,8 +123,9 @@ describe('RequestService', () => {

it('should handle HTTP request error', (done) => {
const body = 'Invalid request parameters';
requestService.getResponseObservable().subscribe((response: HttpResponse<any>) => {
expect(response.body).toBe(body);
requestService.getResponseObservable().subscribe((response: Response) => {
expect(response.httpErrorResponse.status).toBe(404);
expect(response.httpErrorResponse.statusText).toBe('Not Found');
done();
});

Expand All @@ -148,7 +148,7 @@ describe('RequestService', () => {
status: 404, statusText: 'Not Found'
};
httpMock.expectOne('test-request').flush(errorEvent, mockErrorResponse);
expect(window.console.error).toHaveBeenCalled();
expect(window.console.error).not.toHaveBeenCalled();
});

it('should handle templated URIs', (done) => {
Expand All @@ -170,8 +170,8 @@ describe('RequestService', () => {
});

it('should process delete command', (done) => {
requestService.getResponseObservable().subscribe((response: HttpResponse<any>) => {
expect(response.status).toBe(204);
requestService.getResponseObservable().subscribe((response: Response) => {
expect(response.httpResponse.status).toBe(204);
done();
});

Expand Down Expand Up @@ -306,7 +306,8 @@ describe('RequestService', () => {

requestService.getJsonSchema(httpRequestEvent);

const jsonSchemaRequest = httpMock.expectOne('http://schema.org');
const profileRequest = httpMock.expectOne('http://schema.org');
expect(profileRequest.request.method).toBe('HEAD');
});

it('should not request undefined uri', () => {
Expand Down
33 changes: 10 additions & 23 deletions src/app/request/request.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import {Observable, Subject} from 'rxjs';
import * as utpl from 'uri-templates';
import {URITemplate} from 'uri-templates';
import {AppService, RequestHeader} from '../app.service';
import * as HttpStatus from 'http-status-codes';

export enum EventType {FillHttpRequest}

Expand All @@ -21,12 +20,16 @@ export class UriTemplateParameter {
}
}

export class Response {
constructor(public httpResponse: HttpResponse<any>, public httpErrorResponse: HttpErrorResponse) {
}
}

@Injectable()
export class RequestService {

private httpResponse: HttpResponse<any>;
private responseSubject: Subject<HttpResponse<any>> = new Subject<HttpResponse<any>>();
private responseObservable: Observable<HttpResponse<any>> = this.responseSubject.asObservable();
private responseSubject: Subject<Response> = new Subject<Response>();
private responseObservable: Observable<Response> = this.responseSubject.asObservable();

private needInfoSubject: Subject<any> = new Subject<any>();
private needInfoObservable: Observable<any> = this.needInfoSubject.asObservable();
Expand All @@ -43,7 +46,7 @@ export class RequestService {
constructor(private appService: AppService, private http: HttpClient) {
}

getResponseObservable(): Observable<HttpResponse<any>> {
getResponseObservable(): Observable<Response> {
return this.responseObservable;
}

Expand Down Expand Up @@ -71,26 +74,10 @@ export class RequestService {
this.appService.setUri(uri);
this.http.request(httpMethod, uri, {headers, observe: 'response', body}).subscribe(
(response: HttpResponse<any>) => {
(response as any).statusText = HttpStatus.getReasonPhrase(response.status);
this.httpResponse = response;
this.responseSubject.next(response);
this.responseSubject.next(new Response(response, null));
},
(error: HttpErrorResponse) => {
let statusText = '';
if (error.status !== 0) {
statusText = HttpStatus.getReasonPhrase(error.status);
}

if (error.error instanceof ErrorEvent) {
console.error('An error event occurred:', error.error.message);
} else {
// console.error(`Backend returned code ${error.status}, body: ${error.error}`);
this.httpResponse = new HttpResponse({
body: error.error, headers: error.headers,
status: error.status, statusText, url: error.url
});
this.responseSubject.next(this.httpResponse);
}
this.responseSubject.next(new Response(null, error));
}
);
}
Expand Down
77 changes: 70 additions & 7 deletions src/app/response-details/response-details.component.html
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<div [hidden]="responseStatus === 0" class="container">
<div *ngIf="httpResponse && !httpErrorResponse" class="container">
<div class="row">
<div class="col-lg-12">
<br>
Expand All @@ -10,7 +10,7 @@ <h5>Response Status</h5>
<table class="table table-striped table-sm">
<tbody>
<tr>
<td>{{responseStatus}} ({{responseStatusText}})</td>
<td>{{httpResponse.status}} ({{httpResponse.statusText}})</td>
</tr>
</tbody>
</table>
Expand All @@ -23,9 +23,9 @@ <h5>Response Headers</h5>
<div class="bs-component">
<table class="table table-striped table-sm">
<tbody>
<tr *ngFor="let header of responseHeaders">
<td class="w-25">{{header.key}}</td>
<td class="w-75">{{header.value}}</td>
<tr *ngFor="let key of httpResponse.headers.keys()">
<td class="w-25">{{key}}</td>
<td class="w-75">{{httpResponse.headers.get(key)}}</td>
</tr>
</tbody>
</table>
Expand All @@ -38,8 +38,8 @@ <h5>Response Body</h5>

<div class="card info">
<div class="card-text">
<pre *ngIf="!isString" [innerHTML]="responseBody">></pre>
<pre *ngIf="isString">{{responseBody}}</pre>
<pre *ngIf="!isString" [innerHTML]="responseBody">></pre>
<pre *ngIf="isString">{{responseBody}}</pre>
</div>
</div>
</div>
Expand All @@ -48,3 +48,66 @@ <h5>Response Body</h5>
</div>
</div>

<div *ngIf="httpErrorResponse" class="container">
<div class="row">
<div class="col-lg-12">
<br>
<div class="legend">
<h5>Error Response Status</h5>
</div>

<div class="bs-component">
<table class="table table-striped table-sm">
<tbody>
<tr>
<td>{{httpErrorResponse.status}} ({{httpErrorResponse.statusText}})</td>
</tr>
</tbody>
</table>
</div>

<div *ngIf="httpErrorResponse.headers.keys().length > 0">
<div class="legend">
<h5>Error Response Headers</h5>
</div>

<div class="bs-component">
<table class="table table-striped table-sm">
<tbody>
<tr *ngFor="let key of httpErrorResponse.headers.keys()">
<td class="w-25">{{key}}</td>
<td class="w-75">{{httpErrorResponse.headers.get(key)}}</td>
</tr>
</tbody>
</table>
</div>
</div>

<div>
<div class="legend">
<h5>Error Message</h5>
</div>

<div class="card info">
<div class="card-text">
<pre>{{httpErrorResponse.message}}</pre>
</div>
</div>
</div>
<br>
<div>
<div class="legend">
<h5>Additional Error Information</h5>
</div>

<div class="card info">
<div class="card-text">
<pre *ngIf="!isString" [innerHTML]="error">></pre>
<pre *ngIf="isString">{{error}}</pre>
</div>
</div>
</div>

</div>
</div>
</div>
Loading

0 comments on commit 2694846

Please sign in to comment.