1
0
mirror of https://github.com/bitwarden/browser synced 2025-12-06 00:13:28 +00:00

[PM-26749] Add missing properties to CipherView.fromJSON (#16818)

This commit is contained in:
Shane Melton
2025-10-09 14:02:12 -07:00
committed by GitHub
parent 3ba6cfa8de
commit 081cc4fc65
2 changed files with 78 additions and 1 deletions

View File

@@ -109,6 +109,72 @@ describe("CipherView", () => {
expect(actual.key).toBeInstanceOf(EncString);
expect(actual.key?.toJSON()).toBe(cipherKeyObject.toJSON());
});
it("fromJSON should always restore top-level CipherView properties", () => {
jest.spyOn(LoginView, "fromJSON").mockImplementation(mockFromJson);
// Create a fully populated CipherView instance
const original = new CipherView();
original.id = "test-id";
original.organizationId = "org-id";
original.folderId = "folder-id";
original.name = "test-name";
original.notes = "test-notes";
original.type = CipherType.Login;
original.favorite = true;
original.organizationUseTotp = true;
original.permissions = new CipherPermissionsApi();
original.edit = true;
original.viewPassword = false;
original.localData = { lastUsedDate: Date.now() };
original.login = new LoginView();
original.identity = new IdentityView();
original.card = new CardView();
original.secureNote = new SecureNoteView();
original.sshKey = new SshKeyView();
original.attachments = [];
original.fields = [];
original.passwordHistory = [];
original.collectionIds = ["collection-1"];
original.revisionDate = new Date("2022-01-01");
original.creationDate = new Date("2022-01-02");
original.deletedDate = new Date("2022-01-03");
original.archivedDate = new Date("2022-01-04");
original.reprompt = CipherRepromptType.Password;
original.key = new EncString("test-key");
original.decryptionFailure = true;
// Serialize and deserialize
const json = original.toJSON();
const restored = CipherView.fromJSON(json as any);
// Get all enumerable properties from the original instance
const originalProps = Object.keys(original);
// Check that all properties exist on the restored instance
for (const prop of originalProps) {
try {
expect(restored).toHaveProperty(prop);
} catch {
throw new Error(`Property '${prop}' is missing from restored instance`);
}
// For non-function, non-getter properties, verify the value is defined
const descriptor = Object.getOwnPropertyDescriptor(CipherView.prototype, prop);
if (!descriptor?.get && typeof (original as any)[prop] !== "function") {
try {
expect((restored as any)[prop]).toBeDefined();
} catch {
throw new Error(`Property '${prop}' is undefined in restored instance`);
}
}
}
// Verify restored instance has the same properties as original
const restoredProps = Object.keys(restored!).sort();
const sortedOriginalProps = originalProps.sort();
expect(restoredProps).toEqual(sortedOriginalProps);
});
});
describe("fromSdkCipherView", () => {

View File

@@ -196,7 +196,19 @@ export class CipherView implements View, InitializerMetadata {
const view = new CipherView();
view.type = obj.type ?? CipherType.Login;
view.id = obj.id ?? "";
view.organizationId = obj.organizationId ?? undefined;
view.folderId = obj.folderId ?? undefined;
view.collectionIds = obj.collectionIds ?? [];
view.name = obj.name ?? "";
view.notes = obj.notes;
view.edit = obj.edit ?? false;
view.viewPassword = obj.viewPassword ?? true;
view.favorite = obj.favorite ?? false;
view.organizationUseTotp = obj.organizationUseTotp ?? false;
view.localData = obj.localData ? obj.localData : undefined;
view.permissions = obj.permissions ? CipherPermissionsApi.fromJSON(obj.permissions) : undefined;
view.reprompt = obj.reprompt ?? CipherRepromptType.None;
view.decryptionFailure = obj.decryptionFailure ?? false;
if (obj.creationDate) {
view.creationDate = new Date(obj.creationDate);
}
@@ -209,7 +221,6 @@ export class CipherView implements View, InitializerMetadata {
view.fields = obj.fields?.map((f: any) => FieldView.fromJSON(f)) ?? [];
view.passwordHistory =
obj.passwordHistory?.map((ph: any) => PasswordHistoryView.fromJSON(ph)) ?? [];
view.permissions = obj.permissions ? CipherPermissionsApi.fromJSON(obj.permissions) : undefined;
if (obj.key != null) {
let key: EncString | undefined;