test(http): use HttpStatusCode enum in tests (#23548)

Now that we have introduced human-readable http status codes,
we can use it in our tests to improve clarity.

PR Close #23548
This commit is contained in:
Quentin Focheux 2021-01-26 22:42:04 +01:00 committed by Misko Hevery
parent 6fe3a1de7f
commit baadd109aa
4 changed files with 53 additions and 47 deletions

View File

@ -7,7 +7,7 @@
*/
import {HttpClient} from '@angular/common/http/src/client';
import {HttpErrorResponse, HttpEventType, HttpResponse} from '@angular/common/http/src/response';
import {HttpErrorResponse, HttpEventType, HttpResponse, HttpStatusCode} from '@angular/common/http/src/response';
import {HttpClientTestingBackend} from '@angular/common/http/testing/src/backend';
import {ddescribe, describe, fit, it} from '@angular/core/testing/src/testing_internal';
import {toArray} from 'rxjs/operators';
@ -105,7 +105,7 @@ import {toArray} from 'rxjs/operators';
client.post('/test', 'text body', {observe: 'response', responseType: 'text'})
.subscribe(res => {
expect(res.ok).toBeTruthy();
expect(res.status).toBe(200);
expect(res.status).toBe(HttpStatusCode.Ok);
done();
});
backend.expectOne('/test').flush('hello world');
@ -114,7 +114,7 @@ import {toArray} from 'rxjs/operators';
const body = {data: 'json body'};
client.post('/test', body, {observe: 'response', responseType: 'text'}).subscribe(res => {
expect(res.ok).toBeTruthy();
expect(res.status).toBe(200);
expect(res.status).toBe(HttpStatusCode.Ok);
done();
});
const testReq = backend.expectOne('/test');
@ -124,7 +124,7 @@ import {toArray} from 'rxjs/operators';
it('with a json body of false', done => {
client.post('/test', false, {observe: 'response', responseType: 'text'}).subscribe(res => {
expect(res.ok).toBeTruthy();
expect(res.status).toBe(200);
expect(res.status).toBe(HttpStatusCode.Ok);
done();
});
const testReq = backend.expectOne('/test');
@ -134,7 +134,7 @@ import {toArray} from 'rxjs/operators';
it('with a json body of 0', done => {
client.post('/test', 0, {observe: 'response', responseType: 'text'}).subscribe(res => {
expect(res.ok).toBeTruthy();
expect(res.status).toBe(200);
expect(res.status).toBe(HttpStatusCode.Ok);
done();
});
const testReq = backend.expectOne('/test');
@ -145,7 +145,7 @@ import {toArray} from 'rxjs/operators';
const body = new ArrayBuffer(4);
client.post('/test', body, {observe: 'response', responseType: 'text'}).subscribe(res => {
expect(res.ok).toBeTruthy();
expect(res.status).toBe(200);
expect(res.status).toBe(HttpStatusCode.Ok);
done();
});
const testReq = backend.expectOne('/test');
@ -167,7 +167,8 @@ import {toArray} from 'rxjs/operators';
done();
});
backend.expectOne('/test').flush(
{'data': 'hello world'}, {status: 500, statusText: 'Server error'});
{'data': 'hello world'},
{status: HttpStatusCode.InternalServerError, statusText: 'Server error'});
});
});
});

View File

