Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import { TestBed } from "@angular/core/testing";
import { RouterStateSnapshot } from "@angular/router";

import { VaultV2Component } from "../components/vault-v2/vault-v2.component";
import { VaultPopupItemsService } from "../services/vault-popup-items.service";
import { VaultPopupListFiltersService } from "../services/vault-popup-list-filters.service";

import { clearVaultStateGuard } from "./clear-vault-state.guard";

describe("clearVaultStateGuard", () => {
let applyFilterSpy: jest.Mock;
let resetFilterFormSpy: jest.Mock;

beforeEach(() => {
applyFilterSpy = jest.fn();
resetFilterFormSpy = jest.fn();

TestBed.configureTestingModule({
providers: [
{
provide: VaultPopupItemsService,
useValue: { applyFilter: applyFilterSpy },
},
{
provide: VaultPopupListFiltersService,
useValue: { resetFilterForm: resetFilterFormSpy },
},
],
});
});

afterEach(() => {
jest.clearAllMocks();
});

it.each([
"/view-cipher?cipherId=123",
"/edit-cipher?cipherId=123",
"/clone-cipher?cipherId=123",
"/assign-collections?cipherId=123",
])("should not clear vault state when viewing or editing a cipher: %s", (url) => {
const nextState = { url } as RouterStateSnapshot;

const result = TestBed.runInInjectionContext(() =>
clearVaultStateGuard({} as VaultV2Component, null, null, nextState),
);

expect(result).toBe(true);
expect(applyFilterSpy).not.toHaveBeenCalled();
expect(resetFilterFormSpy).not.toHaveBeenCalled();
});

it.each(["/settings", "/tabs/settings"])(
"should clear vault state when navigating to non-cipher routes: %s",
(url) => {
const nextState = { url } as RouterStateSnapshot;

const result = TestBed.runInInjectionContext(() =>
clearVaultStateGuard({} as VaultV2Component, null, null, nextState),
);

expect(result).toBe(true);
expect(applyFilterSpy).toHaveBeenCalledWith("");
expect(resetFilterFormSpy).toHaveBeenCalled();
},
);

it("should not clear vault state when not changing states", () => {
const result = TestBed.runInInjectionContext(() =>
clearVaultStateGuard({} as VaultV2Component, null, null, null),
);

expect(result).toBe(true);
expect(applyFilterSpy).not.toHaveBeenCalled();
expect(resetFilterFormSpy).not.toHaveBeenCalled();
});
});
11 changes: 8 additions & 3 deletions apps/browser/src/vault/popup/guards/clear-vault-state.guard.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ import { VaultPopupListFiltersService } from "../services/vault-popup-list-filte

/**
* Guard to clear the vault state (search and filter) when navigating away from the vault view.
* This ensures the search and filter state is reset when navigating between different tabs, except viewing a cipher.
* This ensures the search and filter state is reset when navigating between different tabs,
* except viewing or editing a cipher.
*/
export const clearVaultStateGuard: CanDeactivateFn<VaultV2Component> = (
component: VaultV2Component,
Expand All @@ -17,12 +18,16 @@ export const clearVaultStateGuard: CanDeactivateFn<VaultV2Component> = (
) => {
const vaultPopupItemsService = inject(VaultPopupItemsService);
const vaultPopupListFiltersService = inject(VaultPopupListFiltersService);
if (nextState && !isViewingCipher(nextState.url)) {
if (nextState && !isCipherOpen(nextState.url)) {
vaultPopupItemsService.applyFilter("");
vaultPopupListFiltersService.resetFilterForm();
}

return true;
};

const isViewingCipher = (url: string): boolean => url.includes("view-cipher");
const isCipherOpen = (url: string): boolean =>
url.includes("view-cipher") ||
url.includes("assign-collections") ||
url.includes("edit-cipher") ||
url.includes("clone-cipher");
Loading