mirror of
https://github.com/bitwarden/browser
synced 2026-02-28 10:33:31 +00:00
* add `CipherViewLike` and utilities to handle `CipherView` and `CipherViewLike` * migrate libs needed for web vault to support `CipherViewLike` * migrate web vault components to support * add for CipherView. will have to be later * fetch full CipherView for copying a password * have only the cipher service utilize SDK migration flag - This keeps feature flag logic away from the component - Also cuts down on what is needed for other platforms * strongly type CipherView for AC vault - Probably temporary before migration of the AC vault to `CipherListView` SDK * fix build icon tests by being more gracious with the uri structure * migrate desktop components to CipherListViews$ * consume card from sdk * add browser implementation for `CipherListView` * update copy message for single copiable items * refactor `getCipherViewLikeLogin` to `getLogin` * refactor `getCipherViewLikeCard` to `getCard` * add `hasFido2Credentials` helper * add decryption failure to cipher like utils * add todo with ticket * fix decryption failure typing * fix copy card messages * fix addition of organizations and collections for `PopupCipherViewLike` - accessors were being lost * refactor to getters to fix re-rendering bug * fix decryption failure helper * fix sorting functions for `CipherViewLike` * formatting * add `CipherViewLikeUtils` tests * refactor "copiable" to "copyable" to match SDK * use `hasOldAttachments` from cipherlistview * fix typing * update SDK version * add feature flag for cipher list view work * use `CipherViewLikeUtils` for copyable values rather than referring to the cipher directly * update restricted item type to support CipherViewLike * add cipher support to `CipherViewLikeUtils` * update `isCipherListView` check * refactor CipherLike to a separate type * refactor `getFullCipherView` into the cipher service * add optional chaining for `uriChecksum` * set empty array for decrypted CipherListView * migrate nudge service to use `cipherListViews` * update web vault to not depend on `cipherViews$` * update popup list filters to use `CipherListView` * fix storybook * fix tests * accept undefined as a MY VAULT filter value for cipher list views * use `LoginUriView` for uri logic (#15530) * filter out null ciphers from the `_allDecryptedCiphers$` (#15539) * use `launchUri` to avoid any unexpected behavior in URIs - this appends `http://` when missing
625 lines
22 KiB
TypeScript
625 lines
22 KiB
TypeScript
import { CipherListView } from "@bitwarden/sdk-internal";
|
|
|
|
import { CipherType } from "../enums";
|
|
import { Attachment } from "../models/domain/attachment";
|
|
import { AttachmentView } from "../models/view/attachment.view";
|
|
import { CipherView } from "../models/view/cipher.view";
|
|
import { Fido2CredentialView } from "../models/view/fido2-credential.view";
|
|
import { IdentityView } from "../models/view/identity.view";
|
|
import { LoginUriView } from "../models/view/login-uri.view";
|
|
import { LoginView } from "../models/view/login.view";
|
|
|
|
import { CipherViewLikeUtils } from "./cipher-view-like-utils";
|
|
|
|
describe("CipherViewLikeUtils", () => {
|
|
const createCipherView = (type: CipherType = CipherType.Login): CipherView => {
|
|
const cipherView = new CipherView();
|
|
// Always set a type to avoid issues within `CipherViewLikeUtils`
|
|
cipherView.type = type;
|
|
|
|
return cipherView;
|
|
};
|
|
|
|
describe("isCipherListView", () => {
|
|
it("returns true when the cipher is a CipherListView", () => {
|
|
const cipherListViewLogin = {
|
|
type: {
|
|
login: {},
|
|
},
|
|
} as CipherListView;
|
|
const cipherListViewSshKey = {
|
|
type: "sshKey",
|
|
} as CipherListView;
|
|
|
|
expect(CipherViewLikeUtils.isCipherListView(cipherListViewLogin)).toBe(true);
|
|
expect(CipherViewLikeUtils.isCipherListView(cipherListViewSshKey)).toBe(true);
|
|
});
|
|
|
|
it("returns false when the cipher is not a CipherListView", () => {
|
|
const cipherView = createCipherView();
|
|
cipherView.type = CipherType.SecureNote;
|
|
|
|
expect(CipherViewLikeUtils.isCipherListView(cipherView)).toBe(false);
|
|
});
|
|
});
|
|
|
|
describe("getLogin", () => {
|
|
it("returns null when the cipher is not a login", () => {
|
|
const cipherView = createCipherView(CipherType.SecureNote);
|
|
|
|
expect(CipherViewLikeUtils.getLogin(cipherView)).toBeNull();
|
|
expect(CipherViewLikeUtils.getLogin({ type: "identity" } as CipherListView)).toBeNull();
|
|
});
|
|
|
|
describe("CipherView", () => {
|
|
it("returns the login object", () => {
|
|
const cipherView = createCipherView(CipherType.Login);
|
|
|
|
expect(CipherViewLikeUtils.getLogin(cipherView)).toEqual(cipherView.login);
|
|
});
|
|
});
|
|
|
|
describe("CipherListView", () => {
|
|
it("returns the login object", () => {
|
|
const cipherListView = {
|
|
type: {
|
|
login: {
|
|
username: "testuser",
|
|
hasFido2: false,
|
|
},
|
|
},
|
|
} as CipherListView;
|
|
|
|
expect(CipherViewLikeUtils.getLogin(cipherListView)).toEqual(
|
|
(cipherListView.type as any).login,
|
|
);
|
|
});
|
|
});
|
|
});
|
|
|
|
describe("getCard", () => {
|
|
it("returns null when the cipher is not a card", () => {
|
|
const cipherView = createCipherView(CipherType.SecureNote);
|
|
|
|
expect(CipherViewLikeUtils.getCard(cipherView)).toBeNull();
|
|
expect(CipherViewLikeUtils.getCard({ type: "identity" } as CipherListView)).toBeNull();
|
|
});
|
|
|
|
describe("CipherView", () => {
|
|
it("returns the card object", () => {
|
|
const cipherView = createCipherView(CipherType.Card);
|
|
|
|
expect(CipherViewLikeUtils.getCard(cipherView)).toEqual(cipherView.card);
|
|
});
|
|
});
|
|
|
|
describe("CipherListView", () => {
|
|
it("returns the card object", () => {
|
|
const cipherListView = {
|
|
type: {
|
|
card: {
|
|
brand: "Visa",
|
|
},
|
|
},
|
|
} as CipherListView;
|
|
|
|
expect(CipherViewLikeUtils.getCard(cipherListView)).toEqual(
|
|
(cipherListView.type as any).card,
|
|
);
|
|
});
|
|
});
|
|
});
|
|
|
|
describe("isDeleted", () => {
|
|
it("returns true when the cipher is deleted", () => {
|
|
const cipherListView = { deletedDate: "2024-02-02", type: "identity" } as CipherListView;
|
|
const cipherView = createCipherView();
|
|
cipherView.deletedDate = new Date();
|
|
|
|
expect(CipherViewLikeUtils.isDeleted(cipherListView)).toBe(true);
|
|
expect(CipherViewLikeUtils.isDeleted(cipherView)).toBe(true);
|
|
});
|
|
|
|
it("returns false when the cipher is not deleted", () => {
|
|
const cipherListView = { deletedDate: undefined, type: "identity" } as CipherListView;
|
|
const cipherView = createCipherView();
|
|
|
|
expect(CipherViewLikeUtils.isDeleted(cipherListView)).toBe(false);
|
|
expect(CipherViewLikeUtils.isDeleted(cipherView)).toBe(false);
|
|
});
|
|
});
|
|
|
|
describe("canAssignToCollections", () => {
|
|
describe("CipherView", () => {
|
|
let cipherView: CipherView;
|
|
|
|
beforeEach(() => {
|
|
cipherView = createCipherView();
|
|
});
|
|
|
|
it("returns true when the cipher is not assigned to an organization", () => {
|
|
expect(CipherViewLikeUtils.canAssignToCollections(cipherView)).toBe(true);
|
|
});
|
|
|
|
it("returns false when the cipher is assigned to an organization and cannot be edited", () => {
|
|
cipherView.organizationId = "org-id";
|
|
cipherView.edit = false;
|
|
cipherView.viewPassword = false;
|
|
|
|
expect(CipherViewLikeUtils.canAssignToCollections(cipherView)).toBe(false);
|
|
});
|
|
|
|
it("returns true when the cipher is assigned to an organization and can be edited", () => {
|
|
cipherView.organizationId = "org-id";
|
|
cipherView.edit = true;
|
|
cipherView.viewPassword = true;
|
|
|
|
expect(CipherViewLikeUtils.canAssignToCollections(cipherView)).toBe(true);
|
|
});
|
|
});
|
|
|
|
describe("CipherListView", () => {
|
|
let cipherListView: CipherListView;
|
|
|
|
beforeEach(() => {
|
|
cipherListView = {
|
|
organizationId: undefined,
|
|
edit: false,
|
|
viewPassword: false,
|
|
type: { login: {} },
|
|
} as CipherListView;
|
|
});
|
|
|
|
it("returns true when the cipher is not assigned to an organization", () => {
|
|
expect(CipherViewLikeUtils.canAssignToCollections(cipherListView)).toBe(true);
|
|
});
|
|
|
|
it("returns false when the cipher is assigned to an organization and cannot be edited", () => {
|
|
cipherListView.organizationId = "org-id";
|
|
|
|
expect(CipherViewLikeUtils.canAssignToCollections(cipherListView)).toBe(false);
|
|
});
|
|
|
|
it("returns true when the cipher is assigned to an organization and can be edited", () => {
|
|
cipherListView.organizationId = "org-id";
|
|
cipherListView.edit = true;
|
|
cipherListView.viewPassword = true;
|
|
|
|
expect(CipherViewLikeUtils.canAssignToCollections(cipherListView)).toBe(true);
|
|
});
|
|
});
|
|
});
|
|
|
|
describe("getType", () => {
|
|
describe("CipherView", () => {
|
|
it("returns the type of the cipher", () => {
|
|
const cipherView = createCipherView();
|
|
cipherView.type = CipherType.Login;
|
|
|
|
expect(CipherViewLikeUtils.getType(cipherView)).toBe(CipherType.Login);
|
|
|
|
cipherView.type = CipherType.SecureNote;
|
|
expect(CipherViewLikeUtils.getType(cipherView)).toBe(CipherType.SecureNote);
|
|
|
|
cipherView.type = CipherType.SshKey;
|
|
expect(CipherViewLikeUtils.getType(cipherView)).toBe(CipherType.SshKey);
|
|
|
|
cipherView.type = CipherType.Identity;
|
|
expect(CipherViewLikeUtils.getType(cipherView)).toBe(CipherType.Identity);
|
|
|
|
cipherView.type = CipherType.Card;
|
|
expect(CipherViewLikeUtils.getType(cipherView)).toBe(CipherType.Card);
|
|
});
|
|
});
|
|
|
|
describe("CipherListView", () => {
|
|
it("converts the `CipherViewListType` to `CipherType`", () => {
|
|
const cipherListView = {
|
|
type: { login: {} },
|
|
} as CipherListView;
|
|
|
|
expect(CipherViewLikeUtils.getType(cipherListView)).toBe(CipherType.Login);
|
|
|
|
cipherListView.type = { card: { brand: "Visa" } };
|
|
expect(CipherViewLikeUtils.getType(cipherListView)).toBe(CipherType.Card);
|
|
|
|
cipherListView.type = "sshKey";
|
|
expect(CipherViewLikeUtils.getType(cipherListView)).toBe(CipherType.SshKey);
|
|
|
|
cipherListView.type = "identity";
|
|
expect(CipherViewLikeUtils.getType(cipherListView)).toBe(CipherType.Identity);
|
|
|
|
cipherListView.type = "secureNote";
|
|
expect(CipherViewLikeUtils.getType(cipherListView)).toBe(CipherType.SecureNote);
|
|
});
|
|
});
|
|
});
|
|
|
|
describe("subtitle", () => {
|
|
describe("CipherView", () => {
|
|
it("returns the subtitle of the cipher", () => {
|
|
const cipherView = createCipherView();
|
|
cipherView.login = new LoginView();
|
|
cipherView.login.username = "Test Username";
|
|
|
|
expect(CipherViewLikeUtils.subtitle(cipherView)).toBe("Test Username");
|
|
});
|
|
});
|
|
|
|
describe("CipherListView", () => {
|
|
it("returns the subtitle of the cipher", () => {
|
|
const cipherListView = {
|
|
subtitle: "Test Subtitle",
|
|
type: "identity",
|
|
} as CipherListView;
|
|
|
|
expect(CipherViewLikeUtils.subtitle(cipherListView)).toBe("Test Subtitle");
|
|
});
|
|
});
|
|
});
|
|
|
|
describe("hasAttachments", () => {
|
|
describe("CipherView", () => {
|
|
it("returns true when the cipher has attachments", () => {
|
|
const cipherView = createCipherView();
|
|
cipherView.attachments = [new AttachmentView({ id: "1" } as Attachment)];
|
|
|
|
expect(CipherViewLikeUtils.hasAttachments(cipherView)).toBe(true);
|
|
});
|
|
|
|
it("returns false when the cipher has no attachments", () => {
|
|
const cipherView = new CipherView();
|
|
(cipherView.attachments as any) = null;
|
|
|
|
expect(CipherViewLikeUtils.hasAttachments(cipherView)).toBe(false);
|
|
});
|
|
});
|
|
|
|
describe("CipherListView", () => {
|
|
it("returns true when there are attachments", () => {
|
|
const cipherListView = { attachments: 1, type: "secureNote" } as CipherListView;
|
|
|
|
expect(CipherViewLikeUtils.hasAttachments(cipherListView)).toBe(true);
|
|
});
|
|
|
|
it("returns false when there are no attachments", () => {
|
|
const cipherListView = { attachments: 0, type: "secureNote" } as CipherListView;
|
|
|
|
expect(CipherViewLikeUtils.hasAttachments(cipherListView)).toBe(false);
|
|
});
|
|
});
|
|
});
|
|
|
|
describe("canLaunch", () => {
|
|
it("returns false when the cipher is not a login", () => {
|
|
const cipherView = createCipherView(CipherType.SecureNote);
|
|
|
|
expect(CipherViewLikeUtils.canLaunch(cipherView)).toBe(false);
|
|
expect(CipherViewLikeUtils.canLaunch({ type: "identity" } as CipherListView)).toBe(false);
|
|
});
|
|
|
|
describe("CipherView", () => {
|
|
it("returns true when the login has URIs that can be launched", () => {
|
|
const cipherView = createCipherView(CipherType.Login);
|
|
cipherView.login = new LoginView();
|
|
cipherView.login.uris = [{ uri: "https://example.com" } as LoginUriView];
|
|
|
|
expect(CipherViewLikeUtils.canLaunch(cipherView)).toBe(true);
|
|
});
|
|
|
|
it("returns true when the uri does not have a protocol", () => {
|
|
const cipherView = createCipherView(CipherType.Login);
|
|
cipherView.login = new LoginView();
|
|
const uriView = new LoginUriView();
|
|
uriView.uri = "bitwarden.com";
|
|
cipherView.login.uris = [uriView];
|
|
|
|
expect(CipherViewLikeUtils.canLaunch(cipherView)).toBe(true);
|
|
});
|
|
|
|
it("returns false when the login has no URIs", () => {
|
|
const cipherView = createCipherView(CipherType.Login);
|
|
cipherView.login = new LoginView();
|
|
|
|
expect(CipherViewLikeUtils.canLaunch(cipherView)).toBe(false);
|
|
});
|
|
});
|
|
|
|
describe("CipherListView", () => {
|
|
it("returns true when the login has URIs that can be launched", () => {
|
|
const cipherListView = {
|
|
type: { login: { uris: [{ uri: "https://example.com" }] } },
|
|
} as CipherListView;
|
|
|
|
expect(CipherViewLikeUtils.canLaunch(cipherListView)).toBe(true);
|
|
});
|
|
|
|
it("returns true when the uri does not have a protocol", () => {
|
|
const cipherListView = {
|
|
type: { login: { uris: [{ uri: "bitwarden.com" }] } },
|
|
} as CipherListView;
|
|
|
|
expect(CipherViewLikeUtils.canLaunch(cipherListView)).toBe(true);
|
|
});
|
|
|
|
it("returns false when the login has no URIs", () => {
|
|
const cipherListView = { type: { login: {} } } as CipherListView;
|
|
|
|
expect(CipherViewLikeUtils.canLaunch(cipherListView)).toBe(false);
|
|
});
|
|
});
|
|
});
|
|
|
|
describe("getLaunchUri", () => {
|
|
it("returns undefined when the cipher is not a login", () => {
|
|
const cipherView = createCipherView(CipherType.SecureNote);
|
|
|
|
expect(CipherViewLikeUtils.getLaunchUri(cipherView)).toBeUndefined();
|
|
expect(
|
|
CipherViewLikeUtils.getLaunchUri({ type: "identity" } as CipherListView),
|
|
).toBeUndefined();
|
|
});
|
|
|
|
describe("CipherView", () => {
|
|
it("returns the first launch-able URI", () => {
|
|
const cipherView = createCipherView(CipherType.Login);
|
|
cipherView.login = new LoginView();
|
|
cipherView.login.uris = [
|
|
{ uri: "" } as LoginUriView,
|
|
{ uri: "https://example.com" } as LoginUriView,
|
|
{ uri: "https://another.com" } as LoginUriView,
|
|
];
|
|
|
|
expect(CipherViewLikeUtils.getLaunchUri(cipherView)).toBe("https://example.com");
|
|
});
|
|
|
|
it("returns undefined when there are no URIs", () => {
|
|
const cipherView = createCipherView(CipherType.Login);
|
|
cipherView.login = new LoginView();
|
|
|
|
expect(CipherViewLikeUtils.getLaunchUri(cipherView)).toBeUndefined();
|
|
});
|
|
|
|
it("appends protocol when there are none", () => {
|
|
const cipherView = createCipherView(CipherType.Login);
|
|
cipherView.login = new LoginView();
|
|
const uriView = new LoginUriView();
|
|
uriView.uri = "bitwarden.com";
|
|
cipherView.login.uris = [uriView];
|
|
|
|
expect(CipherViewLikeUtils.getLaunchUri(cipherView)).toBe("http://bitwarden.com");
|
|
});
|
|
});
|
|
|
|
describe("CipherListView", () => {
|
|
it("returns the first launch-able URI", () => {
|
|
const cipherListView = {
|
|
type: { login: { uris: [{ uri: "" }, { uri: "https://example.com" }] } },
|
|
} as CipherListView;
|
|
|
|
expect(CipherViewLikeUtils.getLaunchUri(cipherListView)).toBe("https://example.com");
|
|
});
|
|
|
|
it("returns undefined when there are no URIs", () => {
|
|
const cipherListView = { type: { login: {} } } as CipherListView;
|
|
|
|
expect(CipherViewLikeUtils.getLaunchUri(cipherListView)).toBeUndefined();
|
|
});
|
|
});
|
|
});
|
|
|
|
describe("matchesUri", () => {
|
|
const emptySet = new Set<string>();
|
|
|
|
it("returns false when the cipher is not a login", () => {
|
|
const cipherView = createCipherView(CipherType.SecureNote);
|
|
|
|
expect(CipherViewLikeUtils.matchesUri(cipherView, "https://example.com", emptySet)).toBe(
|
|
false,
|
|
);
|
|
});
|
|
|
|
describe("CipherView", () => {
|
|
it("returns true when the URI matches", () => {
|
|
const cipherView = createCipherView(CipherType.Login);
|
|
cipherView.login = new LoginView();
|
|
const uri = new LoginUriView();
|
|
uri.uri = "https://example.com";
|
|
cipherView.login.uris = [uri];
|
|
|
|
expect(CipherViewLikeUtils.matchesUri(cipherView, "https://example.com", emptySet)).toBe(
|
|
true,
|
|
);
|
|
});
|
|
|
|
it("returns false when the URI does not match", () => {
|
|
const cipherView = createCipherView(CipherType.Login);
|
|
cipherView.login = new LoginView();
|
|
const uri = new LoginUriView();
|
|
uri.uri = "https://www.bitwarden.com";
|
|
cipherView.login.uris = [uri];
|
|
|
|
expect(
|
|
CipherViewLikeUtils.matchesUri(cipherView, "https://www.another.com", emptySet),
|
|
).toBe(false);
|
|
});
|
|
});
|
|
|
|
describe("CipherListView", () => {
|
|
it("returns true when the URI matches", () => {
|
|
const cipherListView = {
|
|
type: { login: { uris: [{ uri: "https://example.com" }] } },
|
|
} as CipherListView;
|
|
|
|
expect(
|
|
CipherViewLikeUtils.matchesUri(cipherListView, "https://example.com", emptySet),
|
|
).toBe(true);
|
|
});
|
|
|
|
it("returns false when the URI does not match", () => {
|
|
const cipherListView = {
|
|
type: { login: { uris: [{ uri: "https://bitwarden.com" }] } },
|
|
} as CipherListView;
|
|
|
|
expect(
|
|
CipherViewLikeUtils.matchesUri(cipherListView, "https://another.com", emptySet),
|
|
).toBe(false);
|
|
});
|
|
});
|
|
});
|
|
|
|
describe("hasCopyableValue", () => {
|
|
describe("CipherView", () => {
|
|
it("returns true for login fields", () => {
|
|
const cipherView = createCipherView(CipherType.Login);
|
|
cipherView.login = new LoginView();
|
|
cipherView.login.username = "testuser";
|
|
cipherView.login.password = "testpass";
|
|
|
|
expect(CipherViewLikeUtils.hasCopyableValue(cipherView, "username")).toBe(true);
|
|
expect(CipherViewLikeUtils.hasCopyableValue(cipherView, "password")).toBe(true);
|
|
});
|
|
|
|
it("returns true for card fields", () => {
|
|
const cipherView = createCipherView(CipherType.Card);
|
|
cipherView.card = { number: "1234-5678-9012-3456", code: "123" } as any;
|
|
|
|
expect(CipherViewLikeUtils.hasCopyableValue(cipherView, "cardNumber")).toBe(true);
|
|
expect(CipherViewLikeUtils.hasCopyableValue(cipherView, "securityCode")).toBe(true);
|
|
});
|
|
|
|
it("returns true for identity fields", () => {
|
|
const cipherView = createCipherView(CipherType.Identity);
|
|
cipherView.identity = new IdentityView();
|
|
cipherView.identity.email = "example@bitwarden.com";
|
|
cipherView.identity.phone = "123-456-7890";
|
|
|
|
expect(CipherViewLikeUtils.hasCopyableValue(cipherView, "email")).toBe(true);
|
|
expect(CipherViewLikeUtils.hasCopyableValue(cipherView, "phone")).toBe(true);
|
|
});
|
|
|
|
it("returns false when values are not populated", () => {
|
|
const cipherView = createCipherView(CipherType.Login);
|
|
|
|
expect(CipherViewLikeUtils.hasCopyableValue(cipherView, "email")).toBe(false);
|
|
expect(CipherViewLikeUtils.hasCopyableValue(cipherView, "password")).toBe(false);
|
|
expect(CipherViewLikeUtils.hasCopyableValue(cipherView, "securityCode")).toBe(false);
|
|
expect(CipherViewLikeUtils.hasCopyableValue(cipherView, "username")).toBe(false);
|
|
});
|
|
});
|
|
|
|
describe("CipherListView", () => {
|
|
it("returns true for copyable fields in a login cipher", () => {
|
|
const cipherListView = {
|
|
type: { login: { username: "testuser" } },
|
|
copyableFields: ["LoginUsername", "LoginPassword"],
|
|
} as CipherListView;
|
|
|
|
expect(CipherViewLikeUtils.hasCopyableValue(cipherListView, "username")).toBe(true);
|
|
expect(CipherViewLikeUtils.hasCopyableValue(cipherListView, "password")).toBe(true);
|
|
});
|
|
|
|
it("returns true for copyable fields in a card cipher", () => {
|
|
const cipherListView = {
|
|
type: { card: { brand: "MasterCard" } },
|
|
copyableFields: ["CardNumber", "CardSecurityCode"],
|
|
} as CipherListView;
|
|
|
|
expect(CipherViewLikeUtils.hasCopyableValue(cipherListView, "cardNumber")).toBe(true);
|
|
expect(CipherViewLikeUtils.hasCopyableValue(cipherListView, "securityCode")).toBe(true);
|
|
});
|
|
|
|
it("returns true for copyable fields in an sshKey ciphers", () => {
|
|
const cipherListView = {
|
|
type: "sshKey",
|
|
copyableFields: ["SshKey"],
|
|
} as CipherListView;
|
|
|
|
expect(CipherViewLikeUtils.hasCopyableValue(cipherListView, "privateKey")).toBe(true);
|
|
expect(CipherViewLikeUtils.hasCopyableValue(cipherListView, "publicKey")).toBe(true);
|
|
expect(CipherViewLikeUtils.hasCopyableValue(cipherListView, "keyFingerprint")).toBe(true);
|
|
});
|
|
|
|
it("returns true for copyable fields in an identity cipher", () => {
|
|
const cipherListView = {
|
|
type: "identity",
|
|
copyableFields: ["IdentityUsername", "IdentityEmail", "IdentityPhone"],
|
|
} as CipherListView;
|
|
|
|
expect(CipherViewLikeUtils.hasCopyableValue(cipherListView, "username")).toBe(true);
|
|
expect(CipherViewLikeUtils.hasCopyableValue(cipherListView, "email")).toBe(true);
|
|
expect(CipherViewLikeUtils.hasCopyableValue(cipherListView, "phone")).toBe(true);
|
|
});
|
|
|
|
it("returns false for when missing a field", () => {
|
|
const cipherListView = {
|
|
type: { login: {} },
|
|
copyableFields: ["LoginUsername"],
|
|
} as CipherListView;
|
|
|
|
expect(CipherViewLikeUtils.hasCopyableValue(cipherListView, "password")).toBe(false);
|
|
expect(CipherViewLikeUtils.hasCopyableValue(cipherListView, "phone")).toBe(false);
|
|
expect(CipherViewLikeUtils.hasCopyableValue(cipherListView, "address")).toBe(false);
|
|
expect(CipherViewLikeUtils.hasCopyableValue(cipherListView, "publicKey")).toBe(false);
|
|
});
|
|
});
|
|
});
|
|
|
|
describe("hasFido2Credentials", () => {
|
|
describe("CipherView", () => {
|
|
it("returns true when the login has FIDO2 credentials", () => {
|
|
const cipherView = createCipherView(CipherType.Login);
|
|
cipherView.login = new LoginView();
|
|
cipherView.login.fido2Credentials = [new Fido2CredentialView()];
|
|
|
|
expect(CipherViewLikeUtils.hasFido2Credentials(cipherView)).toBe(true);
|
|
});
|
|
|
|
it("returns false when the login has no FIDO2 credentials", () => {
|
|
const cipherView = createCipherView(CipherType.Login);
|
|
cipherView.login = new LoginView();
|
|
|
|
expect(CipherViewLikeUtils.hasFido2Credentials(cipherView)).toBe(false);
|
|
});
|
|
});
|
|
|
|
describe("CipherListView", () => {
|
|
it("returns true when the login has FIDO2 credentials", () => {
|
|
const cipherListView = {
|
|
type: { login: { fido2Credentials: [{ credentialId: "fido2-1" }] } },
|
|
} as CipherListView;
|
|
|
|
expect(CipherViewLikeUtils.hasFido2Credentials(cipherListView)).toBe(true);
|
|
});
|
|
|
|
it("returns false when the login has no FIDO2 credentials", () => {
|
|
const cipherListView = { type: { login: {} } } as CipherListView;
|
|
|
|
expect(CipherViewLikeUtils.hasFido2Credentials(cipherListView)).toBe(false);
|
|
});
|
|
});
|
|
});
|
|
|
|
describe("decryptionFailure", () => {
|
|
it("returns true when the cipher has a decryption failure", () => {
|
|
const cipherView = createCipherView();
|
|
cipherView.decryptionFailure = true;
|
|
|
|
expect(CipherViewLikeUtils.decryptionFailure(cipherView)).toBe(true);
|
|
});
|
|
|
|
it("returns false when the cipher does not have a decryption failure", () => {
|
|
const cipherView = createCipherView();
|
|
cipherView.decryptionFailure = false;
|
|
|
|
expect(CipherViewLikeUtils.decryptionFailure(cipherView)).toBe(false);
|
|
});
|
|
|
|
it("returns false when the cipher is a CipherListView without decryptionFailure", () => {
|
|
const cipherListView = { type: "secureNote" } as CipherListView;
|
|
|
|
expect(CipherViewLikeUtils.decryptionFailure(cipherListView)).toBe(false);
|
|
});
|
|
});
|
|
});
|