fanavaran rate bugs fixed + sms of claimId and claimNo added

This commit is contained in:
2026-08-02 11:33:24 +03:30
parent 86f8b829fd
commit 8f66502c49
10 changed files with 1205 additions and 438 deletions

View File

@@ -0,0 +1,104 @@
import { FanavaranAuthService } from "./fanavaran-auth.service";
describe("FanavaranAuthService", () => {
it("detects Fanavaran transient try-later messages", () => {
expect(
FanavaranAuthService.isTransientTryLaterError(
"کد پیگیری خطا: 10573755\r\n1405/05/1016:56:16:276\r\n.لطفا پس از چند لحظه مجدد تلاش فرمایید.",
),
).toBe(true);
expect(
FanavaranAuthService.isTransientTryLaterError(
"فیلد شماره بيمه نامه ضروری میباشد",
),
).toBe(false);
});
it("caches token and single-flights concurrent logins", async () => {
const http = {
post: jest.fn(),
};
const audit = {
recordStep: jest.fn().mockResolvedValue(undefined),
extractErrorMessage: (e: unknown) =>
e instanceof Error ? e.message : String(e),
sanitizeErrorDetails: () => ({}),
formatErrorWithTrackingCode: (m: string) => m,
};
let loginCalls = 0;
http.post.mockImplementation((url: string) => {
if (url.includes("GetAppToken")) {
return {
toPromise: undefined,
pipe: undefined,
subscribe: undefined,
// firstValueFrom uses Observable — mock as Observable-like via rxjs
};
}
return {};
});
// Use real firstValueFrom path by mocking httpService.post to return an Observable
const { of, delay } = await import("rxjs");
http.post.mockImplementation((url: string) => {
if (url.includes("GetAppToken")) {
return of({
status: 200,
headers: { apptoken: "app-1" },
data: {},
});
}
loginCalls += 1;
return of({
status: 200,
headers: { authenticationtoken: "auth-1" },
data: {},
}).pipe(delay(20));
});
const service = new FanavaranAuthService(http as any, audit as any);
const [a, b, c] = await Promise.all([
service.getAuthenticationToken("parsian"),
service.getAuthenticationToken("parsian"),
service.getAuthenticationToken("parsian"),
]);
expect(a).toBe("auth-1");
expect(b).toBe("auth-1");
expect(c).toBe("auth-1");
expect(loginCalls).toBe(1);
// Cache hit — no extra login
await service.getAuthenticationToken("parsian");
expect(loginCalls).toBe(1);
});
it("enters tenant backoff on try-later errors", () => {
const service = new FanavaranAuthService({} as any, {} as any);
service.registerFailure(
"parsian",
"کد پیگیری خطا: 1\r\n.لطفا پس از چند لحظه مجدد تلاش فرمایید.",
);
expect(service.isInBackoff("parsian")).toBe(true);
expect(() => service.assertNotInBackoff("parsian")).toThrow(
/backoff/i,
);
});
it("computes next Asia/Tehran midnight expiry after now", () => {
// 2026-08-02 10:00:00 UTC ≈ 13:30 Tehran (UTC+3:30) → same calendar day midnight
const now = Date.parse("2026-08-02T10:00:00.000Z");
const expiry = FanavaranAuthService.getNextMidnightExpiryMs(now);
expect(expiry).toBeGreaterThan(now);
// Must land within ~14h (before next Tehran midnight)
expect(expiry - now).toBeLessThanOrEqual(24 * 60 * 60 * 1000);
expect(expiry - now).toBeGreaterThan(0);
// Just after Tehran midnight: 2026-08-01 20:30:01 UTC = 2026-08-02 00:00:01 Tehran
const justAfterMidnight = Date.parse("2026-08-01T20:30:01.000Z");
const next = FanavaranAuthService.getNextMidnightExpiryMs(justAfterMidnight);
expect(next - justAfterMidnight).toBeGreaterThan(23 * 60 * 60 * 1000);
});
});