mirror of
https://github.com/angular/angular
synced 2026-05-24 09:28:37 +00:00
In order to raise an error on upload progress on the `FetchBackend`, we split `reportProgress` into 2 respective properties. DEPRECATED: The `reportProgress` option is deprecated please use `reportUploadProgress` & `reportDownloadProgress` instead.
290 lines
12 KiB
TypeScript
290 lines
12 KiB
TypeScript
/**
|
|
* @license
|
|
* Copyright Google LLC All Rights Reserved.
|
|
*
|
|
* Use of this source code is governed by an MIT-style license that can be
|
|
* found in the LICENSE file at https://angular.dev/license
|
|
*/
|
|
|
|
import {HttpContext} from '../src/context';
|
|
import {HttpHeaders} from '../src/headers';
|
|
import {HttpParams} from '../src/params';
|
|
import {HttpRequest} from '../src/request';
|
|
|
|
const TEST_URL = 'https://angular.io/';
|
|
const TEST_STRING = `I'm a body!`;
|
|
|
|
describe('HttpRequest', () => {
|
|
describe('constructor', () => {
|
|
it('initializes url', () => {
|
|
const req = new HttpRequest('', TEST_URL, null);
|
|
expect(req.url).toBe(TEST_URL);
|
|
});
|
|
it("doesn't require a body for body-less methods", () => {
|
|
let req = new HttpRequest('GET', TEST_URL);
|
|
expect(req.method).toBe('GET');
|
|
expect(req.body).toBeNull();
|
|
req = new HttpRequest('HEAD', TEST_URL);
|
|
expect(req.method).toBe('HEAD');
|
|
expect(req.body).toBeNull();
|
|
req = new HttpRequest('JSONP', TEST_URL);
|
|
expect(req.method).toBe('JSONP');
|
|
expect(req.body).toBeNull();
|
|
req = new HttpRequest('OPTIONS', TEST_URL);
|
|
expect(req.method).toBe('OPTIONS');
|
|
expect(req.body).toBeNull();
|
|
});
|
|
it('accepts a string request method', () => {
|
|
const req = new HttpRequest('TEST', TEST_URL, null);
|
|
expect(req.method).toBe('TEST');
|
|
});
|
|
it('accepts a string body', () => {
|
|
const req = new HttpRequest('POST', TEST_URL, TEST_STRING);
|
|
expect(req.body).toBe(TEST_STRING);
|
|
});
|
|
it('accepts an object body', () => {
|
|
const req = new HttpRequest('POST', TEST_URL, {data: TEST_STRING});
|
|
expect(req.body).toEqual({data: TEST_STRING});
|
|
});
|
|
it('creates default headers if not passed', () => {
|
|
const req = new HttpRequest('GET', TEST_URL);
|
|
expect(req.headers instanceof HttpHeaders).toBeTruthy();
|
|
});
|
|
it('uses the provided headers if passed', () => {
|
|
const headers = new HttpHeaders();
|
|
const req = new HttpRequest('GET', TEST_URL, {headers});
|
|
expect(req.headers).toBe(headers);
|
|
});
|
|
it('uses the provided context if passed', () => {
|
|
const context = new HttpContext();
|
|
const req = new HttpRequest('GET', TEST_URL, {context});
|
|
expect(req.context).toBe(context);
|
|
});
|
|
it('defaults to Json', () => {
|
|
const req = new HttpRequest('GET', TEST_URL);
|
|
expect(req.responseType).toBe('json');
|
|
});
|
|
it('should allow setting keepalive option', () => {
|
|
const req = new HttpRequest('GET', '/test', {keepalive: true});
|
|
expect(req.keepalive).toBe(true);
|
|
|
|
const req2 = new HttpRequest('GET', '/test', {keepalive: false});
|
|
expect(req2.keepalive).toBe(false);
|
|
});
|
|
it('should allow setting priority option', () => {
|
|
const req = new HttpRequest('GET', '/test', {priority: 'high'});
|
|
expect(req.priority).toBe('high');
|
|
});
|
|
it('should allow setting cache option', () => {
|
|
const req = new HttpRequest('GET', '/test', {cache: 'only-if-cached'});
|
|
expect(req.cache).toBe('only-if-cached');
|
|
});
|
|
it('should allow setting timeout option', () => {
|
|
const req = new HttpRequest('GET', '/test', {timeout: 5000});
|
|
expect(req.timeout).toBe(5000);
|
|
});
|
|
it('should allow setting credentials option', () => {
|
|
const req = new HttpRequest('GET', '/test', {credentials: 'same-origin'});
|
|
expect(req.credentials).toBe('same-origin');
|
|
});
|
|
it('should allow setting integrity option', () => {
|
|
const req = new HttpRequest('GET', '/test', {integrity: 'sha256-...'});
|
|
expect(req.integrity).toBe('sha256-...');
|
|
});
|
|
it('should allow setting referrer option', () => {
|
|
const req = new HttpRequest('GET', '/test', {referrer: 'about:client'});
|
|
expect(req.referrer).toBe('about:client');
|
|
});
|
|
it('should allow setting referrerPolicy option', () => {
|
|
const req = new HttpRequest('GET', '/test', {referrerPolicy: 'no-referrer'});
|
|
expect(req.referrerPolicy).toBe('no-referrer');
|
|
});
|
|
it('should allow setting upload and download progress options', () => {
|
|
const req = new HttpRequest('GET', '/test', {
|
|
reportUploadProgress: true,
|
|
reportDownloadProgress: true,
|
|
});
|
|
expect(req.reportUploadProgress).toBe(true);
|
|
expect(req.reportDownloadProgress).toBe(true);
|
|
});
|
|
});
|
|
describe('clone() copies the request', () => {
|
|
const headers = new HttpHeaders({
|
|
'Test': 'Test header',
|
|
});
|
|
const context = new HttpContext();
|
|
const req = new HttpRequest('POST', TEST_URL, 'test body', {
|
|
headers,
|
|
context,
|
|
reportProgress: true,
|
|
reportUploadProgress: true,
|
|
reportDownloadProgress: true,
|
|
responseType: 'text',
|
|
withCredentials: true,
|
|
transferCache: true,
|
|
keepalive: true,
|
|
cache: 'only-if-cached',
|
|
priority: 'high',
|
|
timeout: 1000,
|
|
credentials: 'same-origin',
|
|
referrer: 'about:client',
|
|
integrity: 'sha256-...',
|
|
referrerPolicy: 'no-referrer',
|
|
});
|
|
it('in the base case', () => {
|
|
const clone = req.clone();
|
|
expect(clone.method).toBe('POST');
|
|
expect(clone.responseType).toBe('text');
|
|
expect(clone.url).toBe(TEST_URL);
|
|
// Headers should be the same, as the headers are sealed.
|
|
expect(clone.headers).toBe(headers);
|
|
expect(clone.headers.get('Test')).toBe('Test header');
|
|
|
|
expect(clone.context).toBe(context);
|
|
expect(clone.reportProgress).toBe(true);
|
|
expect(clone.reportUploadProgress).toBe(true);
|
|
expect(clone.reportDownloadProgress).toBe(true);
|
|
expect(clone.transferCache).toBe(true);
|
|
expect(clone.keepalive).toBe(true);
|
|
expect(clone.cache).toBe('only-if-cached');
|
|
expect(clone.priority).toBe('high');
|
|
expect(clone.timeout).toBe(1000);
|
|
expect(clone.credentials).toBe('same-origin');
|
|
expect(clone.referrer).toBe('about:client');
|
|
expect(clone.integrity).toBe('sha256-...');
|
|
expect(clone.referrerPolicy).toBe('no-referrer');
|
|
});
|
|
it('and updates the url', () => {
|
|
expect(req.clone({url: '/changed'}).url).toBe('/changed');
|
|
});
|
|
it('and updates the method', () => {
|
|
expect(req.clone({method: 'PUT'}).method).toBe('PUT');
|
|
});
|
|
it('and updates the body', () => {
|
|
expect(req.clone({body: 'changed body'}).body).toBe('changed body');
|
|
});
|
|
it('and updates the context', () => {
|
|
const newContext = new HttpContext();
|
|
expect(req.clone({context: newContext}).context).toBe(newContext);
|
|
});
|
|
it('and updates the split progress flags', () => {
|
|
const clone = req.clone({reportUploadProgress: false, reportDownloadProgress: false});
|
|
expect(clone.reportUploadProgress).toBe(false);
|
|
expect(clone.reportDownloadProgress).toBe(false);
|
|
expect(clone.reportProgress).toBe(true);
|
|
});
|
|
it('and updates the transferCache', () => {
|
|
expect(req.clone({transferCache: false}).transferCache).toBe(false);
|
|
});
|
|
it('and updates the keepalive', () => {
|
|
expect(req.clone({keepalive: false}).keepalive).toBe(false);
|
|
});
|
|
it('and updates the timeout', () => {
|
|
expect(req.clone({timeout: 5000}).timeout).toBe(5000);
|
|
});
|
|
it('and updates the cache', () => {
|
|
expect(req.clone({cache: 'default'}).cache).toBe('default');
|
|
});
|
|
it('and updates the priority', () => {
|
|
expect(req.clone({priority: 'low'}).priority).toBe('low');
|
|
});
|
|
it('and updates the credentials', () => {
|
|
expect(req.clone({credentials: 'omit'}).credentials).toBe('omit');
|
|
});
|
|
it('and updates the referrer', () => {
|
|
expect(req.clone({referrer: 'https://example.com'}).referrer).toBe('https://example.com');
|
|
});
|
|
it('and updates the integrity', () => {
|
|
expect(req.clone({integrity: 'sha512-...'}).integrity).toBe('sha512-...');
|
|
});
|
|
it('and updates the referrerPolicy', () => {
|
|
expect(req.clone({referrerPolicy: 'origin'}).referrerPolicy).toBe('origin');
|
|
});
|
|
});
|
|
describe('content type detection', () => {
|
|
const baseReq = new HttpRequest('POST', '/test', null);
|
|
it('handles a null body', () => {
|
|
expect(baseReq.detectContentTypeHeader()).toBeNull();
|
|
});
|
|
it("doesn't associate a content type with ArrayBuffers", () => {
|
|
const req = baseReq.clone({body: new ArrayBuffer(4)});
|
|
expect(req.detectContentTypeHeader()).toBeNull();
|
|
});
|
|
it('handles strings as text', () => {
|
|
const req = baseReq.clone({body: 'hello world'});
|
|
expect(req.detectContentTypeHeader()).toBe('text/plain');
|
|
});
|
|
it('handles arrays as json', () => {
|
|
const req = baseReq.clone({body: ['a', 'b']});
|
|
expect(req.detectContentTypeHeader()).toBe('application/json');
|
|
});
|
|
it('handles numbers as json', () => {
|
|
const req = baseReq.clone({body: 314159});
|
|
expect(req.detectContentTypeHeader()).toBe('application/json');
|
|
});
|
|
it('handles objects as json', () => {
|
|
const req = baseReq.clone({body: {data: 'test data'}});
|
|
expect(req.detectContentTypeHeader()).toBe('application/json');
|
|
});
|
|
it('handles boolean as json', () => {
|
|
const req = baseReq.clone({body: true});
|
|
expect(req.detectContentTypeHeader()).toBe('application/json');
|
|
});
|
|
});
|
|
describe('body serialization', () => {
|
|
const baseReq = new HttpRequest('POST', '/test', null);
|
|
it('handles a null body', () => {
|
|
expect(baseReq.serializeBody()).toBeNull();
|
|
});
|
|
it('passes ArrayBuffers through', () => {
|
|
const body = new ArrayBuffer(4);
|
|
expect(baseReq.clone({body}).serializeBody()).toBe(body);
|
|
});
|
|
it('passes URLSearchParams through', () => {
|
|
const body = new URLSearchParams('foo=1&bar=2');
|
|
expect(baseReq.clone({body}).serializeBody()).toBe(body);
|
|
});
|
|
it('passes strings through', () => {
|
|
const body = 'hello world';
|
|
expect(baseReq.clone({body}).serializeBody()).toBe(body);
|
|
});
|
|
it('serializes arrays as json', () => {
|
|
expect(baseReq.clone({body: ['a', 'b']}).serializeBody()).toBe('["a","b"]');
|
|
});
|
|
it('handles numbers as json', () => {
|
|
expect(baseReq.clone({body: 314159}).serializeBody()).toBe('314159');
|
|
});
|
|
it('handles objects as json', () => {
|
|
const req = baseReq.clone({body: {data: 'test data'}});
|
|
expect(req.serializeBody()).toBe('{"data":"test data"}');
|
|
});
|
|
it('serializes parameters as urlencoded', () => {
|
|
const params = new HttpParams().append('first', 'value').append('second', 'other');
|
|
const withParams = baseReq.clone({body: params});
|
|
expect(withParams.serializeBody()).toEqual('first=value&second=other');
|
|
expect(withParams.detectContentTypeHeader()).toEqual(
|
|
'application/x-www-form-urlencoded;charset=UTF-8',
|
|
);
|
|
});
|
|
});
|
|
describe('parameter handling', () => {
|
|
const baseReq = new HttpRequest('GET', '/test', null);
|
|
const params = new HttpParams({fromString: 'test=true'});
|
|
it('appends parameters to a base URL', () => {
|
|
const req = baseReq.clone({params});
|
|
expect(req.urlWithParams).toEqual('/test?test=true');
|
|
});
|
|
it('appends parameters to a URL with an empty query string', () => {
|
|
const req = baseReq.clone({params, url: '/test?'});
|
|
expect(req.urlWithParams).toEqual('/test?test=true');
|
|
});
|
|
it('appends parameters to a URL with a query string', () => {
|
|
const req = baseReq.clone({params, url: '/test?other=false'});
|
|
expect(req.urlWithParams).toEqual('/test?other=false&test=true');
|
|
});
|
|
it('sets parameters via setParams', () => {
|
|
const req = baseReq.clone({setParams: {'test': 'false'}});
|
|
expect(req.urlWithParams).toEqual('/test?test=false');
|
|
});
|
|
});
|
|
});
|