1
0
mirror of https://github.com/bitwarden/browser synced 2025-12-06 00:13:28 +00:00

[PM-29256] - add feature flag to vault spotlight (#17842)

* add feature flag to vault spotlight

* fix spec
This commit is contained in:
Jordan Aasen
2025-12-05 10:45:47 -08:00
committed by GitHub
parent 7cba6f4170
commit 834caa0c88
3 changed files with 26 additions and 8 deletions

View File

@@ -180,7 +180,7 @@ describe("VaultV2Component", () => {
const nudgesSvc = { const nudgesSvc = {
showNudgeSpotlight$: jest.fn().mockImplementation((_type: NudgeType) => of(false)), showNudgeSpotlight$: jest.fn().mockImplementation((_type: NudgeType) => of(false)),
dismissNudge: jest.fn().mockResolvedValue(undefined), dismissNudge: jest.fn().mockResolvedValue(undefined),
} as Partial<NudgesService>; };
const dialogSvc = {} as Partial<DialogService>; const dialogSvc = {} as Partial<DialogService>;
@@ -209,6 +209,10 @@ describe("VaultV2Component", () => {
.mockResolvedValue(new Date(Date.now() - 8 * 24 * 60 * 60 * 1000)), // 8 days ago .mockResolvedValue(new Date(Date.now() - 8 * 24 * 60 * 60 * 1000)), // 8 days ago
}; };
const configSvc = {
getFeatureFlag$: jest.fn().mockImplementation((_flag: string) => of(false)),
};
beforeEach(async () => { beforeEach(async () => {
jest.clearAllMocks(); jest.clearAllMocks();
await TestBed.configureTestingModule({ await TestBed.configureTestingModule({
@@ -256,9 +260,7 @@ describe("VaultV2Component", () => {
{ provide: StateProvider, useValue: mock<StateProvider>() }, { provide: StateProvider, useValue: mock<StateProvider>() },
{ {
provide: ConfigService, provide: ConfigService,
useValue: { useValue: configSvc,
getFeatureFlag$: (_: string) => of(false),
},
}, },
{ {
provide: SearchService, provide: SearchService,
@@ -453,7 +455,9 @@ describe("VaultV2Component", () => {
hasPremiumFromAnySource$.next(false); hasPremiumFromAnySource$.next(false);
(nudgesSvc.showNudgeSpotlight$ as jest.Mock).mockImplementation((type: NudgeType) => configSvc.getFeatureFlag$.mockImplementation((_flag: string) => of(true));
nudgesSvc.showNudgeSpotlight$.mockImplementation((type: NudgeType) =>
of(type === NudgeType.PremiumUpgrade), of(type === NudgeType.PremiumUpgrade),
); );
@@ -482,9 +486,11 @@ describe("VaultV2Component", () => {
})); }));
it("renders Empty-Vault spotlight when vaultState is Empty and nudge is on", fakeAsync(() => { it("renders Empty-Vault spotlight when vaultState is Empty and nudge is on", fakeAsync(() => {
configSvc.getFeatureFlag$.mockImplementation((_flag: string) => of(false));
itemsSvc.emptyVault$.next(true); itemsSvc.emptyVault$.next(true);
(nudgesSvc.showNudgeSpotlight$ as jest.Mock).mockImplementation((type: NudgeType) => { nudgesSvc.showNudgeSpotlight$.mockImplementation((type: NudgeType) => {
return of(type === NudgeType.EmptyVaultNudge); return of(type === NudgeType.EmptyVaultNudge);
}); });

View File

@@ -137,6 +137,10 @@ export class VaultV2Component implements OnInit, AfterViewInit, OnDestroy {
FeatureFlag.VaultLoadingSkeletons, FeatureFlag.VaultLoadingSkeletons,
); );
protected premiumSpotlightFeatureFlag$ = this.configService.getFeatureFlag$(
FeatureFlag.BrowserPremiumSpotlight,
);
private showPremiumNudgeSpotlight$ = this.activeUserId$.pipe( private showPremiumNudgeSpotlight$ = this.activeUserId$.pipe(
switchMap((userId) => this.nudgesService.showNudgeSpotlight$(NudgeType.PremiumUpgrade, userId)), switchMap((userId) => this.nudgesService.showNudgeSpotlight$(NudgeType.PremiumUpgrade, userId)),
); );
@@ -164,6 +168,7 @@ export class VaultV2Component implements OnInit, AfterViewInit, OnDestroy {
); );
protected showPremiumSpotlight$ = combineLatest([ protected showPremiumSpotlight$ = combineLatest([
this.premiumSpotlightFeatureFlag$,
this.showPremiumNudgeSpotlight$, this.showPremiumNudgeSpotlight$,
this.showHasItemsVaultSpotlight$, this.showHasItemsVaultSpotlight$,
this.hasPremium$, this.hasPremium$,
@@ -171,8 +176,13 @@ export class VaultV2Component implements OnInit, AfterViewInit, OnDestroy {
this.accountAgeInDays$, this.accountAgeInDays$,
]).pipe( ]).pipe(
map( map(
([showPremiumNudge, showHasItemsNudge, hasPremium, count, age]) => ([featureFlagEnabled, showPremiumNudge, showHasItemsNudge, hasPremium, count, age]) =>
showPremiumNudge && !showHasItemsNudge && !hasPremium && count >= 5 && age >= 7, featureFlagEnabled &&
showPremiumNudge &&
!showHasItemsNudge &&
!hasPremium &&
count >= 5 &&
age >= 7,
), ),
shareReplay({ bufferSize: 1, refCount: true }), shareReplay({ bufferSize: 1, refCount: true }),
); );

View File

@@ -62,6 +62,7 @@ export enum FeatureFlag {
AutofillConfirmation = "pm-25083-autofill-confirm-from-search", AutofillConfirmation = "pm-25083-autofill-confirm-from-search",
RiskInsightsForPremium = "pm-23904-risk-insights-for-premium", RiskInsightsForPremium = "pm-23904-risk-insights-for-premium",
VaultLoadingSkeletons = "pm-25081-vault-skeleton-loaders", VaultLoadingSkeletons = "pm-25081-vault-skeleton-loaders",
BrowserPremiumSpotlight = "pm-23384-browser-premium-spotlight",
/* Platform */ /* Platform */
IpcChannelFramework = "ipc-channel-framework", IpcChannelFramework = "ipc-channel-framework",
@@ -119,6 +120,7 @@ export const DefaultFeatureFlagValue = {
[FeatureFlag.AutofillConfirmation]: FALSE, [FeatureFlag.AutofillConfirmation]: FALSE,
[FeatureFlag.RiskInsightsForPremium]: FALSE, [FeatureFlag.RiskInsightsForPremium]: FALSE,
[FeatureFlag.VaultLoadingSkeletons]: FALSE, [FeatureFlag.VaultLoadingSkeletons]: FALSE,
[FeatureFlag.BrowserPremiumSpotlight]: FALSE,
/* Auth */ /* Auth */
[FeatureFlag.PM23801_PrefetchPasswordPrelogin]: FALSE, [FeatureFlag.PM23801_PrefetchPasswordPrelogin]: FALSE,