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
Expand Up @@ -2,12 +2,14 @@ import { ComponentRef } from "@angular/core";
import { ComponentFixture, TestBed } from "@angular/core/testing";
import { By } from "@angular/platform-browser";
import { mock, MockProxy } from "jest-mock-extended";
import { of } from "rxjs";
import { BehaviorSubject, of } from "rxjs";

import { CollectionView } from "@bitwarden/common/admin-console/models/collections";
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
import { DomainSettingsService } from "@bitwarden/common/autofill/services/domain-settings.service";
import { ClientType } from "@bitwarden/common/enums";
import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum";
import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
import { EnvironmentService } from "@bitwarden/common/platform/abstractions/environment.service";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
Expand All @@ -21,6 +23,7 @@ describe("ItemDetailsV2Component", () => {
let fixture: ComponentFixture<ItemDetailsV2Component>;
let componentRef: ComponentRef<ItemDetailsV2Component>;
let mockPlatformUtilsService: MockProxy<PlatformUtilsService>;
let desktopMilestone3Flag$: BehaviorSubject<boolean>;

const cipher = {
id: "cipher1",
Expand Down Expand Up @@ -52,18 +55,28 @@ describe("ItemDetailsV2Component", () => {

beforeEach(async () => {
mockPlatformUtilsService = mock<PlatformUtilsService>();
mockPlatformUtilsService.getClientType.mockReturnValue(ClientType.Web);
desktopMilestone3Flag$ = new BehaviorSubject<boolean>(false);

await TestBed.configureTestingModule({
imports: [ItemDetailsV2Component],
providers: [
{ provide: I18nService, useValue: { t: (key: string) => key } },
{ provide: PlatformUtilsService, useValue: { getClientType: () => ClientType.Web } },
{ provide: PlatformUtilsService, useValue: mockPlatformUtilsService },
{
provide: ConfigService,
useValue: {
getFeatureFlag$: (flag: FeatureFlag) =>
flag === FeatureFlag.DesktopUiMigrationMilestone3
? desktopMilestone3Flag$.asObservable()
: of(false),
},
},
{
provide: EnvironmentService,
useValue: { environment$: of({ getIconsUrl: () => "https://icons.example.com" }) },
},
{ provide: DomainSettingsService, useValue: { showFavicons$: of(true) } },
{ provide: PlatformUtilsService, useValue: mockPlatformUtilsService },
],
}).compileComponents();
});
Expand Down Expand Up @@ -102,30 +115,37 @@ describe("ItemDetailsV2Component", () => {
expect(owner).toBeNull();
});

it("should show archive badge when cipher is archived and client is Desktop", () => {
jest.spyOn(mockPlatformUtilsService, "getClientType").mockReturnValue(ClientType.Desktop);
describe("showArchiveBadge", () => {
it("is true when cipher is archived on Desktop and DesktopUiMigrationMilestone3 is off", () => {
mockPlatformUtilsService.getClientType.mockReturnValue(ClientType.Desktop);
desktopMilestone3Flag$.next(false);
componentRef.setInput("cipher", { ...cipher, isArchived: true });

const archivedCipher = { ...cipher, isArchived: true };
componentRef.setInput("cipher", archivedCipher);
expect((component as any).showArchiveBadge()).toBe(true);
});

expect((component as any).showArchiveBadge()).toBe(true);
});

it("should not show archive badge when cipher is not archived", () => {
jest.spyOn(mockPlatformUtilsService, "getClientType").mockReturnValue(ClientType.Desktop);
it("is false when DesktopUiMigrationMilestone3 is on (dialog renders its own badge)", () => {
mockPlatformUtilsService.getClientType.mockReturnValue(ClientType.Desktop);
desktopMilestone3Flag$.next(true);
componentRef.setInput("cipher", { ...cipher, isArchived: true });

const unarchivedCipher = { ...cipher, isArchived: false };
componentRef.setInput("cipher", unarchivedCipher);
expect((component as any).showArchiveBadge()).toBe(false);
});

expect((component as any).showArchiveBadge()).toBe(false);
});
it("is false when cipher is not archived", () => {
mockPlatformUtilsService.getClientType.mockReturnValue(ClientType.Desktop);
desktopMilestone3Flag$.next(false);
componentRef.setInput("cipher", { ...cipher, isArchived: false });

it("should not show archive badge when client is not Desktop", () => {
jest.spyOn(mockPlatformUtilsService, "getClientType").mockReturnValue(ClientType.Web);
expect((component as any).showArchiveBadge()).toBe(false);
});

const archivedCipher = { ...cipher, isArchived: true };
componentRef.setInput("cipher", archivedCipher);
it("is false when client is not Desktop", () => {
mockPlatformUtilsService.getClientType.mockReturnValue(ClientType.Web);
desktopMilestone3Flag$.next(false);
componentRef.setInput("cipher", { ...cipher, isArchived: true });

expect((component as any).showArchiveBadge()).toBe(false);
expect((component as any).showArchiveBadge()).toBe(false);
});
});
});
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
// FIXME: Update this file to be type safe and remove this and next line
// @ts-strict-ignore
import { CommonModule } from "@angular/common";
import { Component, computed, input, signal } from "@angular/core";
import { Component, computed, inject, input, signal } from "@angular/core";
// This import has been flagged as unallowed for this class. It may be involved in a circular dependency loop.
import { toSignal } from "@angular/core/rxjs-interop";
import { fromEvent, map, startWith } from "rxjs";
import { fromEvent, map, of, startWith } from "rxjs";

import { JslibModule } from "@bitwarden/angular/jslib.module";
import { ClientType } from "@bitwarden/client-type";
Expand All @@ -13,6 +13,8 @@ import {
CollectionTypes,
} from "@bitwarden/common/admin-console/models/collections";
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum";
import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view";
Expand Down Expand Up @@ -91,16 +93,23 @@ export class ItemDetailsV2Component {
}
});

private readonly platformUtilsService = inject(PlatformUtilsService);

private readonly configService = inject(ConfigService);

private readonly desktopMilestone3Enabled = toSignal(
this.configService.getFeatureFlag$(FeatureFlag.DesktopUiMigrationMilestone3) ?? of(false),
);

protected readonly showArchiveBadge = computed(() => {
return (
this.cipher().isArchived && this.platformUtilsService.getClientType() === ClientType.Desktop
this.cipher().isArchived &&
this.platformUtilsService.getClientType() === ClientType.Desktop &&
!this.desktopMilestone3Enabled()
);
});

constructor(
private i18nService: I18nService,
private platformUtilsService: PlatformUtilsService,
) {}
constructor(private i18nService: I18nService) {}

toggleShowMore() {
this.showAllDetails.update((value) => !value);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ import { UnionOfValues } from "@bitwarden/common/vault/types/union-of-values";
import { CipherViewLike } from "@bitwarden/common/vault/utils/cipher-view-like-utils";
import {
AsyncActionsModule,
BadgeModule,
BitIconButtonComponent,
ButtonModule,
CenterPositionStrategy,
Expand Down Expand Up @@ -130,6 +131,7 @@ export type VaultItemDialogResult = UnionOfValues<typeof VaultItemDialogResult>;
CommonModule,
CipherFormModule,
AsyncActionsModule,
BadgeModule,
ItemModule,
PremiumBadgeComponent,
I18nPipe,
Expand Down
Loading