diff --git a/app/client/cypress/fixtures/Templates/MockAppViewerUser.json b/app/client/cypress/fixtures/Templates/MockAppViewerUser.json new file mode 100644 index 0000000000..e0145ac9b0 --- /dev/null +++ b/app/client/cypress/fixtures/Templates/MockAppViewerUser.json @@ -0,0 +1,230 @@ +{ + "responseMeta": { + "status": 200, + "success": true + }, + "data": { + "user": { + "id": "63abf1f3cf1ed12127ce3b01", + "userPermissions": [], + "name": "test1@sharklasers.com", + "email": "test1@sharklasers.com", + "source": "FORM", + "isEnabled": true, + "groupIds": [], + "permissions": [], + "isAnonymous": false, + "tenantId": "63abe1a2cf1ed12127ce3ac4", + "enabled": true, + "username": "test1@sharklasers.com", + "accountNonExpired": true, + "accountNonLocked": true, + "credentialsNonExpired": true, + "claims": {}, + "address": {}, + "new": false + }, + "workspaceApplications": [ + { + "workspace": { + "id": "63ad2c156e7a9012ada704c7", + "userPermissions": [ + "inviteUsers:workspace", + "read:workspaces", + "execute:workspaceDatasources", + "read:workspaceApplications" + ], + "name": "Untitled workspace 1", + "email": "test@sharklasers.com", + "plugins": [ + { + "userPermissions": [], + "pluginId": "63abe19ecf1ed12127ce3a5a", + "status": "FREE", + "new": true + }, + { + "userPermissions": [], + "pluginId": "63abe1c5cf1ed12127ce3af5", + "status": "FREE", + "new": true + }, + { + "userPermissions": [], + "pluginId": "63abe19fcf1ed12127ce3a69", + "status": "FREE", + "new": true + }, + { + "userPermissions": [], + "pluginId": "63abe19ecf1ed12127ce3a55", + "status": "FREE", + "new": true + }, + { + "userPermissions": [], + "pluginId": "63abe1c5cf1ed12127ce3af4", + "status": "FREE", + "new": true + }, + { + "userPermissions": [], + "pluginId": "63abe19ccf1ed12127ce3a38", + "status": "FREE", + "new": true + }, + { + "userPermissions": [], + "pluginId": "63abe19fcf1ed12127ce3a64", + "status": "FREE", + "new": true + }, + { + "userPermissions": [], + "pluginId": "63abe1a0cf1ed12127ce3a92", + "status": "FREE", + "new": true + }, + { + "userPermissions": [], + "pluginId": "63abe1c5cf1ed12127ce3af6", + "status": "FREE", + "new": true + }, + { + "userPermissions": [], + "pluginId": "63abe19ecf1ed12127ce3a4c", + "status": "FREE", + "new": true + }, + { + "userPermissions": [], + "pluginId": "63abe1a1cf1ed12127ce3aa3", + "status": "FREE", + "new": true + }, + { + "userPermissions": [], + "pluginId": "63abe1a3cf1ed12127ce3ae9", + "status": "FREE", + "new": true + }, + { + "userPermissions": [], + "pluginId": "63abe19ccf1ed12127ce3a39", + "status": "FREE", + "new": true + }, + { + "userPermissions": [], + "pluginId": "63abe19fcf1ed12127ce3a6d", + "status": "FREE", + "new": true + }, + { + "userPermissions": [], + "pluginId": "63abe19ecf1ed12127ce3a5c", + "status": "FREE", + "new": true + }, + { + "userPermissions": [], + "pluginId": "63abe1a0cf1ed12127ce3a8a", + "status": "FREE", + "new": true + }, + { + "userPermissions": [], + "pluginId": "63abe19fcf1ed12127ce3a84", + "status": "FREE", + "new": true + }, + { + "userPermissions": [], + "pluginId": "63abe19ccf1ed12127ce3a3a", + "status": "FREE", + "new": true + }, + { + "userPermissions": [], + "pluginId": "63abe19fcf1ed12127ce3a79", + "status": "FREE", + "new": true + }, + { + "userPermissions": [], + "pluginId": "63abe19ecf1ed12127ce3a57", + "status": "FREE", + "new": true + } + ], + "slug": "untitled-workspace-1", + "tenantId": "63abe1a2cf1ed12127ce3ac4", + "logoUrl": "/api/v1/assets/null", + "new": false + }, + "applications": [ + { + "id": "63ad2c166e7a9012ada704cb", + "modifiedBy": "test@sharklasers.com", + "userPermissions": [ + "canComment:applications", + "read:applications" + ], + "name": "Untitled application 1", + "workspaceId": "63ad2c156e7a9012ada704c7", + "isPublic": false, + "pages": [ + { + "id": "63ad2c166e7a9012ada704ce", + "isDefault": true, + "slug": "page1", + "defaultPageId": "63ad2c166e7a9012ada704ce", + "default": true + } + ], + "appIsExample": false, + "unreadCommentThreads": 0, + "color": "#FBF4ED", + "icon": "dollar", + "slug": "untitled-application-1", + "unpublishedCustomJSLibs": [], + "publishedCustomJSLibs": [], + "evaluationVersion": 2, + "applicationVersion": 2, + "isManualUpdate": true, + "isAutoUpdate": false, + "new": false, + "modifiedAt": "2022-12-29T05:56:41.772Z" + } + ], + "users": [ + { + "userId": "63abf1edcf1ed12127ce3af7", + "username": "test@sharklasers.com", + "name": "test@sharklasers.com", + "permissionGroupName": "Administrator - Untitled workspace 1", + "permissionGroupId": "63ad2c156e7a9012ada704c8" + }, + { + "userId": "63abf1f3cf1ed12127ce3b01", + "username": "test1@sharklasers.com", + "name": "test1@sharklasers.com", + "permissionGroupName": "App Viewer - Untitled workspace 1", + "permissionGroupId": "63ad2c156e7a9012ada704ca" + } + ] + } + ], + "newReleasesCount": "1", + "releaseItems": [ + { + "tagName": "v1.8.15", + "name": "Release v1.8.15 🌈", + "url": "https://github.com/appsmithorg/appsmith/releases/tag/v1.8.15", + "descriptionHtml": "

💪🏾 Improvements

\n", + "publishedAt": "2022-12-28T12:36:48Z" + } + ] + } +} \ No newline at end of file diff --git a/app/client/cypress/integration/Smoke_TestSuite/ClientSideTests/Templates/Fork_Template_spec.js b/app/client/cypress/integration/Smoke_TestSuite/ClientSideTests/Templates/Fork_Template_spec.js index 94ace8b422..669af44642 100644 --- a/app/client/cypress/integration/Smoke_TestSuite/ClientSideTests/Templates/Fork_Template_spec.js +++ b/app/client/cypress/integration/Smoke_TestSuite/ClientSideTests/Templates/Fork_Template_spec.js @@ -1,5 +1,7 @@ const commonlocators = require("../../../../locators/commonlocators.json"); const templateLocators = require("../../../../locators/TemplatesLocators.json"); +import { ObjectsRegistry } from "../../../../support/Objects/Registry"; +const { AggregateHelper, HomePage } = ObjectsRegistry; describe("Fork a template to an workspace", () => { it("Fork a template to an workspace", () => { @@ -30,4 +32,21 @@ describe("Fork a template to an workspace", () => { expect(location.search).to.eq("?showForkTemplateModal=true"); }); }); + it("Hide template fork button if user does not have a valid workspace to fork", () => { + HomePage.NavigateToHome(); + // Mock user with App Viewer permission + cy.intercept("/api/v1/applications/new", { + fixture: "Templates/MockAppViewerUser.json", + }); + AggregateHelper.RefreshPage(); + HomePage.SwitchToTemplatesTab(); + AggregateHelper.AssertElementExist(templateLocators.templateCard); + AggregateHelper.AssertElementAbsence(templateLocators.templateForkButton); + + AggregateHelper.GetNClick(templateLocators.templateCard); + AggregateHelper.AssertElementExist(templateLocators.templateCard); + AggregateHelper.AssertElementAbsence( + templateLocators.templateViewForkButton, + ); + }); }); diff --git a/app/client/cypress/support/Pages/HomePage.ts b/app/client/cypress/support/Pages/HomePage.ts index 9561c16881..1c7f5ebac5 100644 --- a/app/client/cypress/support/Pages/HomePage.ts +++ b/app/client/cypress/support/Pages/HomePage.ts @@ -80,6 +80,16 @@ export class HomePage { private _deleteAppConfirm = '[data-cy="t--delete"]'; private _wsAction = (action: string) => "//span[text()='" + action + "']/ancestor::a"; + private _homeTab = ".t--apps-tab"; + private _templatesTab = ".t--templates-tab"; + + public SwitchToAppsTab() { + this.agHelper.GetNClick(this._homeTab); + } + + public SwitchToTemplatesTab() { + this.agHelper.GetNClick(this._templatesTab); + } public CreateNewWorkspace(workspaceNewName: string) { let oldName = ""; diff --git a/app/client/src/pages/Templates/Template/TemplateDescription.tsx b/app/client/src/pages/Templates/Template/TemplateDescription.tsx index e9ee451b1d..17d4750747 100644 --- a/app/client/src/pages/Templates/Template/TemplateDescription.tsx +++ b/app/client/src/pages/Templates/Template/TemplateDescription.tsx @@ -28,6 +28,8 @@ import WidgetInfo from "../WidgetInfo"; import ForkTemplate from "../ForkTemplate"; import { templateIdUrl } from "RouteBuilder"; import { useQuery } from "pages/Editor/utils"; +import { useSelector } from "react-redux"; +import { getForkableWorkspaces } from "selectors/templatesSelectors"; export const DescriptionWrapper = styled.div` display: flex; @@ -94,6 +96,7 @@ function TemplateDescription(props: TemplateDescriptionProps) { }>(); const history = useHistory(); const query = useQuery(); + const workspaceList = useSelector(getForkableWorkspaces); const onForkButtonTrigger = () => { history.replace( @@ -114,7 +117,7 @@ function TemplateDescription(props: TemplateDescriptionProps) { {template.description} - {!props.hideForkButton && ( + {!props.hideForkButton && !!workspaceList.length && ( { if (props.onClick) { props.onClick(id); @@ -176,26 +179,29 @@ export function TemplateLayout(props: TemplateLayoutProps) { ); })} -
- - + - - - -
+ + + + + + )}