angular/packages/platform-browser/test/hydration_spec.ts
Matthieu Riegler 7dde42a5df feat(http): allow customization of the HttpTransferCache. (#52029)
`provideClientHydration()` accepts new `HydrationFeature` : `HttpTransferCacheOptions`.

`withHttpTransferCacheOptions` accepts an option object:
* `includeHeaders` : list of headers entries to keep in the cache with the request
* `filter` a callback to determine if a request should be cached
* `includePostRequests`: to include POST requests in the allowed methods

Implements some of the features requested in #50117

PR Close #52029
2023-10-06 12:12:47 -07:00

127 lines
4.6 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.io/license
*/
import {DOCUMENT} from '@angular/common';
import {HttpClient, HttpTransferCacheOptions, provideHttpClient} from '@angular/common/http';
import {HttpTestingController, provideHttpClientTesting} from '@angular/common/http/testing';
import {ApplicationRef, Component, Injectable, ɵSSR_CONTENT_INTEGRITY_MARKER as SSR_CONTENT_INTEGRITY_MARKER} from '@angular/core';
import {TestBed} from '@angular/core/testing';
import {withBody} from '@angular/private/testing';
import {BehaviorSubject} from 'rxjs';
import {provideClientHydration, withNoHttpTransferCache} from '../public_api';
import {withHttpTransferCacheOptions} from '../src/hydration';
describe('provideClientHydration', () => {
@Component({selector: 'test-hydrate-app', template: ''})
class SomeComponent {
}
function makeRequestAndExpectOne(
url: string, body: string, options: HttpTransferCacheOptions|boolean = true): void {
TestBed.inject(HttpClient).get(url, {transferCache: options}).subscribe();
TestBed.inject(HttpTestingController).expectOne(url).flush(body);
}
function makeRequestAndExpectNone(
url: string, options: HttpTransferCacheOptions|boolean = true): void {
TestBed.inject(HttpClient).get(url, {transferCache: options}).subscribe();
TestBed.inject(HttpTestingController).expectNone(url);
}
@Injectable()
class ApplicationRefPatched extends ApplicationRef {
override isStable = new BehaviorSubject<boolean>(false);
}
describe('default', () => {
beforeEach(withBody(
`<!--${SSR_CONTENT_INTEGRITY_MARKER}--><test-hydrate-app></test-hydrate-app>`, () => {
TestBed.resetTestingModule();
TestBed.configureTestingModule({
declarations: [SomeComponent],
providers: [
{provide: DOCUMENT, useFactory: () => document},
{provide: ApplicationRef, useClass: ApplicationRefPatched},
provideClientHydration(),
provideHttpClient(),
provideHttpClientTesting(),
],
});
const appRef = TestBed.inject(ApplicationRef);
appRef.bootstrap(SomeComponent);
}));
it(`should use cached HTTP calls`, () => {
makeRequestAndExpectOne('/test-1', 'foo');
// Do the same call, this time it should served from cache.
makeRequestAndExpectNone('/test-1');
});
});
describe('withNoHttpTransferCache', () => {
beforeEach(withBody(
`<!--${SSR_CONTENT_INTEGRITY_MARKER}--><test-hydrate-app></test-hydrate-app>`, () => {
TestBed.resetTestingModule();
TestBed.configureTestingModule({
declarations: [SomeComponent],
providers: [
{provide: DOCUMENT, useFactory: () => document},
{provide: ApplicationRef, useClass: ApplicationRefPatched},
provideClientHydration(withNoHttpTransferCache()),
provideHttpClient(),
provideHttpClientTesting(),
],
});
const appRef = TestBed.inject(ApplicationRef);
appRef.bootstrap(SomeComponent);
}));
it(`should not cache HTTP calls`, () => {
makeRequestAndExpectOne('/test-1', 'foo', false);
// Do the same call, this time should pass through as cache is disabled.
makeRequestAndExpectOne('/test-1', 'foo');
});
});
describe('withHttpTransferCacheOptions', () => {
beforeEach(withBody(
`<!--${SSR_CONTENT_INTEGRITY_MARKER}--><test-hydrate-app></test-hydrate-app>`, () => {
TestBed.resetTestingModule();
TestBed.configureTestingModule({
declarations: [SomeComponent],
providers: [
{provide: DOCUMENT, useFactory: () => document},
{provide: ApplicationRef, useClass: ApplicationRefPatched},
provideClientHydration(withHttpTransferCacheOptions(
{includePostRequests: true, includeHeaders: ['foo']})),
provideHttpClient(),
provideHttpClientTesting(),
],
});
const appRef = TestBed.inject(ApplicationRef);
appRef.bootstrap(SomeComponent);
}));
it(`should cache HTTP POST calls`, () => {
const url = '/test-1';
const body = 'foo';
TestBed.inject(HttpClient).post(url, body).subscribe();
TestBed.inject(HttpTestingController).expectOne(url).flush(body);
TestBed.inject(HttpClient).post(url, body).subscribe();
TestBed.inject(HttpTestingController).expectNone(url);
});
});
});