From 67f6f82842a2ecedc129b0460f58f1013f395742 Mon Sep 17 00:00:00 2001 From: olfek <27283110+olfek@users.noreply.github.com> Date: Tue, 13 Jan 2026 17:01:05 +0000 Subject: [PATCH 1/6] [PM-30443][FIX] Pass more inclusive user verification Boolean to `setAbortTimeout` (#15027) * [FIX] Pass more inclusive user verification Boolean to `setAbortTimeout` * Update `setAbortTimeout` user verification parameter type * Fix lint issue --------- Co-authored-by: Daniel James Smith <2670567+djsmith85@users.noreply.github.com> Co-authored-by: Daniel James Smith --- .../src/platform/services/fido2/fido2-client.service.ts | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/libs/common/src/platform/services/fido2/fido2-client.service.ts b/libs/common/src/platform/services/fido2/fido2-client.service.ts index 503ffef8241..2aa618e974d 100644 --- a/libs/common/src/platform/services/fido2/fido2-client.service.ts +++ b/libs/common/src/platform/services/fido2/fido2-client.service.ts @@ -30,7 +30,6 @@ import { Fido2ClientService as Fido2ClientServiceAbstraction, PublicKeyCredentialParam, UserRequestedFallbackAbortReason, - UserVerification, } from "../../abstractions/fido2/fido2-client.service.abstraction"; import { LogService } from "../../abstractions/log.service"; import { Utils } from "../../misc/utils"; @@ -195,7 +194,7 @@ export class Fido2ClientService< } const timeoutSubscription = this.setAbortTimeout( abortController, - params.authenticatorSelection?.userVerification, + makeCredentialParams.requireUserVerification, params.timeout, ); @@ -318,7 +317,7 @@ export class Fido2ClientService< const timeoutSubscription = this.setAbortTimeout( abortController, - params.userVerification, + getAssertionParams.requireUserVerification, params.timeout, ); @@ -441,13 +440,13 @@ export class Fido2ClientService< private setAbortTimeout = ( abortController: AbortController, - userVerification?: UserVerification, + requireUserVerification: boolean, timeout?: number, ): Subscription => { let clampedTimeout: number; const { WITH_VERIFICATION, NO_VERIFICATION } = this.TIMEOUTS; - if (userVerification === "required") { + if (requireUserVerification) { timeout = timeout ?? WITH_VERIFICATION.DEFAULT; clampedTimeout = Math.max(WITH_VERIFICATION.MIN, Math.min(timeout, WITH_VERIFICATION.MAX)); } else { From 20974f8195b0f564ff7a0b6c3d67aebefd8acf71 Mon Sep 17 00:00:00 2001 From: SmithThe4th Date: Tue, 13 Jan 2026 12:38:28 -0500 Subject: [PATCH 2/6] [PM-28455] Fix vault breaking when collection name decryption fails (#18331) * Set error cannot decrypt when collection name cannot be decrypted * Put back previous comment --- .../collections/models/collection-admin.view.ts | 2 +- .../src/common/collections/models/collection.view.ts | 11 +++++++++-- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/libs/admin-console/src/common/collections/models/collection-admin.view.ts b/libs/admin-console/src/common/collections/models/collection-admin.view.ts index d5effaad3aa..4e4ebae964e 100644 --- a/libs/admin-console/src/common/collections/models/collection-admin.view.ts +++ b/libs/admin-console/src/common/collections/models/collection-admin.view.ts @@ -121,13 +121,13 @@ export class CollectionAdminView extends CollectionView { try { view.name = await encryptService.decryptString(new EncString(view.name), orgKey); } catch (e) { + view.name = "[error: cannot decrypt]"; // Note: This should be replaced by the owning team with appropriate, domain-specific behavior. // eslint-disable-next-line no-console console.error( "[CollectionAdminView/fromCollectionAccessDetails] Error decrypting collection name", e, ); - throw e; } view.assigned = collection.assigned; view.readOnly = collection.readOnly; diff --git a/libs/admin-console/src/common/collections/models/collection.view.ts b/libs/admin-console/src/common/collections/models/collection.view.ts index 2991e8bb171..64b6e2a9d1e 100644 --- a/libs/admin-console/src/common/collections/models/collection.view.ts +++ b/libs/admin-console/src/common/collections/models/collection.view.ts @@ -126,7 +126,14 @@ export class CollectionView implements View, ITreeNodeObject { ): Promise { const view = new CollectionView({ ...collection, name: "" }); - view.name = await encryptService.decryptString(collection.name, key); + try { + view.name = await encryptService.decryptString(collection.name, key); + } catch (e) { + view.name = "[error: cannot decrypt]"; + // eslint-disable-next-line no-console + console.error("[CollectionView] Error decrypting collection name", e); + } + view.assigned = true; view.externalId = collection.externalId; view.readOnly = collection.readOnly; @@ -147,10 +154,10 @@ export class CollectionView implements View, ITreeNodeObject { try { view.name = await encryptService.decryptString(new EncString(collection.name), orgKey); } catch (e) { + view.name = "[error: cannot decrypt]"; // Note: This should be replaced by the owning team with appropriate, domain-specific behavior. // eslint-disable-next-line no-console console.error("[CollectionView] Error decrypting collection name", e); - throw e; } view.externalId = collection.externalId; From 66819c06893624dd9ed3e456ca00e447b47296f7 Mon Sep 17 00:00:00 2001 From: Daniel Riera Date: Tue, 13 Jan 2026 14:36:52 -0500 Subject: [PATCH 3/6] [PM-29512] Remove ts strict ignore in popup fido 2 cipher row component ts (#18064) * last is dead code, remove completely * pass required true so that angular enforces at runtime and run apply a definitive assignment assertion since angulars input binding is running before use --- .../autofill/popup/fido2/fido2-cipher-row.component.ts | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/apps/browser/src/autofill/popup/fido2/fido2-cipher-row.component.ts b/apps/browser/src/autofill/popup/fido2/fido2-cipher-row.component.ts index adabae2c31d..ace314c6a84 100644 --- a/apps/browser/src/autofill/popup/fido2/fido2-cipher-row.component.ts +++ b/apps/browser/src/autofill/popup/fido2/fido2-cipher-row.component.ts @@ -1,5 +1,3 @@ -// FIXME: Update this file to be type safe and remove this and next line -// @ts-strict-ignore import { CommonModule } from "@angular/common"; import { Component, EventEmitter, Input, Output, ChangeDetectionStrategy } from "@angular/core"; @@ -33,13 +31,10 @@ export class Fido2CipherRowComponent { @Output() onSelected = new EventEmitter(); // FIXME(https://bitwarden.atlassian.net/browse/CL-903): Migrate to Signals // eslint-disable-next-line @angular-eslint/prefer-signals - @Input() cipher: CipherView; + @Input({ required: true }) cipher!: CipherView; // FIXME(https://bitwarden.atlassian.net/browse/CL-903): Migrate to Signals // eslint-disable-next-line @angular-eslint/prefer-signals - @Input() last: boolean; - // FIXME(https://bitwarden.atlassian.net/browse/CL-903): Migrate to Signals - // eslint-disable-next-line @angular-eslint/prefer-signals - @Input() title: string; + @Input({ required: true }) title!: string; protected selectCipher(c: CipherView) { this.onSelected.emit(c); From f018ce36a1b8adf7303425d318a861ffd2660ea0 Mon Sep 17 00:00:00 2001 From: SmithThe4th Date: Tue, 13 Jan 2026 14:38:56 -0500 Subject: [PATCH 4/6] =?UTF-8?q?Revert=20"[PM-28455]=20Fix=20vault=20breaki?= =?UTF-8?q?ng=20when=20collection=20name=20decryption=20fails=20(=E2=80=A6?= =?UTF-8?q?"=20(#18343)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 20974f8195b0f564ff7a0b6c3d67aebefd8acf71. --- .../collections/models/collection-admin.view.ts | 2 +- .../src/common/collections/models/collection.view.ts | 11 ++--------- 2 files changed, 3 insertions(+), 10 deletions(-) diff --git a/libs/admin-console/src/common/collections/models/collection-admin.view.ts b/libs/admin-console/src/common/collections/models/collection-admin.view.ts index 4e4ebae964e..d5effaad3aa 100644 --- a/libs/admin-console/src/common/collections/models/collection-admin.view.ts +++ b/libs/admin-console/src/common/collections/models/collection-admin.view.ts @@ -121,13 +121,13 @@ export class CollectionAdminView extends CollectionView { try { view.name = await encryptService.decryptString(new EncString(view.name), orgKey); } catch (e) { - view.name = "[error: cannot decrypt]"; // Note: This should be replaced by the owning team with appropriate, domain-specific behavior. // eslint-disable-next-line no-console console.error( "[CollectionAdminView/fromCollectionAccessDetails] Error decrypting collection name", e, ); + throw e; } view.assigned = collection.assigned; view.readOnly = collection.readOnly; diff --git a/libs/admin-console/src/common/collections/models/collection.view.ts b/libs/admin-console/src/common/collections/models/collection.view.ts index 64b6e2a9d1e..2991e8bb171 100644 --- a/libs/admin-console/src/common/collections/models/collection.view.ts +++ b/libs/admin-console/src/common/collections/models/collection.view.ts @@ -126,14 +126,7 @@ export class CollectionView implements View, ITreeNodeObject { ): Promise { const view = new CollectionView({ ...collection, name: "" }); - try { - view.name = await encryptService.decryptString(collection.name, key); - } catch (e) { - view.name = "[error: cannot decrypt]"; - // eslint-disable-next-line no-console - console.error("[CollectionView] Error decrypting collection name", e); - } - + view.name = await encryptService.decryptString(collection.name, key); view.assigned = true; view.externalId = collection.externalId; view.readOnly = collection.readOnly; @@ -154,10 +147,10 @@ export class CollectionView implements View, ITreeNodeObject { try { view.name = await encryptService.decryptString(new EncString(collection.name), orgKey); } catch (e) { - view.name = "[error: cannot decrypt]"; // Note: This should be replaced by the owning team with appropriate, domain-specific behavior. // eslint-disable-next-line no-console console.error("[CollectionView] Error decrypting collection name", e); + throw e; } view.externalId = collection.externalId; From 4ea32e7a93d202c54a9945443ae53837f91237e5 Mon Sep 17 00:00:00 2001 From: Vijay Oommen Date: Tue, 13 Jan 2026 14:28:06 -0600 Subject: [PATCH 5/6] [PM-25228] Remove unknown elements from spec files (#18325) --- .../pages/breach-report.component.spec.ts | 29 +++++++++---- ...exposed-passwords-report.component.spec.ts | 42 ++++++++++++++----- ...active-two-factor-report.component.spec.ts | 5 ++- .../reused-passwords-report.component.spec.ts | 34 +++++++++++---- ...nsecured-websites-report.component.spec.ts | 34 +++++++++++---- .../weak-passwords-report.component.spec.ts | 31 ++++++++++---- 6 files changed, 131 insertions(+), 44 deletions(-) diff --git a/apps/web/src/app/dirt/reports/pages/breach-report.component.spec.ts b/apps/web/src/app/dirt/reports/pages/breach-report.component.spec.ts index 886267e3189..6a26d8abd74 100644 --- a/apps/web/src/app/dirt/reports/pages/breach-report.component.spec.ts +++ b/apps/web/src/app/dirt/reports/pages/breach-report.component.spec.ts @@ -1,17 +1,17 @@ -// FIXME: Update this file to be type safe and remove this and next line -// @ts-strict-ignore +import { Component, ChangeDetectionStrategy } from "@angular/core"; import { ComponentFixture, TestBed } from "@angular/core/testing"; import { ReactiveFormsModule } from "@angular/forms"; import { mock, MockProxy } from "jest-mock-extended"; import { BehaviorSubject } from "rxjs"; -import { I18nPipe } from "@bitwarden/angular/platform/pipes/i18n.pipe"; import { AuditService } from "@bitwarden/common/abstractions/audit.service"; import { AccountInfo, AccountService } from "@bitwarden/common/auth/abstractions/account.service"; import { BreachAccountResponse } from "@bitwarden/common/dirt/models/response/breach-account.response"; import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; import { mockAccountInfoWith } from "@bitwarden/common/spec"; import { UserId } from "@bitwarden/common/types/guid"; +import { AsyncActionsModule, ButtonModule, FormFieldModule } from "@bitwarden/components"; +import { I18nPipe } from "@bitwarden/ui-common"; import { BreachReportComponent } from "./breach-report.component"; @@ -32,6 +32,21 @@ const breachedAccounts = [ }), ]; +@Component({ + changeDetection: ChangeDetectionStrategy.OnPush, + selector: "app-header", + template: "
", + standalone: false, +}) +class MockHeaderComponent {} +@Component({ + changeDetection: ChangeDetectionStrategy.OnPush, + selector: "bit-container", + template: "
", + standalone: false, +}) +class MockBitContainerComponent {} + describe("BreachReportComponent", () => { let component: BreachReportComponent; let fixture: ComponentFixture; @@ -51,8 +66,8 @@ describe("BreachReportComponent", () => { accountService.activeAccount$ = activeAccountSubject; await TestBed.configureTestingModule({ - declarations: [BreachReportComponent, I18nPipe], - imports: [ReactiveFormsModule], + declarations: [BreachReportComponent, MockHeaderComponent, MockBitContainerComponent], + imports: [ReactiveFormsModule, I18nPipe, AsyncActionsModule, ButtonModule, FormFieldModule], providers: [ { provide: AuditService, @@ -67,9 +82,7 @@ describe("BreachReportComponent", () => { useValue: mock(), }, ], - // FIXME(PM-18598): Replace unknownElements and unknownProperties with actual imports - errorOnUnknownElements: false, - errorOnUnknownProperties: false, + schemas: [], }).compileComponents(); }); diff --git a/apps/web/src/app/dirt/reports/pages/exposed-passwords-report.component.spec.ts b/apps/web/src/app/dirt/reports/pages/exposed-passwords-report.component.spec.ts index 560245bdc34..e056ec44af5 100644 --- a/apps/web/src/app/dirt/reports/pages/exposed-passwords-report.component.spec.ts +++ b/apps/web/src/app/dirt/reports/pages/exposed-passwords-report.component.spec.ts @@ -1,8 +1,8 @@ +import { Component, ChangeDetectionStrategy } from "@angular/core"; import { ComponentFixture, TestBed } from "@angular/core/testing"; import { mock, MockProxy } from "jest-mock-extended"; import { of } from "rxjs"; -import { I18nPipe } from "@bitwarden/angular/platform/pipes/i18n.pipe"; import { AuditService } from "@bitwarden/common/abstractions/audit.service"; import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction"; import { AccountService } from "@bitwarden/common/auth/abstractions/account.service"; @@ -12,7 +12,13 @@ import { FakeAccountService, mockAccountServiceWith } from "@bitwarden/common/sp import { UserId } from "@bitwarden/common/types/guid"; import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service"; import { SyncService } from "@bitwarden/common/vault/abstractions/sync/sync.service.abstraction"; -import { DialogService } from "@bitwarden/components"; +import { + DialogService, + AsyncActionsModule, + ButtonModule, + FormFieldModule, +} from "@bitwarden/components"; +import { I18nPipe } from "@bitwarden/ui-common"; import { CipherFormConfigService, PasswordRepromptService } from "@bitwarden/vault"; import { AdminConsoleCipherFormConfigService } from "../../../vault/org-vault/services/admin-console-cipher-form-config.service"; @@ -20,6 +26,22 @@ import { AdminConsoleCipherFormConfigService } from "../../../vault/org-vault/se import { ExposedPasswordsReportComponent } from "./exposed-passwords-report.component"; import { cipherData } from "./reports-ciphers.mock"; +@Component({ + changeDetection: ChangeDetectionStrategy.OnPush, + selector: "app-header", + template: "
", + standalone: false, +}) +class MockHeaderComponent {} + +@Component({ + changeDetection: ChangeDetectionStrategy.OnPush, + selector: "bit-container", + template: "
", + standalone: false, +}) +class MockBitContainerComponent {} + describe("ExposedPasswordsReportComponent", () => { let component: ExposedPasswordsReportComponent; let fixture: ComponentFixture; @@ -30,16 +52,19 @@ describe("ExposedPasswordsReportComponent", () => { const userId = Utils.newGuid() as UserId; const accountService: FakeAccountService = mockAccountServiceWith(userId); - beforeEach(() => { + beforeEach(async () => { let cipherFormConfigServiceMock: MockProxy; syncServiceMock = mock(); auditService = mock(); organizationService = mock(); organizationService.organizations$.mockReturnValue(of([])); - // FIXME: Verify that this floating promise is intentional. If it is, add an explanatory comment and ensure there is proper error handling. - // eslint-disable-next-line @typescript-eslint/no-floating-promises - TestBed.configureTestingModule({ - declarations: [ExposedPasswordsReportComponent, I18nPipe], + await TestBed.configureTestingModule({ + declarations: [ + ExposedPasswordsReportComponent, + MockHeaderComponent, + MockBitContainerComponent, + ], + imports: [I18nPipe, AsyncActionsModule, ButtonModule, FormFieldModule], providers: [ { provide: CipherService, @@ -83,9 +108,6 @@ describe("ExposedPasswordsReportComponent", () => { }, ], schemas: [], - // FIXME(PM-18598): Replace unknownElements and unknownProperties with actual imports - errorOnUnknownElements: false, - errorOnUnknownProperties: false, }).compileComponents(); }); diff --git a/apps/web/src/app/dirt/reports/pages/inactive-two-factor-report.component.spec.ts b/apps/web/src/app/dirt/reports/pages/inactive-two-factor-report.component.spec.ts index 64a851e120e..12453ea3b88 100644 --- a/apps/web/src/app/dirt/reports/pages/inactive-two-factor-report.component.spec.ts +++ b/apps/web/src/app/dirt/reports/pages/inactive-two-factor-report.component.spec.ts @@ -3,7 +3,6 @@ import { ComponentFixture, TestBed } from "@angular/core/testing"; import { MockProxy, mock } from "jest-mock-extended"; import { of } from "rxjs"; -import { I18nPipe } from "@bitwarden/angular/platform/pipes/i18n.pipe"; import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction"; import { AccountService } from "@bitwarden/common/auth/abstractions/account.service"; import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; @@ -14,6 +13,7 @@ import { UserId } from "@bitwarden/common/types/guid"; import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service"; import { SyncService } from "@bitwarden/common/vault/abstractions/sync/sync.service.abstraction"; import { DialogService } from "@bitwarden/components"; +import { I18nPipe } from "@bitwarden/ui-common"; import { CipherFormConfigService, PasswordRepromptService } from "@bitwarden/vault"; import { AdminConsoleCipherFormConfigService } from "../../../vault/org-vault/services/admin-console-cipher-form-config.service"; @@ -37,7 +37,8 @@ describe("InactiveTwoFactorReportComponent", () => { syncServiceMock = mock(); await TestBed.configureTestingModule({ - declarations: [InactiveTwoFactorReportComponent, I18nPipe], + declarations: [InactiveTwoFactorReportComponent], + imports: [I18nPipe], providers: [ { provide: CipherService, diff --git a/apps/web/src/app/dirt/reports/pages/reused-passwords-report.component.spec.ts b/apps/web/src/app/dirt/reports/pages/reused-passwords-report.component.spec.ts index 5933d2ce293..1b7006d0c68 100644 --- a/apps/web/src/app/dirt/reports/pages/reused-passwords-report.component.spec.ts +++ b/apps/web/src/app/dirt/reports/pages/reused-passwords-report.component.spec.ts @@ -1,8 +1,8 @@ +import { ChangeDetectionStrategy, Component } from "@angular/core"; import { ComponentFixture, TestBed } from "@angular/core/testing"; import { MockProxy, mock } from "jest-mock-extended"; import { of } from "rxjs"; -import { I18nPipe } from "@bitwarden/angular/platform/pipes/i18n.pipe"; import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction"; import { AccountService } from "@bitwarden/common/auth/abstractions/account.service"; import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; @@ -12,6 +12,7 @@ import { UserId } from "@bitwarden/common/types/guid"; import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service"; import { SyncService } from "@bitwarden/common/vault/abstractions/sync/sync.service.abstraction"; import { DialogService } from "@bitwarden/components"; +import { I18nPipe } from "@bitwarden/ui-common"; import { CipherFormConfigService, PasswordRepromptService } from "@bitwarden/vault"; import { AdminConsoleCipherFormConfigService } from "../../../vault/org-vault/services/admin-console-cipher-form-config.service"; @@ -19,6 +20,22 @@ import { AdminConsoleCipherFormConfigService } from "../../../vault/org-vault/se import { cipherData } from "./reports-ciphers.mock"; import { ReusedPasswordsReportComponent } from "./reused-passwords-report.component"; +@Component({ + changeDetection: ChangeDetectionStrategy.OnPush, + selector: "app-header", + template: "
", + standalone: false, +}) +class MockHeaderComponent {} + +@Component({ + changeDetection: ChangeDetectionStrategy.OnPush, + selector: "bit-container", + template: "
", + standalone: false, +}) +class MockBitContainerComponent {} + describe("ReusedPasswordsReportComponent", () => { let component: ReusedPasswordsReportComponent; let fixture: ComponentFixture; @@ -28,15 +45,18 @@ describe("ReusedPasswordsReportComponent", () => { const userId = Utils.newGuid() as UserId; const accountService: FakeAccountService = mockAccountServiceWith(userId); - beforeEach(() => { + beforeEach(async () => { let cipherFormConfigServiceMock: MockProxy; organizationService = mock(); organizationService.organizations$.mockReturnValue(of([])); syncServiceMock = mock(); - // FIXME: Verify that this floating promise is intentional. If it is, add an explanatory comment and ensure there is proper error handling. - // eslint-disable-next-line @typescript-eslint/no-floating-promises - TestBed.configureTestingModule({ - declarations: [ReusedPasswordsReportComponent, I18nPipe], + await TestBed.configureTestingModule({ + declarations: [ + ReusedPasswordsReportComponent, + MockHeaderComponent, + MockBitContainerComponent, + ], + imports: [I18nPipe], providers: [ { provide: CipherService, @@ -76,8 +96,6 @@ describe("ReusedPasswordsReportComponent", () => { }, ], schemas: [], - // FIXME(PM-18598): Replace unknownElements and unknownProperties with actual imports - errorOnUnknownElements: false, }).compileComponents(); }); diff --git a/apps/web/src/app/dirt/reports/pages/unsecured-websites-report.component.spec.ts b/apps/web/src/app/dirt/reports/pages/unsecured-websites-report.component.spec.ts index 040d73a0d66..2107e0c8df7 100644 --- a/apps/web/src/app/dirt/reports/pages/unsecured-websites-report.component.spec.ts +++ b/apps/web/src/app/dirt/reports/pages/unsecured-websites-report.component.spec.ts @@ -1,9 +1,9 @@ +import { ChangeDetectionStrategy, Component } from "@angular/core"; import { ComponentFixture, TestBed } from "@angular/core/testing"; import { MockProxy, mock } from "jest-mock-extended"; import { of } from "rxjs"; import { CollectionService } from "@bitwarden/admin-console/common"; -import { I18nPipe } from "@bitwarden/angular/platform/pipes/i18n.pipe"; import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction"; import { AccountService } from "@bitwarden/common/auth/abstractions/account.service"; import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; @@ -13,6 +13,7 @@ import { UserId } from "@bitwarden/common/types/guid"; import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service"; import { SyncService } from "@bitwarden/common/vault/abstractions/sync/sync.service.abstraction"; import { DialogService } from "@bitwarden/components"; +import { I18nPipe } from "@bitwarden/ui-common"; import { CipherFormConfigService, PasswordRepromptService } from "@bitwarden/vault"; import { AdminConsoleCipherFormConfigService } from "../../../vault/org-vault/services/admin-console-cipher-form-config.service"; @@ -20,6 +21,22 @@ import { AdminConsoleCipherFormConfigService } from "../../../vault/org-vault/se import { cipherData } from "./reports-ciphers.mock"; import { UnsecuredWebsitesReportComponent } from "./unsecured-websites-report.component"; +@Component({ + changeDetection: ChangeDetectionStrategy.OnPush, + selector: "app-header", + template: "
", + standalone: false, +}) +class MockHeaderComponent {} + +@Component({ + changeDetection: ChangeDetectionStrategy.OnPush, + selector: "bit-container", + template: "
", + standalone: false, +}) +class MockBitContainerComponent {} + describe("UnsecuredWebsitesReportComponent", () => { let component: UnsecuredWebsitesReportComponent; let fixture: ComponentFixture; @@ -30,7 +47,7 @@ describe("UnsecuredWebsitesReportComponent", () => { const userId = Utils.newGuid() as UserId; const accountService: FakeAccountService = mockAccountServiceWith(userId); - beforeEach(() => { + beforeEach(async () => { let cipherFormConfigServiceMock: MockProxy; organizationService = mock(); organizationService.organizations$.mockReturnValue(of([])); @@ -38,10 +55,13 @@ describe("UnsecuredWebsitesReportComponent", () => { collectionService = mock(); adminConsoleCipherFormConfigService = mock(); - // FIXME: Verify that this floating promise is intentional. If it is, add an explanatory comment and ensure there is proper error handling. - // eslint-disable-next-line @typescript-eslint/no-floating-promises - TestBed.configureTestingModule({ - declarations: [UnsecuredWebsitesReportComponent, I18nPipe], + await TestBed.configureTestingModule({ + declarations: [ + UnsecuredWebsitesReportComponent, + MockHeaderComponent, + MockBitContainerComponent, + ], + imports: [I18nPipe], providers: [ { provide: CipherService, @@ -85,8 +105,6 @@ describe("UnsecuredWebsitesReportComponent", () => { }, ], schemas: [], - // FIXME(PM-18598): Replace unknownElements and unknownProperties with actual imports - errorOnUnknownElements: false, }).compileComponents(); }); diff --git a/apps/web/src/app/dirt/reports/pages/weak-passwords-report.component.spec.ts b/apps/web/src/app/dirt/reports/pages/weak-passwords-report.component.spec.ts index d78dc7e3ceb..a63723dc688 100644 --- a/apps/web/src/app/dirt/reports/pages/weak-passwords-report.component.spec.ts +++ b/apps/web/src/app/dirt/reports/pages/weak-passwords-report.component.spec.ts @@ -1,8 +1,8 @@ +import { ChangeDetectionStrategy, Component } from "@angular/core"; import { ComponentFixture, TestBed } from "@angular/core/testing"; import { mock, MockProxy } from "jest-mock-extended"; import { of } from "rxjs"; -import { I18nPipe } from "@bitwarden/angular/platform/pipes/i18n.pipe"; import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction"; import { AccountService } from "@bitwarden/common/auth/abstractions/account.service"; import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; @@ -13,6 +13,7 @@ import { UserId } from "@bitwarden/common/types/guid"; import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service"; import { SyncService } from "@bitwarden/common/vault/abstractions/sync/sync.service.abstraction"; import { DialogService } from "@bitwarden/components"; +import { I18nPipe } from "@bitwarden/ui-common"; import { CipherFormConfigService, PasswordRepromptService } from "@bitwarden/vault"; import { AdminConsoleCipherFormConfigService } from "../../../vault/org-vault/services/admin-console-cipher-form-config.service"; @@ -20,6 +21,22 @@ import { AdminConsoleCipherFormConfigService } from "../../../vault/org-vault/se import { cipherData } from "./reports-ciphers.mock"; import { WeakPasswordsReportComponent } from "./weak-passwords-report.component"; +@Component({ + changeDetection: ChangeDetectionStrategy.OnPush, + selector: "app-header", + template: "
", + standalone: false, +}) +class MockHeaderComponent {} + +@Component({ + changeDetection: ChangeDetectionStrategy.OnPush, + selector: "bit-container", + template: "
", + standalone: false, +}) +class MockBitContainerComponent {} + describe("WeakPasswordsReportComponent", () => { let component: WeakPasswordsReportComponent; let fixture: ComponentFixture; @@ -30,16 +47,16 @@ describe("WeakPasswordsReportComponent", () => { const userId = Utils.newGuid() as UserId; const accountService: FakeAccountService = mockAccountServiceWith(userId); - beforeEach(() => { + beforeEach(async () => { let cipherFormConfigServiceMock: MockProxy; syncServiceMock = mock(); passwordStrengthService = mock(); organizationService = mock(); organizationService.organizations$.mockReturnValue(of([])); - // FIXME: Verify that this floating promise is intentional. If it is, add an explanatory comment and ensure there is proper error handling. - // eslint-disable-next-line @typescript-eslint/no-floating-promises - TestBed.configureTestingModule({ - declarations: [WeakPasswordsReportComponent, I18nPipe], + + await TestBed.configureTestingModule({ + declarations: [WeakPasswordsReportComponent, MockHeaderComponent, MockBitContainerComponent], + imports: [I18nPipe], providers: [ { provide: CipherService, @@ -84,8 +101,6 @@ describe("WeakPasswordsReportComponent", () => { }, ], schemas: [], - // FIXME(PM-18598): Replace unknownElements and unknownProperties with actual imports - errorOnUnknownElements: false, }).compileComponents(); }); From 149b3578b4855a63f7b15304bbc6fa49595e1577 Mon Sep 17 00:00:00 2001 From: Jason Ng Date: Tue, 13 Jan 2026 15:40:39 -0500 Subject: [PATCH 6/6] [PM-30734] hide the trash icon on the new item modal (#18342) --- .../vault-item-dialog.component.html | 20 ++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/apps/web/src/app/vault/components/vault-item-dialog/vault-item-dialog.component.html b/apps/web/src/app/vault/components/vault-item-dialog/vault-item-dialog.component.html index 3dce773c7c1..640febf41d2 100644 --- a/apps/web/src/app/vault/components/vault-item-dialog/vault-item-dialog.component.html +++ b/apps/web/src/app/vault/components/vault-item-dialog/vault-item-dialog.component.html @@ -106,15 +106,17 @@ > } } - + @if (cipher) { + + } }