mirror of
https://github.com/bitwarden/browser
synced 2026-01-06 10:33:57 +00:00
PM-9665: implement view item view (#10416)
* Add initial view cipher dialog. * Add working view cipher modal dialog markup. * Cleanup dialog markup and allow edit from dialog. * Cleanup unused imports. * Begin adding org-vault view-cipher functionality. * Refactor to remove loose-components usage and use DialogService. * Add edit and delete button functionality. * Add delete functionality. * Remove addition to loose components. * Remove unused modal-dialog artifacts. * Ensure dialog closes and URL updates properly on edit or close. * Disable edit/delete buttons instead of hiding them. * Add simple tests for view.component.ts. * Adjust import order. * Remove now unnecessary ng-template. * Decrypt cipher to cipher view. * Add cleanup function and additional delete test. * Remove boolean return from delete promise. * Remove fake timers. * Remove unnecessary TestBed.inject calls. * Add code comments. * Hide new view cipher dialog behind feature flag. * Keep "else if" statement intact. * Simplify getting cipherTypeString. * Add comments to vault.component.ts files. * Change button type to "danger" Update apps/web/src/app/vault/individual-vault/view.component.html Co-authored-by: Nick Krantz <125900171+nick-livefront@users.noreply.github.com> * Add a11y title to delete button. * Simplify OrganizationService testing. * Update comment to better reflect function. * Use large dialog to better match designs. * Add aria-haspopup to cipher row button. * Add deleteCipher to messages.json. * Remove extra argument from canEditAllCiphers. * Use 'delete' instead of 'delete cipher' for a11y title. * Remove 'bitFormButton' from non-form buttons. * Rework view cipher view delete functionality. * Add translations for cipher types. * Remove unecesarry test. * Add additional test coverage to ensure dialogs close. * Add back delete functionality in view.component.ts. * Update "secure note" to "note". --------- Co-authored-by: Nick Krantz <125900171+nick-livefront@users.noreply.github.com>
This commit is contained in:
117
apps/web/src/app/vault/individual-vault/view.component.spec.ts
Normal file
117
apps/web/src/app/vault/individual-vault/view.component.spec.ts
Normal file
@@ -0,0 +1,117 @@
|
||||
import { DIALOG_DATA, DialogRef } from "@angular/cdk/dialog";
|
||||
import { ComponentFixture, TestBed } from "@angular/core/testing";
|
||||
import { Router } from "@angular/router";
|
||||
import { mock } from "jest-mock-extended";
|
||||
|
||||
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
||||
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
|
||||
import { BillingAccountProfileStateService } from "@bitwarden/common/billing/abstractions/account/billing-account-profile-state.service";
|
||||
import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
|
||||
import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service";
|
||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
||||
import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service";
|
||||
import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
|
||||
import { CollectionService } from "@bitwarden/common/vault/abstractions/collection.service";
|
||||
import { FolderService } from "@bitwarden/common/vault/abstractions/folder/folder.service.abstraction";
|
||||
import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view";
|
||||
import { DialogService, ToastService } from "@bitwarden/components";
|
||||
|
||||
import { ViewComponent, ViewCipherDialogParams, ViewCipherDialogResult } from "./view.component";
|
||||
|
||||
describe("ViewComponent", () => {
|
||||
let component: ViewComponent;
|
||||
let fixture: ComponentFixture<ViewComponent>;
|
||||
let router: Router;
|
||||
|
||||
const mockCipher: CipherView = {
|
||||
id: "cipher-id",
|
||||
type: 1,
|
||||
organizationId: "org-id",
|
||||
isDeleted: false,
|
||||
} as CipherView;
|
||||
|
||||
const mockOrganization: Organization = {
|
||||
id: "org-id",
|
||||
name: "Test Organization",
|
||||
} as Organization;
|
||||
|
||||
const mockParams: ViewCipherDialogParams = {
|
||||
cipher: mockCipher,
|
||||
};
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
imports: [ViewComponent],
|
||||
providers: [
|
||||
{ provide: DIALOG_DATA, useValue: mockParams },
|
||||
{ provide: DialogRef, useValue: mock<DialogRef>() },
|
||||
{ provide: I18nService, useValue: { t: jest.fn().mockReturnValue("login") } },
|
||||
{ provide: DialogService, useValue: mock<DialogService>() },
|
||||
{ provide: CipherService, useValue: mock<CipherService>() },
|
||||
{ provide: ToastService, useValue: mock<ToastService>() },
|
||||
{ provide: MessagingService, useValue: mock<MessagingService>() },
|
||||
{ provide: LogService, useValue: mock<LogService>() },
|
||||
{
|
||||
provide: OrganizationService,
|
||||
useValue: { get: jest.fn().mockResolvedValue(mockOrganization) },
|
||||
},
|
||||
{ provide: Router, useValue: mock<Router>() },
|
||||
{ provide: CollectionService, useValue: mock<CollectionService>() },
|
||||
{ provide: FolderService, useValue: mock<FolderService>() },
|
||||
{ provide: CryptoService, useValue: mock<CryptoService>() },
|
||||
{
|
||||
provide: BillingAccountProfileStateService,
|
||||
useValue: mock<BillingAccountProfileStateService>(),
|
||||
},
|
||||
{ provide: ConfigService, useValue: mock<ConfigService>() },
|
||||
],
|
||||
}).compileComponents();
|
||||
|
||||
fixture = TestBed.createComponent(ViewComponent);
|
||||
component = fixture.componentInstance;
|
||||
router = TestBed.inject(Router);
|
||||
component.params = mockParams;
|
||||
component.cipher = mockCipher;
|
||||
});
|
||||
|
||||
describe("ngOnInit", () => {
|
||||
it("initializes the component with cipher and organization", async () => {
|
||||
await component.ngOnInit();
|
||||
|
||||
expect(component.cipher).toEqual(mockCipher);
|
||||
expect(component.organization).toEqual(mockOrganization);
|
||||
});
|
||||
});
|
||||
|
||||
describe("edit", () => {
|
||||
it("navigates to the edit route and closes the dialog with the proper arguments", async () => {
|
||||
jest.spyOn(router, "navigate").mockResolvedValue(true);
|
||||
const dialogRefCloseSpy = jest.spyOn(component["dialogRef"], "close");
|
||||
|
||||
await component.edit();
|
||||
|
||||
expect(router.navigate).toHaveBeenCalledWith([], {
|
||||
queryParams: {
|
||||
itemId: mockCipher.id,
|
||||
action: "edit",
|
||||
organizationId: mockCipher.organizationId,
|
||||
},
|
||||
});
|
||||
expect(dialogRefCloseSpy).toHaveBeenCalledWith({ action: ViewCipherDialogResult.edited });
|
||||
});
|
||||
});
|
||||
|
||||
describe("delete", () => {
|
||||
it("calls the delete method on delete and closes the dialog with the proper arguments", async () => {
|
||||
const deleteSpy = jest.spyOn(component, "delete");
|
||||
const dialogRefCloseSpy = jest.spyOn(component["dialogRef"], "close");
|
||||
jest.spyOn(component["dialogService"], "openSimpleDialog").mockResolvedValue(true);
|
||||
|
||||
await component.delete();
|
||||
|
||||
expect(deleteSpy).toHaveBeenCalled();
|
||||
expect(dialogRefCloseSpy).toHaveBeenCalledWith({ action: ViewCipherDialogResult.deleted });
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user