passbolt-styleguide
Version:
Passbolt styleguide contains common styling assets used by the different sites, plugin, etc.
383 lines (301 loc) • 15.9 kB
JavaScript
/**
* Passbolt ~ Open source password manager for teams
* Copyright (c) Passbolt SA (https://www.passbolt.com)
*
* Licensed under GNU Affero General Public License version 3 of the or any later version.
* For full copyright and license information, please see the LICENSE.txt
* Redistributions of files must retain the above copyright notice.
*
* @copyright Copyright (c) Passbolt SA (https://www.passbolt.com)
* @license https://opensource.org/licenses/AGPL-3.0 AGPL License
* @link https://www.passbolt.com Passbolt(tm)
* @since 5.0.0
*/
import DisplayResourceCreationMenuPage from "./DisplayResourceCreationMenu.test.page";
import CreateResource from "./CreateResource";
import ResourceTypesCollection from "../../../../shared/models/entity/resourceType/resourceTypesCollection";
import { ResourceWorkspaceFilterTypes } from "../../../contexts/ResourceWorkspaceContext";
import { waitFor } from "@testing-library/dom";
import {
resourceTypeTotpDto,
resourceTypeV5PasswordStringDto,
} from "../../../../shared/models/entity/resourceType/resourceTypeEntity.test.data";
import {
RESOURCE_TYPE_PASSWORD_AND_DESCRIPTION_SLUG,
RESOURCE_TYPE_TOTP_SLUG,
RESOURCE_TYPE_V5_CUSTOM_FIELDS_SLUG,
RESOURCE_TYPE_V5_DEFAULT_SLUG,
RESOURCE_TYPE_V5_STANDALONE_NOTE_SLUG,
RESOURCE_TYPE_V5_TOTP_SLUG,
} from "../../../../shared/models/entity/resourceType/resourceTypeSchemasDefinition";
import {
defaultProps,
fullV5AndPartialV4ContentTypes,
onlyPasswordV5ContentTypes,
onlyTotpV5ContentTypes,
onlyV4ContentTypesProps,
onlyV5ContentTypesProps,
} from "./DisplayResourceCreationMenu.test.data";
import { defaultFolderDto } from "../../../../shared/models/entity/folder/folderEntity.test.data";
import { defaultUserAppContext } from "../../../contexts/ExtAppContext.test.data";
import { defaultUserDto } from "../../../../shared/models/entity/user/userEntity.test.data";
import { v4 as uuidv4 } from "uuid";
import { defaultMetadataKeysSettingsDto } from "../../../../shared/models/entity/metadata/metadataKeysSettingsEntity.test.data";
import ActionAbortedMissingMetadataKeys from "../../Metadata/ActionAbortedMissingMetadataKeys/ActionAbortedMissingMetadataKeys";
import { resourceWorkspaceContextWithSelectedFolderIOwn } from "../../../contexts/ResourceWorkspaceContext.test.data";
/**
* Unit tests on Display Resource Creation Menu in regard of specifications
*/
describe("See the Display Resource Creation Menu", () => {
describe("Styleguide specifications", () => {
it("should display the component matches the styleguide", async () => {
expect.assertions(12);
const props = defaultProps(); // The props to pass
const page = new DisplayResourceCreationMenuPage(props);
// Dialog title exists and correct
expect(page.exists()).toBeTruthy();
expect(page.title.textContent).toBe("Create a resource");
// Close button exists
expect(page.dialogClose).not.toBeNull();
// tabs should be displayed
expect(page.tabs).not.toBeNull();
expect(page.encryptedMetadataTab).not.toBeNull();
expect(page.legacyCleartextMetadataTab).not.toBeNull();
expect(page.encryptedMetadataTab.textContent).toBe("Resources with encrypted metadata");
expect(page.legacyCleartextMetadataTab.textContent).toBe("Legacy resources");
// first content type available
expect(page.getContentTypeName(1).textContent).toStrictEqual("Password");
// second content type available
expect(page.getContentTypeName(2).textContent).toStrictEqual("TOTP");
// third content type available
expect(page.getContentTypeName(3).textContent).toStrictEqual("Note");
// fourth content type available
expect(page.getContentTypeName(4).textContent).toStrictEqual("Custom fields");
});
it("should close the dialog when pressing escape", async () => {
expect.assertions(2);
const props = defaultProps(); // The props to pass
const page = new DisplayResourceCreationMenuPage(props);
expect(page.exists()).toBeTruthy();
page.pressEscapeKey();
expect(props.onClose).toHaveBeenCalledTimes(1);
});
it("should display only encrypted metadata content types without tabs", () => {
expect.assertions(5);
const props = onlyV5ContentTypesProps(); // The props to pass
const page = new DisplayResourceCreationMenuPage(props);
// Dialog title exists and correct
expect(page.exists()).toBeTruthy();
expect(page.title.textContent).toBe("Create a resource");
// tabs should not be displayed
expect(page.tabs).toBeNull();
// first content type available
expect(page.getContentTypeName(1).textContent).toStrictEqual("Password");
// second content type available
expect(page.getContentTypeName(2).textContent).toStrictEqual("TOTP");
});
it("should display only legacy cleartext metadata content types without tabs", () => {
expect.assertions(7);
const props = onlyV4ContentTypesProps(); // The props to pass
const page = new DisplayResourceCreationMenuPage(props);
// is dialog ready
expect(page.exists()).toBeTruthy();
expect(page.title.textContent).toBe("Create a resource");
// tabs should not be displayed
expect(page.tabs).toBeNull();
// first content type available
expect(page.getContentTypeName(1).textContent).toStrictEqual("Password (legacy)");
expect(page.getContentTypeDescription(1).textContent).toStrictEqual("with cleartext metadata");
// second content type available
expect(page.getContentTypeName(2).textContent).toStrictEqual("TOTP (legacy)");
expect(page.getContentTypeDescription(2).textContent).toStrictEqual("with cleartext metadata");
});
it("should switch tab when clicking on legacy cleartext metadata tab", async () => {
expect.assertions(8);
const props = defaultProps(); // The props to pass
const page = new DisplayResourceCreationMenuPage(props);
// is dialog ready
expect(page.exists()).toBeTruthy();
// tabs should not be displayed
expect(page.tabs).not.toBeNull();
expect(page.activeTab.textContent).toStrictEqual("Resources with encrypted metadata");
page.clickOn(page.legacyCleartextMetadataTab);
expect(page.activeTab.textContent).toBe("Legacy resources");
// first content type available
expect(page.getContentTypeName(1).textContent).toStrictEqual("Password (legacy)");
expect(page.getContentTypeDescription(1).textContent).toStrictEqual("with cleartext metadata");
// second content type available
expect(page.getContentTypeName(2).textContent).toStrictEqual("TOTP (legacy)");
expect(page.getContentTypeDescription(2).textContent).toStrictEqual("with cleartext metadata");
});
it("should not display Password V5 button if no password content type is available", () => {
expect.assertions(3);
const props = onlyTotpV5ContentTypes(); // The props to pass
const page = new DisplayResourceCreationMenuPage(props);
// Dialog title exists and correct
expect(page.exists()).toBeTruthy();
// first content type available
expect(page.getContentTypeName(1).textContent).toStrictEqual("TOTP");
// second content type availability
expect(page.getContentTypeName(2)).toBeUndefined();
});
it("should not display TOTP V5 button if no totp content type is available", () => {
expect.assertions(3);
const props = onlyPasswordV5ContentTypes(); // The props to pass
const page = new DisplayResourceCreationMenuPage(props);
// Dialog title exists and correct
expect(page.exists()).toBeTruthy();
// first content type available
expect(page.getContentTypeName(1).textContent).toStrictEqual("Password");
// second content type availability
expect(page.getContentTypeName(2)).toBeUndefined();
});
it("should not display Password V4 button if no password content type is available", () => {
expect.assertions(4);
const props = fullV5AndPartialV4ContentTypes(); // The props to pass
const page = new DisplayResourceCreationMenuPage(props);
// Dialog title exists and correct
expect(page.exists()).toBeTruthy();
page.clickOn(page.legacyCleartextMetadataTab);
// first content type available
expect(page.getContentTypeName(1).textContent).toStrictEqual("Password (legacy)");
expect(page.getContentTypeDescription(1).textContent).toStrictEqual("with cleartext metadata");
// second content type availability
expect(page.getContentTypeName(2)).toBeUndefined();
});
it("should not display TOTP V4 button if no totp content type is available", () => {
expect.assertions(4);
const props = onlyPasswordV5ContentTypes({
resourceTypes: new ResourceTypesCollection([resourceTypeV5PasswordStringDto(), resourceTypeTotpDto()]),
});
const page = new DisplayResourceCreationMenuPage(props);
// Dialog title exists and correct
expect(page.exists()).toBeTruthy();
page.clickOn(page.legacyCleartextMetadataTab);
// first content type available
expect(page.getContentTypeName(1).textContent).toStrictEqual("TOTP (legacy)");
expect(page.getContentTypeDescription(1).textContent).toStrictEqual("with cleartext metadata");
// second content type availability
expect(page.getContentTypeName(2)).toBeUndefined();
});
});
describe("should open the resource creation dialog with the right parameters", () => {
it("should open the dialog with the right resource type", async () => {
expect.assertions(8);
const props = defaultProps(); // The props to pass
const page = new DisplayResourceCreationMenuPage(props);
const folderParentId = null;
//click on password v5
page.clickOn(page.displayedContentTypes[0]);
await waitFor(() => {});
let resourceType = props.resourceTypes.getFirstBySlug(RESOURCE_TYPE_V5_DEFAULT_SLUG);
expect(props.dialogContext.open).toHaveBeenCalledWith(CreateResource, { resourceType, folderParentId });
//click on totp v5
page.clickOn(page.displayedContentTypes[1]);
await waitFor(() => {});
resourceType = props.resourceTypes.getFirstBySlug(RESOURCE_TYPE_V5_TOTP_SLUG);
expect(props.dialogContext.open).toHaveBeenCalledWith(CreateResource, { resourceType, folderParentId });
//click on note v5
page.clickOn(page.displayedContentTypes[2]);
await waitFor(() => {});
resourceType = props.resourceTypes.getFirstBySlug(RESOURCE_TYPE_V5_STANDALONE_NOTE_SLUG);
expect(props.dialogContext.open).toHaveBeenCalledWith(CreateResource, { resourceType, folderParentId });
//click on custom fields v5
page.clickOn(page.displayedContentTypes[3]);
await waitFor(() => {});
resourceType = props.resourceTypes.getFirstBySlug(RESOURCE_TYPE_V5_CUSTOM_FIELDS_SLUG);
expect(props.dialogContext.open).toHaveBeenCalledWith(CreateResource, { resourceType, folderParentId });
//switch tab
page.clickOn(page.legacyCleartextMetadataTab);
await waitFor(() => {});
//click on password v4
page.clickOn(page.displayedContentTypes[0]);
await waitFor(() => {});
resourceType = props.resourceTypes.getFirstBySlug(RESOURCE_TYPE_PASSWORD_AND_DESCRIPTION_SLUG);
expect(props.dialogContext.open).toHaveBeenCalledWith(CreateResource, { resourceType, folderParentId });
//click on totp v4
page.clickOn(page.displayedContentTypes[1]);
await waitFor(() => {});
resourceType = props.resourceTypes.getFirstBySlug(RESOURCE_TYPE_TOTP_SLUG);
expect(props.dialogContext.open).toHaveBeenCalledWith(CreateResource, { resourceType, folderParentId });
expect(props.dialogContext.open).toHaveBeenCalledTimes(6);
expect(props.onClose).toHaveBeenCalledTimes(6);
});
it("should open the action aborted dialog if shared metadata key is enforced and missing", async () => {
expect.assertions(5);
const props = defaultProps({
context: defaultUserAppContext({
loggedInUser: defaultUserDto({ missing_metadata_key_ids: [uuidv4()] }, { withRole: true }),
}),
metadataKeysSettings: defaultMetadataKeysSettingsDto({ allow_usage_of_personal_keys: false }),
}); // The props to pass
const page = new DisplayResourceCreationMenuPage(props);
//click on password v5
page.clickOn(page.displayedContentTypes[0]);
await waitFor(() => {});
expect(props.dialogContext.open).toHaveBeenNthCalledWith(1, ActionAbortedMissingMetadataKeys);
//click on totp v5
page.clickOn(page.displayedContentTypes[1]);
await waitFor(() => {});
expect(props.dialogContext.open).toHaveBeenNthCalledWith(2, ActionAbortedMissingMetadataKeys);
//click on note v5
page.clickOn(page.displayedContentTypes[2]);
await waitFor(() => {});
expect(props.dialogContext.open).toHaveBeenNthCalledWith(3, ActionAbortedMissingMetadataKeys);
//click on custom fields v5
page.clickOn(page.displayedContentTypes[3]);
await waitFor(() => {});
expect(props.dialogContext.open).toHaveBeenNthCalledWith(4, ActionAbortedMissingMetadataKeys);
expect(props.dialogContext.open).toHaveBeenCalledTimes(4);
});
it("should open the action aborted dialog if shared metadata key is missing to create a shared resource", async () => {
expect.assertions(5);
const props = defaultProps({
context: defaultUserAppContext({
loggedInUser: defaultUserDto({ missing_metadata_key_ids: [uuidv4()] }, { withRole: true }),
}),
resourceWorkspaceContext: resourceWorkspaceContextWithSelectedFolderIOwn(),
}); // The props to pass
const page = new DisplayResourceCreationMenuPage(props);
//click on password v5
page.clickOn(page.displayedContentTypes[0]);
await waitFor(() => {});
expect(props.dialogContext.open).toHaveBeenNthCalledWith(1, ActionAbortedMissingMetadataKeys);
//click on totp v5
page.clickOn(page.displayedContentTypes[1]);
await waitFor(() => {});
expect(props.dialogContext.open).toHaveBeenNthCalledWith(2, ActionAbortedMissingMetadataKeys);
//click on note v5
page.clickOn(page.displayedContentTypes[2]);
await waitFor(() => {});
expect(props.dialogContext.open).toHaveBeenNthCalledWith(3, ActionAbortedMissingMetadataKeys);
//click on custom fields v5
page.clickOn(page.displayedContentTypes[3]);
await waitFor(() => {});
expect(props.dialogContext.open).toHaveBeenNthCalledWith(4, ActionAbortedMissingMetadataKeys);
expect(props.dialogContext.open).toHaveBeenCalledTimes(4);
});
it("should open the dialog with the right folder parent id set", async () => {
expect.assertions(3);
const folder = defaultFolderDto();
const props = defaultProps(); // The props to pass
props.resourceWorkspaceContext.filter = {
type: ResourceWorkspaceFilterTypes.FOLDER,
payload: {
folder: folder,
},
};
const page = new DisplayResourceCreationMenuPage(props);
//click on password v5
page.clickOn(page.displayedContentTypes[0]);
await waitFor(() => {});
const resourceType = props.resourceTypes.getFirstBySlug(RESOURCE_TYPE_V5_DEFAULT_SLUG);
expect(props.dialogContext.open).toHaveBeenCalledWith(CreateResource, {
resourceType: resourceType,
folderParentId: folder.id,
});
expect(props.dialogContext.open).toHaveBeenCalledTimes(1);
expect(props.onClose).toHaveBeenCalledTimes(1);
});
});
});