Skip to content

Commit b2b0eb6

Browse files
committed
WEB-840: Implement Unit Test Suite for AuthenticationInterceptor
1 parent abf9bac commit b2b0eb6

File tree

1 file changed

+181
-0
lines changed

1 file changed

+181
-0
lines changed
Lines changed: 181 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,181 @@
1+
/**
2+
* Copyright since 2025 Mifos Initiative
3+
*
4+
* This Source Code Form is subject to the terms of the Mozilla Public
5+
* License, v. 2.0. If a copy of the MPL was not distributed with this
6+
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
7+
*/
8+
9+
import { TestBed } from '@angular/core/testing';
10+
import { HttpTestingController, provideHttpClientTesting } from '@angular/common/http/testing';
11+
import { provideHttpClient, withInterceptorsFromDi, HTTP_INTERCEPTORS, HttpClient } from '@angular/common/http';
12+
import { firstValueFrom } from 'rxjs';
13+
import { describe, it, expect, beforeEach, afterEach } from '@jest/globals';
14+
15+
import { AuthenticationInterceptor } from './authentication.interceptor';
16+
import { SettingsService } from 'app/settings/settings.service';
17+
import { environment } from 'environments/environment';
18+
19+
describe('AuthenticationInterceptor', () => {
20+
let interceptor: AuthenticationInterceptor;
21+
let httpMock: HttpTestingController;
22+
let http: HttpClient;
23+
24+
const mockSettingsService: { tenantIdentifier: string | null } = {
25+
tenantIdentifier: null
26+
};
27+
28+
beforeEach(() => {
29+
TestBed.configureTestingModule({
30+
providers: [
31+
AuthenticationInterceptor,
32+
provideHttpClient(withInterceptorsFromDi()),
33+
provideHttpClientTesting(),
34+
{ provide: SettingsService, useValue: mockSettingsService },
35+
{ provide: HTTP_INTERCEPTORS, useExisting: AuthenticationInterceptor, multi: true }]
36+
});
37+
interceptor = TestBed.inject(AuthenticationInterceptor);
38+
httpMock = TestBed.inject(HttpTestingController);
39+
http = TestBed.inject(HttpClient);
40+
});
41+
42+
afterEach(() => {
43+
httpMock.verify();
44+
interceptor.removeAuthorization();
45+
interceptor.removeTwoFactorAuthorization();
46+
mockSettingsService.tenantIdentifier = null;
47+
});
48+
49+
describe('intercept', () => {
50+
it('should set Fineract-Platform-TenantId on internal requests', async () => {
51+
const resultPromise = firstValueFrom(http.get('/clients'));
52+
53+
const req = httpMock.expectOne((r) => r.url === '/clients' && r.method === 'GET');
54+
expect(req.request.headers.get('Fineract-Platform-TenantId')).toBe(environment.fineractPlatformTenantId);
55+
56+
req.flush([]);
57+
await resultPromise;
58+
});
59+
60+
it('should use custom tenant from SettingsService when set', async () => {
61+
mockSettingsService.tenantIdentifier = 'custom-tenant';
62+
const resultPromise = firstValueFrom(http.get('/clients'));
63+
64+
const req = httpMock.expectOne((r) => r.url === '/clients' && r.method === 'GET');
65+
expect(req.request.headers.get('Fineract-Platform-TenantId')).toBe('custom-tenant');
66+
67+
req.flush([]);
68+
await resultPromise;
69+
});
70+
71+
it('should pass external URLs through without Fineract headers', async () => {
72+
const resultPromise = firstValueFrom(http.get('https://api.external.com/data'));
73+
74+
const req = httpMock.expectOne((r) => r.url === 'https://api.external.com/data' && r.method === 'GET');
75+
expect(req.request.headers.has('Fineract-Platform-TenantId')).toBe(false);
76+
77+
req.flush({});
78+
await resultPromise;
79+
});
80+
81+
it('should include Authorization header on requests when previously set', async () => {
82+
interceptor.setAuthorizationToken('dGVzdDp0ZXN0');
83+
const resultPromise = firstValueFrom(http.get('/clients'));
84+
85+
const req = httpMock.expectOne((r) => r.url === '/clients' && r.method === 'GET');
86+
expect(req.request.headers.get('Authorization')).toBe('Basic dGVzdDp0ZXN0');
87+
88+
req.flush([]);
89+
await resultPromise;
90+
});
91+
});
92+
93+
describe('setAuthorizationToken', () => {
94+
it('should set Basic prefix when OAuth is disabled', async () => {
95+
const originalOAuth = environment.oauth.enabled;
96+
try {
97+
environment.oauth.enabled = false;
98+
interceptor.setAuthorizationToken('dGVzdDp0ZXN0');
99+
100+
const resultPromise = firstValueFrom(http.get('/clients'));
101+
const req = httpMock.expectOne((r) => r.url === '/clients' && r.method === 'GET');
102+
expect(req.request.headers.get('Authorization')).toBe('Basic dGVzdDp0ZXN0');
103+
104+
req.flush([]);
105+
await resultPromise;
106+
} finally {
107+
environment.oauth.enabled = originalOAuth;
108+
}
109+
});
110+
111+
it('should set Bearer prefix when OAuth is enabled', async () => {
112+
const originalOAuth = environment.oauth.enabled;
113+
try {
114+
environment.oauth.enabled = true;
115+
interceptor.setAuthorizationToken('my-oauth-token');
116+
117+
const resultPromise = firstValueFrom(http.get('/clients'));
118+
const req = httpMock.expectOne((r) => r.url === '/clients' && r.method === 'GET');
119+
expect(req.request.headers.get('Authorization')).toBe('Bearer my-oauth-token');
120+
121+
req.flush([]);
122+
await resultPromise;
123+
} finally {
124+
environment.oauth.enabled = originalOAuth;
125+
}
126+
});
127+
});
128+
129+
describe('Two-Factor Authentication', () => {
130+
it('should set Fineract-Platform-TFA-Token header', async () => {
131+
interceptor.setTwoFactorAccessToken('tfa-token-123');
132+
const resultPromise = firstValueFrom(http.get('/clients'));
133+
134+
const req = httpMock.expectOne((r) => r.url === '/clients' && r.method === 'GET');
135+
expect(req.request.headers.get('Fineract-Platform-TFA-Token')).toBe('tfa-token-123');
136+
137+
req.flush([]);
138+
await resultPromise;
139+
});
140+
141+
it('should remove TFA header after removeTwoFactorAuthorization', async () => {
142+
interceptor.setTwoFactorAccessToken('tfa-token-123');
143+
interceptor.removeTwoFactorAuthorization();
144+
145+
const resultPromise = firstValueFrom(http.get('/clients'));
146+
const req = httpMock.expectOne((r) => r.url === '/clients' && r.method === 'GET');
147+
expect(req.request.headers.has('Fineract-Platform-TFA-Token')).toBe(false);
148+
149+
req.flush([]);
150+
await resultPromise;
151+
});
152+
});
153+
154+
describe('removeAuthorization / removeAuthorizationTenant', () => {
155+
it('should remove only Authorization header and keep tenant', async () => {
156+
interceptor.setAuthorizationToken('dGVzdDp0ZXN0');
157+
interceptor.removeAuthorization();
158+
159+
const resultPromise = firstValueFrom(http.get('/clients'));
160+
const req = httpMock.expectOne((r) => r.url === '/clients' && r.method === 'GET');
161+
expect(req.request.headers.has('Authorization')).toBe(false);
162+
expect(req.request.headers.has('Fineract-Platform-TenantId')).toBe(true);
163+
164+
req.flush([]);
165+
await resultPromise;
166+
});
167+
168+
it('should remove both Authorization and tenant headers', async () => {
169+
interceptor.setAuthorizationToken('dGVzdDp0ZXN0');
170+
interceptor.removeAuthorizationTenant();
171+
172+
const resultPromise = firstValueFrom(http.get('/clients'));
173+
const req = httpMock.expectOne((r) => r.url === '/clients' && r.method === 'GET');
174+
expect(req.request.headers.has('Authorization')).toBe(false);
175+
expect(req.request.headers.has('Fineract-Platform-TenantId')).toBe(false);
176+
177+
req.flush([]);
178+
await resultPromise;
179+
});
180+
});
181+
});

0 commit comments

Comments
 (0)