@ -7,8 +7,8 @@
*/
import {HttpHeaders} from '@angular/common/http/src/headers';
import {HttpResponse} from '@angular/common/http/src/response';
import {ddescribe, describe, it} from '@angular/core/testing/src/testing_internal';
import {HttpResponse, HttpStatusCode} from '@angular/common/http/src/response';
import {describe, it} from '@angular/core/testing/src/testing_internal';
{
describe('HttpResponse', () => {
@ -19,21 +19,21 @@ import {ddescribe, describe, it} from '@angular/core/testing/src/testing_interna
headers: new HttpHeaders({
'Test': 'Test header',
}),
status: 201,
status: HttpStatusCode.Created,
statusText: 'Created',
url: '/test',
});
expect(resp.body).toBe('test body');
expect(resp.headers instanceof HttpHeaders).toBeTruthy();
expect(resp.headers.get('Test')).toBe('Test header');
expect(resp.status).toBe(201);
expect(resp.status).toBe(HttpStatusCode.Created);
expect(resp.statusText).toBe('Created');
expect(resp.url).toBe('/test');
});
it('uses defaults if no args passed', () => {
const resp = new HttpResponse({});
expect(resp.headers).not.toBeNull();
expect(resp.status).toBe(200);
expect(resp.status).toBe(HttpStatusCode.Ok);
expect(resp.statusText).toBe('OK');
expect(resp.body).toBeNull();
expect(resp.ok).toBeTruthy();
@ -57,21 +57,22 @@ import {ddescribe, describe, it} from '@angular/core/testing/src/testing_interna
describe('.clone()', () => {
it('copies the original when given no arguments', () => {
const clone =
new HttpResponse({body: 'test', status: 201, statusText: 'created', url: '/test'})
new HttpResponse(
{body: 'test', status: HttpStatusCode.Created, statusText: 'created', url: '/test'})
.clone();
expect(clone.body).toBe('test');
expect(clone.status).toBe(201);
expect(clone.status).toBe(HttpStatusCode.Created);
expect(clone.statusText).toBe('created');
expect(clone.url).toBe('/test');
expect(clone.headers).not.toBeNull();
});
it('overrides the original', () => {
const orig =
new HttpResponse({body: 'test', status: 201, statusText: 'created', url: '/test'});
const clone =
orig.clone({body: {data: 'test'}, status: 200, statusText: 'Okay', url: '/bar'});
const orig = new HttpResponse(
{body: 'test', status: HttpStatusCode.Created, statusText: 'created', url: '/test'});
const clone = orig.clone(
{body: {data: 'test'}, status: HttpStatusCode.Ok, statusText: 'Okay', url: '/bar'});
expect(clone.body).toEqual({data: 'test'});
expect(clone.status).toBe(200);
expect(clone.status).toBe(HttpStatusCode.Ok);
expect(clone.statusText).toBe('Okay');
expect(clone.url).toBe('/bar');
expect(clone.headers).toBe(orig.headers);

View File

@ -7,9 +7,9 @@
*/
import {HttpRequest} from '@angular/common/http/src/request';
import {HttpDownloadProgressEvent, HttpErrorResponse, HttpEvent, HttpEventType, HttpHeaderResponse, HttpResponse, HttpResponseBase, HttpUploadProgressEvent} from '@angular/common/http/src/response';
import {HttpDownloadProgressEvent, HttpErrorResponse, HttpEvent, HttpEventType, HttpHeaderResponse, HttpResponse, HttpResponseBase, HttpStatusCode, HttpUploadProgressEvent} from '@angular/common/http/src/response';
import {HttpXhrBackend} from '@angular/common/http/src/xhr';
import {ddescribe, describe, fit, it} from '@angular/core/testing/src/testing_internal';
import {describe, it} from '@angular/core/testing/src/testing_internal';
import {Observable} from 'rxjs';
import {toArray} from 'rxjs/operators';
@ -78,39 +78,42 @@ const XSSI_PREFIX = ')]}\'\n';
});
it('handles a text response', () => {
const events = trackEvents(backend.handle(TEST_POST));
factory.mock.mockFlush(200, 'OK', 'some response');
factory.mock.mockFlush(HttpStatusCode.Ok, 'OK', 'some response');
expect(events.length).toBe(2);
expect(events[1].type).toBe(HttpEventType.Response);
expect(events[1] instanceof HttpResponse).toBeTruthy();
const res = events[1] as HttpResponse<string>;
expect(res.body).toBe('some response');
expect(res.status).toBe(200);
expect(res.status).toBe(HttpStatusCode.Ok);
expect(res.statusText).toBe('OK');
});
it('handles a json response', () => {
const events = trackEvents(backend.handle(TEST_POST.clone({responseType: 'json'})));
factory.mock.mockFlush(200, 'OK', JSON.stringify({data: 'some data'}));
factory.mock.mockFlush(HttpStatusCode.Ok, 'OK', JSON.stringify({data: 'some data'}));
expect(events.length).toBe(2);
const res = events[1] as HttpResponse<{data: string}>;
expect(res.body!.data).toBe('some data');
});
it('handles a blank json response', () => {
const events = trackEvents(backend.handle(TEST_POST.clone({responseType: 'json'})));
factory.mock.mockFlush(200, 'OK', '');
factory.mock.mockFlush(HttpStatusCode.Ok, 'OK', '');
expect(events.length).toBe(2);
const res = events[1] as HttpResponse<{data: string}>;
expect(res.body).toBeNull();
});
it('handles a json error response', () => {
const events = trackEvents(backend.handle(TEST_POST.clone({responseType: 'json'})));
factory.mock.mockFlush(500, 'Error', JSON.stringify({data: 'some data'}));
factory.mock.mockFlush(
HttpStatusCode.InternalServerError, 'Error', JSON.stringify({data: 'some data'}));
expect(events.length).toBe(2);
const res = events[1] as any as HttpErrorResponse;
expect(res.error!.data).toBe('some data');
});
it('handles a json error response with XSSI prefix', () => {
const events = trackEvents(backend.handle(TEST_POST.clone({responseType: 'json'})));
factory.mock.mockFlush(500, 'Error', XSSI_PREFIX + JSON.stringify({data: 'some data'}));
factory.mock.mockFlush(
HttpStatusCode.InternalServerError, 'Error',
XSSI_PREFIX + JSON.stringify({data: 'some data'}));
expect(events.length).toBe(2);
const res = events[1] as any as HttpErrorResponse;
expect(res.error!.data).toBe('some data');
@ -118,14 +121,15 @@ const XSSI_PREFIX = ')]}\'\n';
it('handles a json string response', () => {
const events = trackEvents(backend.handle(TEST_POST.clone({responseType: 'json'})));
expect(factory.mock.responseType).toEqual('text');
factory.mock.mockFlush(200, 'OK', JSON.stringify('this is a string'));
factory.mock.mockFlush(HttpStatusCode.Ok, 'OK', JSON.stringify('this is a string'));
expect(events.length).toBe(2);
const res = events[1] as HttpResponse<string>;
expect(res.body).toEqual('this is a string');
});
it('handles a json response with an XSSI prefix', () => {
const events = trackEvents(backend.handle(TEST_POST.clone({responseType: 'json'})));
factory.mock.mockFlush(200, 'OK', XSSI_PREFIX + JSON.stringify({data: 'some data'}));
factory.mock.mockFlush(
HttpStatusCode.Ok, 'OK', XSSI_PREFIX + JSON.stringify({data: 'some data'}));
expect(events.length).toBe(2);
const res = events[1] as HttpResponse<{data: string}>;
expect(res.body!.data).toBe('some data');
@ -136,7 +140,7 @@ const XSSI_PREFIX = ')]}\'\n';
expect(err.error).toBe('this is the error');
done();
});
factory.mock.mockFlush(400, 'Bad Request', 'this is the error');
factory.mock.mockFlush(HttpStatusCode.BadRequest, 'Bad Request', 'this is the error');
});
it('emits real errors via the error path', done => {
backend.handle(TEST_POST).subscribe(undefined, (err: HttpErrorResponse) => {
@ -156,7 +160,7 @@ const XSSI_PREFIX = ')]}\'\n';
});
factory.mock.abort = abort;
factory.mock.mockFlush(200, 'OK', 'Done');
factory.mock.mockFlush(HttpStatusCode.Ok, 'OK', 'Done');
});
describe('progress events', () => {
it('are emitted for download progress', done => {
@ -187,7 +191,7 @@ const XSSI_PREFIX = ')]}\'\n';
factory.mock.mockDownloadProgressEvent(100, 300);
factory.mock.responseText = 'download';
factory.mock.mockDownloadProgressEvent(200, 300);
factory.mock.mockFlush(200, 'OK', 'downloaded');
factory.mock.mockFlush(HttpStatusCode.Ok, 'OK', 'downloaded');
});
it('are emitted for upload progress', done => {
backend.handle(TEST_POST.clone({reportProgress: true}))
@ -211,7 +215,7 @@ const XSSI_PREFIX = ')]}\'\n';
});
factory.mock.mockUploadProgressEvent(100, 300);
factory.mock.mockUploadProgressEvent(200, 300);
factory.mock.mockFlush(200, 'OK', 'Done');
factory.mock.mockFlush(HttpStatusCode.Ok, 'OK', 'Done');
});
it('are emitted when both upload and download progress are available', done => {
backend.handle(TEST_POST.clone({reportProgress: true}))
@ -228,7 +232,7 @@ const XSSI_PREFIX = ')]}\'\n';
});
factory.mock.mockUploadProgressEvent(100, 300);
factory.mock.mockDownloadProgressEvent(200, 300);
factory.mock.mockFlush(200, 'OK', 'Done');
factory.mock.mockFlush(HttpStatusCode.Ok, 'OK', 'Done');
});
it('are emitted even if length is not computable', done => {
backend.handle(TEST_POST.clone({reportProgress: true}))
@ -245,7 +249,7 @@ const XSSI_PREFIX = ')]}\'\n';
});
factory.mock.mockUploadProgressEvent(100);
factory.mock.mockDownloadProgressEvent(200);
factory.mock.mockFlush(200, 'OK', 'Done');
factory.mock.mockFlush(HttpStatusCode.Ok, 'OK', 'Done');
});
it('include ResponseHeader with headers and status', done => {
backend.handle(TEST_POST.clone({reportProgress: true}))
@ -264,7 +268,7 @@ const XSSI_PREFIX = ')]}\'\n';
});
factory.mock.mockResponseHeaders = 'Test: Test header\nContent-Type: text/plain\n';
factory.mock.mockDownloadProgressEvent(200);
factory.mock.mockFlush(200, 'OK', 'Done');
factory.mock.mockFlush(HttpStatusCode.Ok, 'OK', 'Done');
});
it('are unsubscribed along with the main request', () => {
const sub = backend.handle(TEST_POST.clone({reportProgress: true})).subscribe();
@ -282,16 +286,16 @@ const XSSI_PREFIX = ')]}\'\n';
event.type === HttpEventType.ResponseHeader)
.map(event => event as HttpResponseBase)
.forEach(event => {
expect(event.status).toBe(203);
expect(event.status).toBe(HttpStatusCode.NonAuthoritativeInformation);
expect(event.headers.get('Test')).toEqual('This is a test');
});
done();
});
factory.mock.mockResponseHeaders = 'Test: This is a test\n';
factory.mock.status = 203;
factory.mock.status = HttpStatusCode.NonAuthoritativeInformation;
factory.mock.mockDownloadProgressEvent(100, 300);
factory.mock.mockResponseHeaders = 'Test: should never be read\n';
factory.mock.mockFlush(203, 'OK', 'Testing 1 2 3');
factory.mock.mockFlush(HttpStatusCode.NonAuthoritativeInformation, 'OK', 'Testing 1 2 3');
});
});
describe('gets response URL', () => {
@ -304,7 +308,7 @@ const XSSI_PREFIX = ')]}\'\n';
done();
});
factory.mock.responseURL = '/response/url';
factory.mock.mockFlush(200, 'OK', 'Test');
factory.mock.mockFlush(HttpStatusCode.Ok, 'OK', 'Test');
});
it('from X-Request-URL header if XHR.responseURL is not present', done => {
backend.handle(TEST_POST).pipe(toArray()).subscribe(events => {
@ -315,7 +319,7 @@ const XSSI_PREFIX = ')]}\'\n';
done();
});
factory.mock.mockResponseHeaders = 'X-Request-URL: /response/url\n';
factory.mock.mockFlush(200, 'OK', 'Test');
factory.mock.mockFlush(HttpStatusCode.Ok, 'OK', 'Test');
});
it('falls back on Request.url if neither are available', done => {
backend.handle(TEST_POST).pipe(toArray()).subscribe(events => {
@ -325,7 +329,7 @@ const XSSI_PREFIX = ')]}\'\n';
expect(response.url).toBe('/test');
done();
});
factory.mock.mockFlush(200, 'OK', 'Test');
factory.mock.mockFlush(HttpStatusCode.Ok, 'OK', 'Test');
});
});
describe('corrects for quirks', () => {
@ -334,7 +338,7 @@ const XSSI_PREFIX = ')]}\'\n';
expect(events.length).toBe(2);
expect(events[1].type).toBe(HttpEventType.Response);
const response = events[1] as HttpResponse<string>;
expect(response.status).toBe(204);
expect(response.status).toBe(HttpStatusCode.NoContent);
done();
});
factory.mock.mockFlush(1223, 'IE Special Status', 'Test');
@ -344,7 +348,7 @@ const XSSI_PREFIX = ')]}\'\n';
expect(events.length).toBe(2);
expect(events[1].type).toBe(HttpEventType.Response);
const response = events[1] as HttpResponse<string>;
expect(response.status).toBe(200);
expect(response.status).toBe(HttpStatusCode.Ok);
done();
});
factory.mock.mockFlush(0, 'CORS 0 status', 'Test');

View File

@ -6,7 +6,7 @@
* found in the LICENSE file at https://angular.io/license
*/
import {HttpErrorResponse, HttpEvent, HttpHeaders, HttpRequest, HttpResponse} from '@angular/common/http';
import {HttpErrorResponse, HttpEvent, HttpHeaders, HttpRequest, HttpResponse, HttpStatusCode} from '@angular/common/http';
import {Observer} from 'rxjs';
/**
@ -56,10 +56,10 @@ export class TestRequest {
(opts.headers instanceof HttpHeaders) ? opts.headers : new HttpHeaders(opts.headers);
body = _maybeConvertBody(this.request.responseType, body);
let statusText: string|undefined = opts.statusText;
let status: number = opts.status !== undefined ? opts.status : 200;
let status: number = opts.status !== undefined ? opts.status : HttpStatusCode.Ok;
if (opts.status === undefined) {
if (body === null) {
status = 204;
status = HttpStatusCode.NoContent;
statusText = statusText || 'No Content';
} else {
statusText = statusText || 'OK';