mirror of
https://github.com/bitwarden/browser
synced 2026-02-10 05:30:01 +00:00
added testing suite & all expected FFs
This commit is contained in:
@@ -6,7 +6,7 @@
|
||||
<bit-callout type="warning" title="{{ 'warning' | i18n }}">
|
||||
{{ "deleteAccountWarning" | i18n }}
|
||||
</bit-callout>
|
||||
@if (migrationMilestone3) {
|
||||
@if (migrationMilestone4) {
|
||||
<app-user-verification-form-input
|
||||
formControlName="verification"
|
||||
verificationType="server"
|
||||
|
||||
121
apps/desktop/src/auth/delete-account.component.spec.ts
Normal file
121
apps/desktop/src/auth/delete-account.component.spec.ts
Normal file
@@ -0,0 +1,121 @@
|
||||
import { FormBuilder } from "@angular/forms";
|
||||
import { MockProxy, mock } from "jest-mock-extended";
|
||||
|
||||
import { AccountApiService } from "@bitwarden/common/auth/abstractions/account-api.service";
|
||||
import { VerificationWithSecret } from "@bitwarden/common/auth/types/verification";
|
||||
import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
|
||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||
import { ToastService } from "@bitwarden/components";
|
||||
|
||||
import { DeleteAccountComponent } from "./delete-account.component";
|
||||
|
||||
describe("DeleteAccountComponent", () => {
|
||||
let component: DeleteAccountComponent;
|
||||
let i18nService: MockProxy<I18nService>;
|
||||
let formBuilder: FormBuilder;
|
||||
let accountApiService: MockProxy<AccountApiService>;
|
||||
let toastService: MockProxy<ToastService>;
|
||||
let configService: MockProxy<ConfigService>;
|
||||
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
|
||||
i18nService = mock<I18nService>();
|
||||
formBuilder = new FormBuilder();
|
||||
accountApiService = mock<AccountApiService>();
|
||||
toastService = mock<ToastService>();
|
||||
configService = mock<ConfigService>();
|
||||
|
||||
i18nService.t.mockImplementation((key: any) => key);
|
||||
|
||||
component = new DeleteAccountComponent(
|
||||
i18nService,
|
||||
formBuilder,
|
||||
accountApiService,
|
||||
toastService,
|
||||
configService,
|
||||
);
|
||||
});
|
||||
|
||||
describe("submit", () => {
|
||||
const mockVerification: VerificationWithSecret = {
|
||||
type: 0,
|
||||
secret: "masterPassword123",
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
component.deleteForm.patchValue({
|
||||
verification: mockVerification,
|
||||
});
|
||||
});
|
||||
|
||||
describe("when feature flag is enabled", () => {
|
||||
beforeEach(() => {
|
||||
component["migrationMilestone4"] = true;
|
||||
});
|
||||
|
||||
it("should delete account and show success toast on successful deletion", async () => {
|
||||
accountApiService.deleteAccount.mockResolvedValue(undefined);
|
||||
|
||||
await component.submit();
|
||||
|
||||
expect(accountApiService.deleteAccount).toHaveBeenCalledWith(mockVerification);
|
||||
expect(toastService.showToast).toHaveBeenCalledWith({
|
||||
variant: "success",
|
||||
title: "accountDeleted",
|
||||
message: "accountDeletedDesc",
|
||||
});
|
||||
expect(component["invalidSecret"]).toBe(false);
|
||||
});
|
||||
|
||||
it("should set invalidSecret to true when deletion fails", async () => {
|
||||
accountApiService.deleteAccount.mockRejectedValue(new Error("Invalid credentials"));
|
||||
|
||||
await component.submit();
|
||||
|
||||
expect(accountApiService.deleteAccount).toHaveBeenCalledWith(mockVerification);
|
||||
expect(toastService.showToast).not.toHaveBeenCalled();
|
||||
expect(component["invalidSecret"]).toBe(true);
|
||||
});
|
||||
|
||||
it("should reset invalidSecret to false before attempting deletion", async () => {
|
||||
component["invalidSecret"] = true;
|
||||
accountApiService.deleteAccount.mockResolvedValue(undefined);
|
||||
|
||||
await component.submit();
|
||||
|
||||
expect(component["invalidSecret"]).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe("when feature flag is disabled", () => {
|
||||
beforeEach(() => {
|
||||
component["migrationMilestone4"] = false;
|
||||
});
|
||||
|
||||
it("should delete account and show success toast on successful deletion", async () => {
|
||||
accountApiService.deleteAccount.mockResolvedValue(undefined);
|
||||
|
||||
await component.submit();
|
||||
|
||||
expect(accountApiService.deleteAccount).toHaveBeenCalledWith(mockVerification);
|
||||
expect(toastService.showToast).toHaveBeenCalledWith({
|
||||
variant: "success",
|
||||
title: "accountDeleted",
|
||||
message: "accountDeletedDesc",
|
||||
});
|
||||
});
|
||||
|
||||
it("should not set invalidSecret when deletion fails", async () => {
|
||||
const initialInvalidSecret = component["invalidSecret"];
|
||||
accountApiService.deleteAccount.mockRejectedValue(new Error("Invalid credentials"));
|
||||
|
||||
await component.submit();
|
||||
|
||||
expect(accountApiService.deleteAccount).toHaveBeenCalledWith(mockVerification);
|
||||
expect(toastService.showToast).not.toHaveBeenCalled();
|
||||
expect(component["invalidSecret"]).toBe(initialInvalidSecret);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -50,9 +50,9 @@ export class DeleteAccountComponent implements OnInit {
|
||||
protected invalidSecret = false;
|
||||
|
||||
/**
|
||||
* Feature flag for UI Migration Milestone 3
|
||||
* Feature flag for UI Migration Milestone 4
|
||||
*/
|
||||
protected migrationMilestone3 = false;
|
||||
protected migrationMilestone4 = false;
|
||||
|
||||
constructor(
|
||||
private i18nService: I18nService,
|
||||
@@ -63,8 +63,8 @@ export class DeleteAccountComponent implements OnInit {
|
||||
) {}
|
||||
|
||||
async ngOnInit() {
|
||||
this.migrationMilestone3 = await this.configService.getFeatureFlag(
|
||||
FeatureFlag.DesktopUiMigrationMilestone3,
|
||||
this.migrationMilestone4 = await this.configService.getFeatureFlag(
|
||||
FeatureFlag.DesktopUiMigrationMilestone4,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -78,8 +78,8 @@ export class DeleteAccountComponent implements OnInit {
|
||||
|
||||
submit = async () => {
|
||||
try {
|
||||
if (this.migrationMilestone3) {
|
||||
this.invalidSecret = false; // Reset error state before attempting
|
||||
if (this.migrationMilestone4) {
|
||||
this.invalidSecret = false;
|
||||
}
|
||||
const verification = this.deleteForm.get("verification").value;
|
||||
await this.accountApiService.deleteAccount(verification);
|
||||
@@ -89,7 +89,7 @@ export class DeleteAccountComponent implements OnInit {
|
||||
message: this.i18nService.t("accountDeletedDesc"),
|
||||
});
|
||||
} catch {
|
||||
if (this.migrationMilestone3) {
|
||||
if (this.migrationMilestone4) {
|
||||
this.invalidSecret = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -77,8 +77,9 @@ export enum FeatureFlag {
|
||||
|
||||
/* Desktop */
|
||||
DesktopUiMigrationMilestone1 = "desktop-ui-migration-milestone-1",
|
||||
DesktopUiMigrationMilestone3 = "desktop-ui-migration-milestone-3",
|
||||
DesktopUiMigrationMilestone2 = "desktop-ui-migration-milestone-2",
|
||||
DesktopUiMigrationMilestone3 = "desktop-ui-migration-milestone-3",
|
||||
DesktopUiMigrationMilestone4 = "desktop-ui-migration-milestone-4",
|
||||
|
||||
/* UIF */
|
||||
RouterFocusManagement = "router-focus-management",
|
||||
@@ -168,8 +169,9 @@ export const DefaultFeatureFlagValue = {
|
||||
|
||||
/* Desktop */
|
||||
[FeatureFlag.DesktopUiMigrationMilestone1]: FALSE,
|
||||
[FeatureFlag.DesktopUiMigrationMilestone3]: FALSE,
|
||||
[FeatureFlag.DesktopUiMigrationMilestone2]: FALSE,
|
||||
[FeatureFlag.DesktopUiMigrationMilestone3]: FALSE,
|
||||
[FeatureFlag.DesktopUiMigrationMilestone4]: FALSE,
|
||||
|
||||
/* UIF */
|
||||
[FeatureFlag.RouterFocusManagement]: FALSE,
|
||||
@@ -186,12 +188,6 @@ export function getFeatureFlagValue<Flag extends FeatureFlag>(
|
||||
serverConfig: ServerConfig | null,
|
||||
flag: Flag,
|
||||
) {
|
||||
if (flag === FeatureFlag.DesktopUiMigrationMilestone1) {
|
||||
return true;
|
||||
}
|
||||
if (flag === FeatureFlag.DesktopUiMigrationMilestone3) {
|
||||
return true;
|
||||
}
|
||||
if (serverConfig?.featureStates == null || serverConfig.featureStates[flag] == null) {
|
||||
return DefaultFeatureFlagValue[flag];
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user