From baadd109aa0659a7783924f6159e230ed2589a88 Mon Sep 17 00:00:00 2001 From: Quentin Focheux Date: Tue, 26 Jan 2021 22:42:04 +0100 Subject: [PATCH] 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 --- packages/common/http/test/client_spec.ts | 15 +++--- packages/common/http/test/response_spec.ts | 25 +++++----- packages/common/http/test/xhr_spec.ts | 54 +++++++++++---------- packages/common/http/testing/src/request.ts | 6 +-- 4 files changed, 53 insertions(+), 47 deletions(-) diff --git a/packages/common/http/test/client_spec.ts b/packages/common/http/test/client_spec.ts index f76c1a2389..d41693b368 100644 --- a/packages/common/http/test/client_spec.ts +++ b/packages/common/http/test/client_spec.ts @@ -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'}); }); }); }); diff --git a/packages/common/http/test/response_spec.ts b/packages/common/http/test/response_spec.ts index dafcb31b2f..c9d31174d5 100644 --- a/packages/common/http/test/response_spec.ts +++ b/packages/common/http/test/response_spec.ts @@ -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); diff --git a/packages/common/http/test/xhr_spec.ts b/packages/common/http/test/xhr_spec.ts index ae37b9e5d4..d645be91e3 100644 --- a/packages/common/http/test/xhr_spec.ts +++ b/packages/common/http/test/xhr_spec.ts @@ -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; 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; 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; - 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; - expect(response.status).toBe(200); + expect(response.status).toBe(HttpStatusCode.Ok); done(); }); factory.mock.mockFlush(0, 'CORS 0 status', 'Test'); diff --git a/packages/common/http/testing/src/request.ts b/packages/common/http/testing/src/request.ts index bdd9121784..f2039bc7f3 100644 --- a/packages/common/http/testing/src/request.ts +++ b/packages/common/http/testing/src/request.ts @@ -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';