diff --git a/libs/auth/src/angular/two-factor-auth/child-components/two-factor-auth-email/two-factor-auth-component-email-cache.service.spec.ts b/libs/auth/src/angular/two-factor-auth/child-components/two-factor-auth-email/two-factor-auth-component-email-cache.service.spec.ts new file mode 100644 index 00000000000..a697426fc4c --- /dev/null +++ b/libs/auth/src/angular/two-factor-auth/child-components/two-factor-auth-email/two-factor-auth-component-email-cache.service.spec.ts @@ -0,0 +1,163 @@ +import { TestBed } from "@angular/core/testing"; +import { mock, MockProxy } from "jest-mock-extended"; +import { BehaviorSubject } from "rxjs"; + +import { ViewCacheService } from "@bitwarden/angular/platform/abstractions/view-cache.service"; +import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum"; +import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service"; + +import { + TwoFactorAuthEmailCache, + TwoFactorAuthComponentEmailCacheService, +} from "./two-factor-auth-component-email-cache.service"; + +describe("TwoFactorAuthEmailCache", () => { + describe("fromJSON", () => { + it("returns null when input is null", () => { + const result = TwoFactorAuthComponentEmailCache.fromJSON(null as any); + expect(result).toBeNull(); + }); + + it("creates a TwoFactorAuthEmailCache instance from valid JSON", () => { + const jsonData = { emailSent: true }; + const result = TwoFactorAuthEmailCache.fromJSON(jsonData); + + expect(result).not.toBeNull(); + expect(result).toBeInstanceOf(TwoFactorAuthEmailCache); + expect(result?.emailSent).toBe(true); + }); + }); +}); + +describe("TwoFactorAuthComponentEmailCacheService", () => { + let service: TwoFactorAuthComponentEmailCacheService; + let mockViewCacheService: MockProxy; + let mockConfigService: MockProxy; + let cacheData: BehaviorSubject; + let mockSignal: any; + + beforeEach(() => { + mockViewCacheService = mock(); + mockConfigService = mock(); + cacheData = new BehaviorSubject(null); + mockSignal = jest.fn(() => cacheData.getValue()); + mockSignal.set = jest.fn((value: TwoFactorAuthEmailCache | null) => cacheData.next(value)); + mockViewCacheService.signal.mockReturnValue(mockSignal); + + TestBed.configureTestingModule({ + providers: [ + TwoFactorAuthComponentEmailCacheService, + { provide: ViewCacheService, useValue: mockViewCacheService }, + { provide: ConfigService, useValue: mockConfigService }, + ], + }); + + service = TestBed.inject(TwoFactorAuthComponentEmailCacheService); + }); + + it("creates the service", () => { + expect(service).toBeTruthy(); + }); + + describe("init", () => { + it("sets featureEnabled to true when flag is enabled", async () => { + mockConfigService.getFeatureFlag.mockResolvedValue(true); + + await service.init(); + + expect(mockConfigService.getFeatureFlag).toHaveBeenCalledWith( + FeatureFlag.PM9115_TwoFactorExtensionDataPersistence, + ); + + service.cacheData({ emailSent: true }); + expect(mockSignal.set).toHaveBeenCalled(); + }); + + it("sets featureEnabled to false when flag is disabled", async () => { + mockConfigService.getFeatureFlag.mockResolvedValue(false); + + await service.init(); + + expect(mockConfigService.getFeatureFlag).toHaveBeenCalledWith( + FeatureFlag.PM9115_TwoFactorExtensionDataPersistence, + ); + + service.cacheData({ emailSent: true }); + expect(mockSignal.set).not.toHaveBeenCalled(); + }); + }); + + describe("cacheData", () => { + beforeEach(async () => { + mockConfigService.getFeatureFlag.mockResolvedValue(true); + await service.init(); + }); + + it("caches email sent state when feature is enabled", () => { + service.cacheData({ emailSent: true }); + + expect(mockSignal.set).toHaveBeenCalledWith({ + emailSent: true, + }); + }); + + it("does not cache data when feature is disabled", async () => { + mockConfigService.getFeatureFlag.mockResolvedValue(false); + await service.init(); + + service.cacheData({ emailSent: true }); + + expect(mockSignal.set).not.toHaveBeenCalled(); + }); + }); + + describe("clearCachedData", () => { + beforeEach(async () => { + mockConfigService.getFeatureFlag.mockResolvedValue(true); + await service.init(); + }); + + it("clears cached data when feature is enabled", () => { + service.clearCachedData(); + + expect(mockSignal.set).toHaveBeenCalledWith(null); + }); + + it("does not clear cached data when feature is disabled", async () => { + mockConfigService.getFeatureFlag.mockResolvedValue(false); + await service.init(); + + service.clearCachedData(); + + expect(mockSignal.set).not.toHaveBeenCalled(); + }); + }); + + describe("getCachedData", () => { + beforeEach(async () => { + mockConfigService.getFeatureFlag.mockResolvedValue(true); + await service.init(); + }); + + it("returns cached data when feature is enabled", () => { + const testData = new TwoFactorAuthEmailCache(); + testData.emailSent = true; + cacheData.next(testData); + + const result = service.getCachedData(); + + expect(result).toEqual(testData); + expect(mockSignal).toHaveBeenCalled(); + }); + + it("returns null when feature is disabled", async () => { + mockConfigService.getFeatureFlag.mockResolvedValue(false); + await service.init(); + + const result = service.getCachedData(); + + expect(result).toBeNull(); + expect(mockSignal).not.toHaveBeenCalled(); + }); + }); +}); diff --git a/libs/auth/src/angular/two-factor-auth/child-components/two-factor-auth-email/two-factor-auth-email-component-cache.service.spec.ts b/libs/auth/src/angular/two-factor-auth/child-components/two-factor-auth-email/two-factor-auth-email-component-cache.service.spec.ts index 15c323ed976..1613c0e4af8 100644 --- a/libs/auth/src/angular/two-factor-auth/child-components/two-factor-auth-email/two-factor-auth-email-component-cache.service.spec.ts +++ b/libs/auth/src/angular/two-factor-auth/child-components/two-factor-auth-email/two-factor-auth-email-component-cache.service.spec.ts @@ -7,23 +7,23 @@ import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum"; import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service"; import { - TwoFactorAuthEmailCache, + TwoFactorAuthEmailComponentCache, TwoFactorAuthEmailComponentCacheService, } from "./two-factor-auth-email-component-cache.service"; -describe("TwoFactorAuthEmailCache", () => { +describe("TwoFactorAuthEmailComponentCache", () => { describe("fromJSON", () => { it("returns null when input is null", () => { - const result = TwoFactorAuthEmailCache.fromJSON(null as any); + const result = TwoFactorAuthEmailComponentCache.fromJSON(null as any); expect(result).toBeNull(); }); it("creates a TwoFactorAuthEmailCache instance from valid JSON", () => { const jsonData = { emailSent: true }; - const result = TwoFactorAuthEmailCache.fromJSON(jsonData); + const result = TwoFactorAuthEmailComponentCache.fromJSON(jsonData); expect(result).not.toBeNull(); - expect(result).toBeInstanceOf(TwoFactorAuthEmailCache); + expect(result).toBeInstanceOf(TwoFactorAuthEmailComponentCache); expect(result?.emailSent).toBe(true); }); }); @@ -33,15 +33,17 @@ describe("TwoFactorAuthEmailComponentCacheService", () => { let service: TwoFactorAuthEmailComponentCacheService; let mockViewCacheService: MockProxy; let mockConfigService: MockProxy; - let cacheData: BehaviorSubject; + let cacheData: BehaviorSubject; let mockSignal: any; beforeEach(() => { mockViewCacheService = mock(); mockConfigService = mock(); - cacheData = new BehaviorSubject(null); + cacheData = new BehaviorSubject(null); mockSignal = jest.fn(() => cacheData.getValue()); - mockSignal.set = jest.fn((value: TwoFactorAuthEmailCache | null) => cacheData.next(value)); + mockSignal.set = jest.fn((value: TwoFactorAuthEmailComponentCache | null) => + cacheData.next(value), + ); mockViewCacheService.signal.mockReturnValue(mockSignal); TestBed.configureTestingModule({ @@ -140,7 +142,7 @@ describe("TwoFactorAuthEmailComponentCacheService", () => { }); it("returns cached data when feature is enabled", () => { - const testData = new TwoFactorAuthEmailCache(); + const testData = new TwoFactorAuthEmailComponentCache(); testData.emailSent = true; cacheData.next(testData); diff --git a/libs/auth/src/angular/two-factor-auth/child-components/two-factor-auth-email/two-factor-auth-email-component-cache.service.ts b/libs/auth/src/angular/two-factor-auth/child-components/two-factor-auth-email/two-factor-auth-email-component-cache.service.ts index 84a19615031..e32b6cd1385 100644 --- a/libs/auth/src/angular/two-factor-auth/child-components/two-factor-auth-email/two-factor-auth-email-component-cache.service.ts +++ b/libs/auth/src/angular/two-factor-auth/child-components/two-factor-auth-email/two-factor-auth-email-component-cache.service.ts @@ -13,16 +13,18 @@ export const TWO_FACTOR_AUTH_EMAIL_COMPONENT_CACHE_KEY = "two-factor-auth-email- /** * Cache model for the email two factor auth component. */ -export class TwoFactorAuthEmailCache { +export class TwoFactorAuthEmailComponentCache { emailSent: boolean = false; - static fromJSON(obj: Partial>): TwoFactorAuthEmailCache | null { + static fromJSON( + obj: Partial>, + ): TwoFactorAuthEmailComponentCache | null { // Return null if the cache is empty if (obj == null) { return null; } - return Object.assign(new TwoFactorAuthEmailCache(), obj); + return Object.assign(new TwoFactorAuthEmailComponentCache(), obj); } } @@ -40,11 +42,11 @@ export class TwoFactorAuthEmailComponentCacheService { /** * Signal for the cached email state. */ - private emailCache: WritableSignal = - this.viewCacheService.signal({ + private emailCache: WritableSignal = + this.viewCacheService.signal({ key: TWO_FACTOR_AUTH_EMAIL_COMPONENT_CACHE_KEY, initialValue: null, - deserializer: TwoFactorAuthEmailCache.fromJSON, + deserializer: TwoFactorAuthEmailComponentCache.fromJSON, }); /** @@ -66,7 +68,7 @@ export class TwoFactorAuthEmailComponentCacheService { this.emailCache.set({ emailSent: data.emailSent, - } as TwoFactorAuthEmailCache); + } as TwoFactorAuthEmailComponentCache); } /** @@ -83,7 +85,7 @@ export class TwoFactorAuthEmailComponentCacheService { /** * Get whether the email has been sent. */ - getCachedData(): TwoFactorAuthEmailCache | null { + getCachedData(): TwoFactorAuthEmailComponentCache | null { if (!this.featureEnabled) { return null; }