[PM-13284] Implement method to ensure that we can handle logic when switching the notification improvements feature flag (#11468)

This commit is contained in:
Cesar Gonzalez 2024-10-08 15:47:20 -05:00 committed by GitHub
parent ce871672d2
commit fdfbe66513
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 43 additions and 11 deletions

View File

@ -1,4 +1,5 @@
import { mock, MockProxy } from "jest-mock-extended"; import { mock, MockProxy } from "jest-mock-extended";
import { BehaviorSubject } from "rxjs";
import { CLEAR_NOTIFICATION_LOGIN_DATA_DURATION } from "@bitwarden/common/autofill/constants"; import { CLEAR_NOTIFICATION_LOGIN_DATA_DURATION } from "@bitwarden/common/autofill/constants";
import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service"; import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
@ -24,6 +25,7 @@ import { OverlayNotificationsBackground } from "./overlay-notifications.backgrou
describe("OverlayNotificationsBackground", () => { describe("OverlayNotificationsBackground", () => {
let logService: MockProxy<LogService>; let logService: MockProxy<LogService>;
let getFeatureFlagMock$: BehaviorSubject<boolean>;
let configService: MockProxy<ConfigService>; let configService: MockProxy<ConfigService>;
let notificationBackground: NotificationBackground; let notificationBackground: NotificationBackground;
let getEnableChangedPasswordPromptSpy: jest.SpyInstance; let getEnableChangedPasswordPromptSpy: jest.SpyInstance;
@ -33,7 +35,10 @@ describe("OverlayNotificationsBackground", () => {
beforeEach(async () => { beforeEach(async () => {
jest.useFakeTimers(); jest.useFakeTimers();
logService = mock<LogService>(); logService = mock<LogService>();
configService = mock<ConfigService>(); getFeatureFlagMock$ = new BehaviorSubject(true);
configService = mock<ConfigService>({
getFeatureFlag$: jest.fn().mockReturnValue(getFeatureFlagMock$),
});
notificationBackground = mock<NotificationBackground>(); notificationBackground = mock<NotificationBackground>();
getEnableChangedPasswordPromptSpy = jest getEnableChangedPasswordPromptSpy = jest
.spyOn(notificationBackground, "getEnableChangedPasswordPrompt") .spyOn(notificationBackground, "getEnableChangedPasswordPrompt")

View File

@ -1,4 +1,5 @@
import { Subject, switchMap, timer } from "rxjs"; import { startWith, Subject, Subscription, switchMap, timer } from "rxjs";
import { pairwise } from "rxjs/operators";
import { CLEAR_NOTIFICATION_LOGIN_DATA_DURATION } from "@bitwarden/common/autofill/constants"; import { CLEAR_NOTIFICATION_LOGIN_DATA_DURATION } from "@bitwarden/common/autofill/constants";
import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum"; import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum";
@ -23,6 +24,7 @@ export class OverlayNotificationsBackground implements OverlayNotificationsBackg
private websiteOriginsWithFields: WebsiteOriginsWithFields = new Map(); private websiteOriginsWithFields: WebsiteOriginsWithFields = new Map();
private activeFormSubmissionRequests: ActiveFormSubmissionRequests = new Set(); private activeFormSubmissionRequests: ActiveFormSubmissionRequests = new Set();
private modifyLoginCipherFormData: ModifyLoginCipherFormDataForTab = new Map(); private modifyLoginCipherFormData: ModifyLoginCipherFormDataForTab = new Map();
private featureFlagState$: Subscription;
private clearLoginCipherFormDataSubject: Subject<void> = new Subject(); private clearLoginCipherFormDataSubject: Subject<void> = new Subject();
private notificationFallbackTimeout: number | NodeJS.Timeout | null; private notificationFallbackTimeout: number | NodeJS.Timeout | null;
private readonly formSubmissionRequestMethods: Set<string> = new Set(["POST", "PUT", "PATCH"]); private readonly formSubmissionRequestMethods: Set<string> = new Set(["POST", "PUT", "PATCH"]);
@ -42,19 +44,35 @@ export class OverlayNotificationsBackground implements OverlayNotificationsBackg
* Initialize the overlay notifications background service. * Initialize the overlay notifications background service.
*/ */
async init() { async init() {
const featureFlagActive = await this.configService.getFeatureFlag( this.featureFlagState$ = this.configService
FeatureFlag.NotificationBarAddLoginImprovements, .getFeatureFlag$(FeatureFlag.NotificationBarAddLoginImprovements)
); .pipe(startWith(undefined), pairwise())
if (!featureFlagActive) { .subscribe(([prev, current]) => this.handleInitFeatureFlagChange(prev, current));
return;
}
this.setupExtensionListeners();
this.clearLoginCipherFormDataSubject this.clearLoginCipherFormDataSubject
.pipe(switchMap(() => timer(CLEAR_NOTIFICATION_LOGIN_DATA_DURATION))) .pipe(switchMap(() => timer(CLEAR_NOTIFICATION_LOGIN_DATA_DURATION)))
.subscribe(() => this.modifyLoginCipherFormData.clear()); .subscribe(() => this.modifyLoginCipherFormData.clear());
} }
/**
* Handles enabling/disabling the extension listeners that trigger the
* overlay notifications based on the feature flag state.
*
* @param previousValue - The previous value of the feature flag
* @param currentValue - The current value of the feature flag
*/
private handleInitFeatureFlagChange = (previousValue: boolean, currentValue: boolean) => {
if (previousValue === currentValue) {
return;
}
if (currentValue) {
this.setupExtensionListeners();
return;
}
this.removeExtensionListeners();
};
/** /**
* Handles the response from the content script with the page details. Triggers an initialization * Handles the response from the content script with the page details. Triggers an initialization
* of the add login or change password notification if the conditions are met. * of the add login or change password notification if the conditions are met.
@ -495,11 +513,20 @@ export class OverlayNotificationsBackground implements OverlayNotificationsBackg
* Sets up the listeners for the extension messages and the tab events. * Sets up the listeners for the extension messages and the tab events.
*/ */
private setupExtensionListeners() { private setupExtensionListeners() {
BrowserApi.messageListener("overlay-notifications", this.handleExtensionMessage); BrowserApi.addListener(chrome.runtime.onMessage, this.handleExtensionMessage);
chrome.tabs.onRemoved.addListener(this.handleTabRemoved); chrome.tabs.onRemoved.addListener(this.handleTabRemoved);
chrome.tabs.onUpdated.addListener(this.handleTabUpdated); chrome.tabs.onUpdated.addListener(this.handleTabUpdated);
} }
/**
* Removes the listeners for the extension messages and the tab events.
*/
private removeExtensionListeners() {
BrowserApi.removeListener(chrome.runtime.onMessage, this.handleExtensionMessage);
chrome.tabs.onRemoved.removeListener(this.handleTabRemoved);
chrome.tabs.onUpdated.removeListener(this.handleTabUpdated);
}
/** /**
* Handles messages that are sent to the extension background. * Handles messages that are sent to the extension background.
* *