fix: hide Create app from templates in airgapped image (#33581)
## Description On homepage create new application from template should not be available to airgapped image. Includes unit tests for `WorkspaceAction.test.tsx` Fixes #`Issue Number` _or_ Fixes `Issue URL` > [!WARNING] > _If no issue exists, please create an issue first, and check with the maintainers if the issue is valid._ ## Automation /ok-to-test tags="@tag.Templates" ### 🔍 Cypress test results <!-- This is an auto-generated comment: Cypress test results --> > [!TIP] > 🟢 🟢 🟢 All cypress tests have passed! 🎉 🎉 🎉 > Workflow run: <https://github.com/appsmithorg/appsmith/actions/runs/9156749330> > Commit: c7461fd1a6c8dfbfd945ec552125f49e846ebd83 > Cypress dashboard url: <a href="https://internal.appsmith.com/app/cypress-dashboard/rundetails-65890b3c81d7400d08fa9ee5?branch=master&workflowId=9156749330&attempt=1" target="_blank">Click here!</a> <!-- end of auto-generated comment: Cypress test results --> ## Communication Should the DevRel and Marketing teams inform users about this change? - [ ] Yes - [x] No
This commit is contained in:
parent
0f90f75740
commit
49b7d1d77f
|
|
@ -20,6 +20,7 @@ import type { Workspace } from "@appsmith/constants/workspaceConstants";
|
|||
import { getIsCreatingApplicationByWorkspaceId } from "@appsmith/selectors/applicationSelectors";
|
||||
import { getIsFetchingApplications } from "@appsmith/selectors/selectedWorkspaceSelectors";
|
||||
import { hasCreateNewAppPermission } from "@appsmith/utils/permissionHelpers";
|
||||
import { isAirgapped } from "@appsmith/utils/airgapHelpers";
|
||||
|
||||
export interface WorkspaceActionProps {
|
||||
workspace: Workspace;
|
||||
|
|
@ -45,6 +46,7 @@ function WorkspaceAction({
|
|||
const isCreatingApplication = Boolean(
|
||||
useSelector(getIsCreatingApplicationByWorkspaceId(workspace.id)),
|
||||
);
|
||||
const isAirgappedInstance = isAirgapped();
|
||||
|
||||
const openActionMenu = useCallback(() => {
|
||||
setIsActionMenuOpen(true);
|
||||
|
|
@ -93,14 +95,16 @@ function WorkspaceAction({
|
|||
</MenuItem>
|
||||
{<Divider className="!block mb-[2px]" />}
|
||||
|
||||
<MenuItem
|
||||
data-testid="t--workspace-action-create-app-from-template"
|
||||
disabled={!hasCreateNewApplicationPermission}
|
||||
onSelect={() => onStartFromTemplate(workspaceId)}
|
||||
startIcon="layout-2-line"
|
||||
>
|
||||
{createMessage(NEW_APP_FROM_TEMPLATE)}
|
||||
</MenuItem>
|
||||
{!isAirgappedInstance && (
|
||||
<MenuItem
|
||||
data-testid="t--workspace-action-create-app-from-template"
|
||||
disabled={!hasCreateNewApplicationPermission}
|
||||
onSelect={() => onStartFromTemplate(workspaceId)}
|
||||
startIcon="layout-2-line"
|
||||
>
|
||||
{createMessage(NEW_APP_FROM_TEMPLATE)}
|
||||
</MenuItem>
|
||||
)}
|
||||
|
||||
{enableImportExport && hasCreateNewApplicationPermission && (
|
||||
<MenuItem
|
||||
|
|
|
|||
|
|
@ -0,0 +1,265 @@
|
|||
import {
|
||||
WORKSPACE_ACTION_BUTTON,
|
||||
createMessage,
|
||||
} from "@appsmith/constants/messages";
|
||||
import type { Workspace } from "@appsmith/constants/workspaceConstants";
|
||||
import "@testing-library/jest-dom";
|
||||
import { fireEvent, render } from "@testing-library/react";
|
||||
import "jest-styled-components";
|
||||
import { unitTestBaseMockStore } from "layoutSystems/common/dropTarget/unitTestUtils";
|
||||
import React from "react";
|
||||
import { Provider } from "react-redux";
|
||||
import configureStore from "redux-mock-store";
|
||||
import { lightTheme } from "selectors/themeSelectors";
|
||||
import { ThemeProvider } from "styled-components";
|
||||
import WorkspaceAction from "../WorkspaceAction";
|
||||
|
||||
const mockStore = configureStore([]);
|
||||
const locators = {
|
||||
testId: {
|
||||
createNewApp: "t--workspace-action-create-app",
|
||||
createAppFromTemplates: "t--workspace-action-create-app-from-template",
|
||||
importApp: "t--workspace-import-app",
|
||||
},
|
||||
};
|
||||
|
||||
const onCreateNewApplication = jest.fn();
|
||||
const onStartFromTemplate = jest.fn();
|
||||
const setSelectedWorkspaceIdForImportApplication = jest.fn();
|
||||
|
||||
const renderWorkspaceActionComponent = (
|
||||
workspace: Workspace,
|
||||
workspaceId: string,
|
||||
) =>
|
||||
render(
|
||||
<Provider store={mockStore(baseStoreForSpec)}>
|
||||
<ThemeProvider theme={lightTheme}>
|
||||
<WorkspaceAction
|
||||
enableImportExport
|
||||
isMobile={false}
|
||||
onCreateNewApplication={onCreateNewApplication}
|
||||
onStartFromTemplate={onStartFromTemplate}
|
||||
setSelectedWorkspaceIdForImportApplication={
|
||||
setSelectedWorkspaceIdForImportApplication
|
||||
}
|
||||
workspace={workspace}
|
||||
workspaceId={workspaceId}
|
||||
/>
|
||||
</ThemeProvider>
|
||||
</Provider>,
|
||||
);
|
||||
|
||||
describe("WorkspaceAction", () => {
|
||||
const workspace = {
|
||||
id: "663a0815de1fdf7aa1618918",
|
||||
userPermissions: [
|
||||
"publish:workspaceApplications",
|
||||
"delete:workspace",
|
||||
"manage:workspaceApplications",
|
||||
"delete:workspaceDatasources",
|
||||
"export:workspaceApplications",
|
||||
"read:workspaceDatasources",
|
||||
"read:workspaceApplications",
|
||||
"inviteUsers:workspace",
|
||||
"read:workspaces",
|
||||
"manage:workspaceDatasources",
|
||||
"create:datasources",
|
||||
"delete:workspaceApplications",
|
||||
"manage:workspaces",
|
||||
"create:applications",
|
||||
],
|
||||
} as Workspace;
|
||||
|
||||
it("1. should render the WorkspaceAction component", () => {
|
||||
const { getByText } = renderWorkspaceActionComponent(
|
||||
workspace,
|
||||
workspace.id,
|
||||
);
|
||||
|
||||
expect(
|
||||
getByText(createMessage(WORKSPACE_ACTION_BUTTON)),
|
||||
).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("2. should call onCreateNewApplication when 'Create New App' is selected", () => {
|
||||
const { getByTestId, getByText } = renderWorkspaceActionComponent(
|
||||
workspace,
|
||||
workspace.id,
|
||||
);
|
||||
|
||||
fireEvent.click(getByText(createMessage(WORKSPACE_ACTION_BUTTON)));
|
||||
fireEvent.click(getByTestId(locators.testId.createNewApp));
|
||||
|
||||
expect(onCreateNewApplication).toHaveBeenCalledWith(workspace.id);
|
||||
});
|
||||
|
||||
it("3. should call onStartFromTemplate when 'Start from Template' is selected", () => {
|
||||
const { getByTestId, getByText } = renderWorkspaceActionComponent(
|
||||
workspace,
|
||||
workspace.id,
|
||||
);
|
||||
|
||||
fireEvent.click(getByText(createMessage(WORKSPACE_ACTION_BUTTON)));
|
||||
fireEvent.click(getByTestId(locators.testId.createAppFromTemplates));
|
||||
|
||||
expect(onStartFromTemplate).toHaveBeenCalledWith(workspace.id);
|
||||
});
|
||||
|
||||
it("4. should call setSelectedWorkspaceIdForImportApplication when 'Import App' is selected", () => {
|
||||
const { getByTestId, getByText } = renderWorkspaceActionComponent(
|
||||
workspace,
|
||||
workspace.id,
|
||||
);
|
||||
|
||||
fireEvent.click(getByText(createMessage(WORKSPACE_ACTION_BUTTON)));
|
||||
fireEvent.click(getByTestId(locators.testId.importApp));
|
||||
|
||||
expect(setSelectedWorkspaceIdForImportApplication).toHaveBeenCalledWith(
|
||||
workspace.id,
|
||||
);
|
||||
});
|
||||
|
||||
it("5. should not render anything if create app permission is unavailable", () => {
|
||||
//setup
|
||||
const existingPermissions = workspace.userPermissions;
|
||||
|
||||
// execute test
|
||||
workspace.userPermissions = ["manage:workspaces"];
|
||||
const { queryByText } = renderWorkspaceActionComponent(
|
||||
workspace,
|
||||
workspace.id,
|
||||
);
|
||||
|
||||
expect(queryByText(createMessage(WORKSPACE_ACTION_BUTTON))).toBeNull();
|
||||
|
||||
// reset the changes
|
||||
workspace.userPermissions = existingPermissions;
|
||||
});
|
||||
});
|
||||
|
||||
jest.mock("@appsmith/utils/airgapHelpers", () => ({
|
||||
isAirgapped: jest.fn(),
|
||||
}));
|
||||
|
||||
const mockIsAirGapped = (val: boolean) => {
|
||||
/* eslint-disable @typescript-eslint/no-var-requires */
|
||||
const { isAirgapped } = require("@appsmith/utils/airgapHelpers");
|
||||
isAirgapped.mockImplementation(() => val);
|
||||
};
|
||||
|
||||
describe("[Airgap] WorkspaceAction", () => {
|
||||
const workspace = {
|
||||
id: "663a0815de1fdf7aa1618918",
|
||||
userPermissions: [
|
||||
"publish:workspaceApplications",
|
||||
"delete:workspace",
|
||||
"manage:workspaceApplications",
|
||||
"delete:workspaceDatasources",
|
||||
"export:workspaceApplications",
|
||||
"read:workspaceDatasources",
|
||||
"read:workspaceApplications",
|
||||
"inviteUsers:workspace",
|
||||
"read:workspaces",
|
||||
"manage:workspaceDatasources",
|
||||
"create:datasources",
|
||||
"delete:workspaceApplications",
|
||||
"manage:workspaces",
|
||||
"create:applications",
|
||||
],
|
||||
} as Workspace;
|
||||
|
||||
beforeEach(() => mockIsAirGapped(true));
|
||||
|
||||
it("1. [Airgap] should render the WorkspaceAction component", () => {
|
||||
const { getByText } = renderWorkspaceActionComponent(
|
||||
workspace,
|
||||
workspace.id,
|
||||
);
|
||||
|
||||
expect(
|
||||
getByText(createMessage(WORKSPACE_ACTION_BUTTON)),
|
||||
).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("2. [Airgap] should call onCreateNewApplication when 'Create New App' is selected", () => {
|
||||
const { getByTestId, getByText } = renderWorkspaceActionComponent(
|
||||
workspace,
|
||||
workspace.id,
|
||||
);
|
||||
|
||||
fireEvent.click(getByText(createMessage(WORKSPACE_ACTION_BUTTON)));
|
||||
fireEvent.click(getByTestId(locators.testId.createNewApp));
|
||||
|
||||
expect(onCreateNewApplication).toHaveBeenCalledWith(workspace.id);
|
||||
});
|
||||
|
||||
it("3. [Airgap] should not have 'Start from Template'", () => {
|
||||
const { getByText, queryByTestId } = renderWorkspaceActionComponent(
|
||||
workspace,
|
||||
workspace.id,
|
||||
);
|
||||
|
||||
fireEvent.click(getByText(createMessage(WORKSPACE_ACTION_BUTTON)));
|
||||
expect(queryByTestId(locators.testId.createAppFromTemplates)).toBeNull();
|
||||
});
|
||||
|
||||
it("4. [Airgap] should call setSelectedWorkspaceIdForImportApplication when 'Import App' is selected", () => {
|
||||
const { getByTestId, getByText } = renderWorkspaceActionComponent(
|
||||
workspace,
|
||||
workspace.id,
|
||||
);
|
||||
|
||||
fireEvent.click(getByText(createMessage(WORKSPACE_ACTION_BUTTON)));
|
||||
fireEvent.click(getByTestId(locators.testId.importApp));
|
||||
|
||||
expect(setSelectedWorkspaceIdForImportApplication).toHaveBeenCalledWith(
|
||||
workspace.id,
|
||||
);
|
||||
});
|
||||
|
||||
it("5. [Airgap] should not render anything if create app permission is unavailable", () => {
|
||||
//setup
|
||||
const existingPermissions = workspace.userPermissions;
|
||||
|
||||
// execute test
|
||||
workspace.userPermissions = ["manage:workspaces"];
|
||||
const { queryByText } = renderWorkspaceActionComponent(
|
||||
workspace,
|
||||
workspace.id,
|
||||
);
|
||||
|
||||
expect(queryByText(createMessage(WORKSPACE_ACTION_BUTTON))).toBeNull();
|
||||
|
||||
// reset the changes
|
||||
workspace.userPermissions = existingPermissions;
|
||||
});
|
||||
});
|
||||
|
||||
const baseStoreForSpec = {
|
||||
...unitTestBaseMockStore,
|
||||
ui: {
|
||||
...unitTestBaseMockStore.ui,
|
||||
applications: {
|
||||
creatingApplication: {},
|
||||
},
|
||||
workspaces: {
|
||||
loadingStates: {
|
||||
isFetchAllRoles: false,
|
||||
isSavingWorkspaceInfo: false,
|
||||
isFetchingWorkspaces: false,
|
||||
isFetchingEntities: false,
|
||||
isDeletingWorkspace: false,
|
||||
},
|
||||
workspaceRoles: [],
|
||||
searchEntities: {},
|
||||
},
|
||||
selectedWorkspace: {
|
||||
packages: [],
|
||||
loadingStates: {
|
||||
isFetchingApplications: false,
|
||||
isFetchingAllUsers: false,
|
||||
isFetchingCurrentWorkspace: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
Loading…
Reference in New Issue
Block a user