1
0
mirror of https://github.com/bitwarden/browser synced 2025-12-23 11:43:46 +00:00

[PM-22693] Firefox - After creating a new item, the View Item screen is blank (#15868)

* Updated get cipher data to retrieve data from observable

* Fixed tests
This commit is contained in:
SmithThe4th
2025-08-14 14:22:45 -04:00
committed by GitHub
parent 736e615ebd
commit 41ad0a7ef9
2 changed files with 39 additions and 29 deletions

View File

@@ -78,14 +78,14 @@ describe("ViewV2Component", () => {
const accountService: FakeAccountService = mockAccountServiceWith(mockUserId);
const mockCipherService = {
get: jest.fn().mockResolvedValue({ decrypt: jest.fn().mockResolvedValue(mockCipher) }),
cipherViews$: jest.fn().mockImplementation((userId) => of([mockCipher])),
getKeyForCipherKeyDecryption: jest.fn().mockResolvedValue({}),
deleteWithServer: jest.fn().mockResolvedValue(undefined),
softDeleteWithServer: jest.fn().mockResolvedValue(undefined),
decrypt: jest.fn().mockResolvedValue(mockCipher),
};
beforeEach(async () => {
mockCipherService.cipherViews$.mockClear();
mockCipherService.deleteWithServer.mockClear();
mockCipherService.softDeleteWithServer.mockClear();
mockNavigate.mockClear();
@@ -162,7 +162,7 @@ describe("ViewV2Component", () => {
flush(); // Resolve all promises
expect(mockCipherService.get).toHaveBeenCalledWith("122-333-444", mockUserId);
expect(mockCipherService.cipherViews$).toHaveBeenCalledWith(mockUserId);
expect(component.cipher).toEqual(mockCipher);
}));
@@ -210,7 +210,7 @@ describe("ViewV2Component", () => {
}));
it('invokes `doAutofill` when action="AUTOFILL_ID"', fakeAsync(() => {
params$.next({ action: AUTOFILL_ID });
params$.next({ action: AUTOFILL_ID, cipherId: mockCipher.id });
flush(); // Resolve all promises
@@ -218,7 +218,7 @@ describe("ViewV2Component", () => {
}));
it('invokes `copy` when action="copy-username"', fakeAsync(() => {
params$.next({ action: COPY_USERNAME_ID });
params$.next({ action: COPY_USERNAME_ID, cipherId: mockCipher.id });
flush(); // Resolve all promises
@@ -226,7 +226,7 @@ describe("ViewV2Component", () => {
}));
it('invokes `copy` when action="copy-password"', fakeAsync(() => {
params$.next({ action: COPY_PASSWORD_ID });
params$.next({ action: COPY_PASSWORD_ID, cipherId: mockCipher.id });
flush(); // Resolve all promises
@@ -234,7 +234,7 @@ describe("ViewV2Component", () => {
}));
it('invokes `copy` when action="copy-totp"', fakeAsync(() => {
params$.next({ action: COPY_VERIFICATION_CODE_ID });
params$.next({ action: COPY_VERIFICATION_CODE_ID, cipherId: mockCipher.id });
flush(); // Resolve all promises
@@ -243,11 +243,13 @@ describe("ViewV2Component", () => {
it("does not set the cipher until reprompt is complete", fakeAsync(() => {
let promptPromise: (val?: unknown) => void;
mockCipherService.decrypt.mockImplementationOnce(() =>
Promise.resolve({
...mockCipher,
reprompt: CipherRepromptType.Password,
}),
mockCipherService.cipherViews$.mockImplementationOnce((userId) =>
of([
{
...mockCipher,
reprompt: CipherRepromptType.Password,
},
]),
);
doAutofill.mockImplementationOnce(() => {
return new Promise((resolve) => {
@@ -256,7 +258,7 @@ describe("ViewV2Component", () => {
});
});
params$.next({ action: AUTOFILL_ID });
params$.next({ action: AUTOFILL_ID, cipherId: mockCipher.id });
flush(); // Flush all pending actions
@@ -271,11 +273,13 @@ describe("ViewV2Component", () => {
it("does not set the cipher at all if doAutofill fails and reprompt is active", fakeAsync(() => {
let promptPromise: (val?: unknown) => void;
mockCipherService.decrypt.mockImplementationOnce(() =>
Promise.resolve({
...mockCipher,
reprompt: CipherRepromptType.Password,
}),
mockCipherService.cipherViews$.mockImplementationOnce((userId) =>
of([
{
...mockCipher,
reprompt: CipherRepromptType.Password,
},
]),
);
doAutofill.mockImplementationOnce(() => {
return new Promise((resolve) => {
@@ -284,7 +288,7 @@ describe("ViewV2Component", () => {
});
});
params$.next({ action: AUTOFILL_ID });
params$.next({ action: AUTOFILL_ID, cipherId: mockCipher.id });
flush(); // Flush all pending actions
@@ -301,11 +305,13 @@ describe("ViewV2Component", () => {
"does not set cipher when copy fails for %s",
fakeAsync((action: string) => {
let promptPromise: (val?: unknown) => void;
mockCipherService.decrypt.mockImplementationOnce(() =>
Promise.resolve({
...mockCipher,
reprompt: CipherRepromptType.Password,
}),
mockCipherService.cipherViews$.mockImplementationOnce((userId) =>
of([
{
...mockCipher,
reprompt: CipherRepromptType.Password,
},
]),
);
copy.mockImplementationOnce(() => {
return new Promise((resolve) => {
@@ -314,7 +320,7 @@ describe("ViewV2Component", () => {
});
});
params$.next({ action });
params$.next({ action, cipherId: mockCipher.id });
flush(); // Flush all pending actions
@@ -336,7 +342,7 @@ describe("ViewV2Component", () => {
.spyOn(BrowserApi, "focusTab")
.mockImplementation(() => Promise.resolve());
params$.next({ action: AUTOFILL_ID, senderTabId: 99 });
params$.next({ action: AUTOFILL_ID, senderTabId: 99, cipherId: mockCipher.id });
flush(); // Resolve all promises

View File

@@ -5,7 +5,7 @@ import { Component } from "@angular/core";
import { takeUntilDestroyed } from "@angular/core/rxjs-interop";
import { FormsModule } from "@angular/forms";
import { ActivatedRoute, Router } from "@angular/router";
import { firstValueFrom, Observable, switchMap, of } from "rxjs";
import { firstValueFrom, Observable, switchMap, of, map } from "rxjs";
import { CollectionView } from "@bitwarden/admin-console/common";
import { JslibModule } from "@bitwarden/angular/jslib.module";
@@ -209,8 +209,12 @@ export class ViewV2Component {
}
async getCipherData(id: string, userId: UserId) {
const cipher = await this.cipherService.get(id, userId);
return await this.cipherService.decrypt(cipher, userId);
return await firstValueFrom(
this.cipherService.cipherViews$(userId).pipe(
filterOutNullish(),
map((ciphers) => ciphers.find((c) => c.id === id)),
),
);
}
async editCipher() {