mirror of
https://github.com/bitwarden/browser
synced 2025-12-11 13:53:34 +00:00
[PM-26749] Add missing properties to CipherView.fromJSON (#16818)
This commit is contained in:
@@ -109,6 +109,72 @@ describe("CipherView", () => {
|
|||||||
expect(actual.key).toBeInstanceOf(EncString);
|
expect(actual.key).toBeInstanceOf(EncString);
|
||||||
expect(actual.key?.toJSON()).toBe(cipherKeyObject.toJSON());
|
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", () => {
|
describe("fromSdkCipherView", () => {
|
||||||
|
|||||||
@@ -196,7 +196,19 @@ export class CipherView implements View, InitializerMetadata {
|
|||||||
const view = new CipherView();
|
const view = new CipherView();
|
||||||
view.type = obj.type ?? CipherType.Login;
|
view.type = obj.type ?? CipherType.Login;
|
||||||
view.id = obj.id ?? "";
|
view.id = obj.id ?? "";
|
||||||
|
view.organizationId = obj.organizationId ?? undefined;
|
||||||
|
view.folderId = obj.folderId ?? undefined;
|
||||||
|
view.collectionIds = obj.collectionIds ?? [];
|
||||||
view.name = obj.name ?? "";
|
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) {
|
if (obj.creationDate) {
|
||||||
view.creationDate = new Date(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.fields = obj.fields?.map((f: any) => FieldView.fromJSON(f)) ?? [];
|
||||||
view.passwordHistory =
|
view.passwordHistory =
|
||||||
obj.passwordHistory?.map((ph: any) => PasswordHistoryView.fromJSON(ph)) ?? [];
|
obj.passwordHistory?.map((ph: any) => PasswordHistoryView.fromJSON(ph)) ?? [];
|
||||||
view.permissions = obj.permissions ? CipherPermissionsApi.fromJSON(obj.permissions) : undefined;
|
|
||||||
|
|
||||||
if (obj.key != null) {
|
if (obj.key != null) {
|
||||||
let key: EncString | undefined;
|
let key: EncString | undefined;
|
||||||
|
|||||||
Reference in New Issue
Block a user