Целью этого перехватчика является повторная отправка запроса, когда сервер запрашивает ключ-капчу.
Но его можно использовать при обновлении токена jwt.
Перехватчик работает нормально, но я не могу объяснить, почему тест не пройден.
Поток никогда не перейдет в httpClient.get ('/ error'). Subscribe (), если код ответа!= 200.
Вот ссылка на воспроизводимый демонстрационный пример: https://stackblitz.com/edit/angular-testing-template-mfqwpj?embed=1&file=app/interceptor.spec.ts
import {HttpEvent, HttpHandler, HttpInterceptor, HttpRequest} from '@angular/common/http';
import {Observable} from 'rxjs';
import {Injectable} from '@angular/core';
import {catchError, switchMap} from 'rxjs/operators';
import {CaptchaHeader, CaptchaV2Service} from 'century-lib';
@Injectable({
providedIn: 'root'
})
export class CaptchaInterceptor implements HttpInterceptor {
constructor(private captchaService: CaptchaV2Service) {
}
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
return next.handle(req).pipe(
catchError(err => {
if (!this.captchaIsRequired(err)) {
return;
}
return this.captchaService.getCaptchaKey().pipe(
switchMap((key) => {
const newReq = this.applyCaptchaKey(req, key);
return next.handle(newReq);
})
);
})
);
}
applyCaptchaKey(req, key) {
return req.clone({
headers: req.headers.set('Captcha-Token', key)
});
}
private captchaIsRequired(error) {
return (error.status === 400 && error.headers.get('Captcha-Status') === 'required');
}
}
Тест:
import {async, TestBed} from '@angular/core/testing';
import {HttpClientTestingModule, HttpTestingController} from '@angular/common/http/testing';
import {CaptchaV2Service} from 'century-lib';
import {HTTP_INTERCEPTORS, HttpClient, HttpHeaders} from '@angular/common/http';
import {CaptchaInterceptor} from './captcha.interceptor';
import {EventEmitter} from '@angular/core';
class MockCaptchaService {
valid = new EventEmitter<string>();
reset = new EventEmitter<boolean>();
getCaptchaKey() {
setTimeout(() => {
this.valid.emit('captcha-key');
}, 500);
return this.valid;
}
}
describe('Captcha interceptor', () => {
let httpClient: HttpClient;
let httpMock: HttpTestingController;
let interceptor: CaptchaInterceptor;
beforeEach(() => {
TestBed.configureTestingModule({
imports: [HttpClientTestingModule],
providers: [
CaptchaInterceptor,
{provide: CaptchaV2Service, useValue: new MockCaptchaService()},
{provide: HTTP_INTERCEPTORS, useClass: CaptchaInterceptor, multi: true},
]
});
httpClient = TestBed.get(HttpClient);
httpMock = TestBed.get(HttpTestingController);
interceptor = TestBed.get(CaptchaInterceptor);
});
it('should construct', async(() => {
expect(interceptor).toBeDefined();
}));
it('Should interrogate the captchaService when service returns Captcha-Required', async(() => {
httpClient.get('/error').subscribe(() => {
}, () => {
});
const req = httpMock.expectOne('/error');
req.error(new ErrorEvent('Captcha Error'), {
status: 400,
statusText: 'Captcha-Error',
headers: new HttpHeaders().set('Captcha-Status', 'required')
});
expect(req.request.headers.get('Captcha-Token')).toBe('captcha-key');
httpMock.verify();
}));
afterEach(() => {
TestBed.resetTestingModule();
});
});