From 61b588593da882977b8225778ed7b75264d9fe6e Mon Sep 17 00:00:00 2001 From: Csaba Tuncsik Date: Mon, 15 Jul 2024 13:24:39 +0200 Subject: [PATCH 1/8] fix(editor): Remove "move" action from workflow and credential on community plan --- packages/editor-ui/src/components/CredentialCard.vue | 4 +++- packages/editor-ui/src/components/WorkflowCard.vue | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/editor-ui/src/components/CredentialCard.vue b/packages/editor-ui/src/components/CredentialCard.vue index b772c6e5c630e..e0d88f4824672 100644 --- a/packages/editor-ui/src/components/CredentialCard.vue +++ b/packages/editor-ui/src/components/CredentialCard.vue @@ -13,6 +13,7 @@ import type { ProjectSharingData } from '@/types/projects.types'; import { useProjectsStore } from '@/stores/projects.store'; import ProjectCardBadge from '@/components/Projects/ProjectCardBadge.vue'; import { useI18n } from '@/composables/useI18n'; +import { useSettingsStore } from '@/stores/settings.store'; const CREDENTIAL_LIST_ITEM_ACTIONS = { OPEN: 'open', @@ -44,6 +45,7 @@ const message = useMessage(); const uiStore = useUIStore(); const credentialsStore = useCredentialsStore(); const projectsStore = useProjectsStore(); +const settingsStore = useSettingsStore(); const credentialType = computed(() => credentialsStore.getCredentialTypeByName(props.data.type)); const credentialPermissions = computed(() => getCredentialPermissions(props.data)); @@ -62,7 +64,7 @@ const actions = computed(() => { }); } - if (credentialPermissions.value.move) { + if (credentialPermissions.value.move && settingsStore.planName.toLowerCase() !== 'community') { items.push({ label: locale.baseText('credentials.item.move'), value: CREDENTIAL_LIST_ITEM_ACTIONS.MOVE, diff --git a/packages/editor-ui/src/components/WorkflowCard.vue b/packages/editor-ui/src/components/WorkflowCard.vue index fa96404a8a200..3f85a43257574 100644 --- a/packages/editor-ui/src/components/WorkflowCard.vue +++ b/packages/editor-ui/src/components/WorkflowCard.vue @@ -93,7 +93,7 @@ const actions = computed(() => { }); } - if (workflowPermissions.value.move) { + if (workflowPermissions.value.move && settingsStore.planName.toLowerCase() !== 'community') { items.push({ label: locale.baseText('workflows.item.move'), value: WORKFLOW_LIST_ITEM_ACTIONS.MOVE, From 09af37d21cee66fed86f716d446e6eafc389a02e Mon Sep 17 00:00:00 2001 From: Csaba Tuncsik Date: Tue, 16 Jul 2024 11:15:47 +0200 Subject: [PATCH 2/8] test: Test workflow and credential card for Move action visibility --- .../src/components/CredentialCard.test.ts | 33 ++++++++++++++++ .../src/components/WorkflowCard.test.ts | 38 ++++++++++++++++++- 2 files changed, 69 insertions(+), 2 deletions(-) diff --git a/packages/editor-ui/src/components/CredentialCard.test.ts b/packages/editor-ui/src/components/CredentialCard.test.ts index d7309159ac5e0..06f767f6ab5a9 100644 --- a/packages/editor-ui/src/components/CredentialCard.test.ts +++ b/packages/editor-ui/src/components/CredentialCard.test.ts @@ -1,9 +1,12 @@ import { setActivePinia } from 'pinia'; +import { waitFor, within } from '@testing-library/vue'; +import userEvent from '@testing-library/user-event'; import { createTestingPinia } from '@pinia/testing'; import { createComponentRenderer } from '@/__tests__/render'; import CredentialCard from '@/components/CredentialCard.vue'; import type { ICredentialsResponse } from '@/Interface'; import type { ProjectSharingData } from '@/types/projects.types'; +import { useSettingsStore } from '@/stores/settings.store'; const renderComponent = createComponentRenderer(CredentialCard); @@ -19,9 +22,12 @@ const createCredential = (overrides = {}): ICredentialsResponse => ({ }); describe('CredentialCard', () => { + let settingsStore: ReturnType; + beforeEach(() => { const pinia = createTestingPinia(); setActivePinia(pinia); + settingsStore = useSettingsStore(); }); it('should render name and home project name', () => { @@ -55,4 +61,31 @@ describe('CredentialCard', () => { expect(heading).toHaveTextContent(data.name); expect(badge).toHaveTextContent('John Doe'); }); + + it('should show Move action only if there is resource permission and not on community plan', async () => { + vi.spyOn(settingsStore, 'planName', 'get').mockReturnValue('Enterprise'); + + const data = createCredential({ + scopes: ['credential:move'], + }); + const { getByTestId } = renderComponent({ props: { data } }); + const cardActions = getByTestId('credential-card-actions'); + + expect(cardActions).toBeInTheDocument(); + + const cardActionsOpener = within(cardActions).getByRole('button'); + expect(cardActionsOpener).toBeInTheDocument(); + + const controllingId = cardActionsOpener.getAttribute('aria-controls'); + + await userEvent.click(cardActions); + const actions = document.querySelector(`#${controllingId}`); + if (!actions) { + throw new Error('Actions menu not found'); + } + await waitFor(() => { + expect(actions).toBeInTheDocument(); + }); + expect(actions).toHaveTextContent('Move'); + }); }); diff --git a/packages/editor-ui/src/components/WorkflowCard.test.ts b/packages/editor-ui/src/components/WorkflowCard.test.ts index a58167c3b93da..368708395e7dc 100644 --- a/packages/editor-ui/src/components/WorkflowCard.test.ts +++ b/packages/editor-ui/src/components/WorkflowCard.test.ts @@ -7,6 +7,7 @@ import { VIEWS } from '@/constants'; import WorkflowCard from '@/components/WorkflowCard.vue'; import type { IWorkflowDb } from '@/Interface'; import { useRouter } from 'vue-router'; +import { useSettingsStore } from '@/stores/settings.store'; vi.mock('vue-router', () => { const push = vi.fn(); @@ -39,12 +40,14 @@ describe('WorkflowCard', () => { let pinia: ReturnType; let windowOpenSpy: MockInstance; let router: ReturnType; + let settingsStore: ReturnType; beforeEach(async () => { pinia = createPinia(); setActivePinia(pinia); router = useRouter(); - windowOpenSpy = vi.spyOn(window, 'open'); + settingsStore = useSettingsStore(); + windowOpenSpy = vi.spyOn(window, 'open').mockImplementation(() => null); }); afterEach(() => { @@ -95,10 +98,14 @@ describe('WorkflowCard', () => { }); const actions = document.querySelector(`#${controllingId}`); + if (!actions) { + throw new Error('Actions menu not found'); + } await waitFor(() => { expect(actions).toBeInTheDocument(); }); - await userEvent.click(actions!.querySelectorAll('li')[0]); + await userEvent.click(actions.querySelectorAll('li')[0]); + expect(actions).not.toHaveTextContent('Move'); await waitFor(() => { expect(router.push).toHaveBeenCalledWith({ name: VIEWS.WORKFLOW, @@ -138,4 +145,31 @@ describe('WorkflowCard', () => { expect(heading).toHaveTextContent(data.name); expect(badge).toHaveTextContent('John Doe'); }); + + it('should show Move action only if there is resource permission and not on community plan', async () => { + vi.spyOn(settingsStore, 'planName', 'get').mockReturnValue('Enterprise'); + + const data = createWorkflow({ + scopes: ['workflow:move'], + }); + const { getByTestId } = renderComponent({ props: { data } }); + const cardActions = getByTestId('workflow-card-actions'); + + expect(cardActions).toBeInTheDocument(); + + const cardActionsOpener = within(cardActions).getByRole('button'); + expect(cardActionsOpener).toBeInTheDocument(); + + const controllingId = cardActionsOpener.getAttribute('aria-controls'); + + await userEvent.click(cardActions); + const actions = document.querySelector(`#${controllingId}`); + if (!actions) { + throw new Error('Actions menu not found'); + } + await waitFor(() => { + expect(actions).toBeInTheDocument(); + }); + expect(actions).toHaveTextContent('Move'); + }); }); From bb3c0b1be5d5f2a5e962e195e947610203526e8f Mon Sep 17 00:00:00 2001 From: Csaba Tuncsik Date: Tue, 16 Jul 2024 16:23:29 +0200 Subject: [PATCH 3/8] fix(editor): Setting store planName might not always be present --- packages/editor-ui/src/components/CredentialCard.vue | 5 ++++- packages/editor-ui/src/components/WorkflowCard.vue | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/packages/editor-ui/src/components/CredentialCard.vue b/packages/editor-ui/src/components/CredentialCard.vue index e0d88f4824672..18cd8d61d80a1 100644 --- a/packages/editor-ui/src/components/CredentialCard.vue +++ b/packages/editor-ui/src/components/CredentialCard.vue @@ -64,7 +64,10 @@ const actions = computed(() => { }); } - if (credentialPermissions.value.move && settingsStore.planName.toLowerCase() !== 'community') { + if ( + credentialPermissions.value.move && + String(settingsStore.planName).toLowerCase() !== 'community' + ) { items.push({ label: locale.baseText('credentials.item.move'), value: CREDENTIAL_LIST_ITEM_ACTIONS.MOVE, diff --git a/packages/editor-ui/src/components/WorkflowCard.vue b/packages/editor-ui/src/components/WorkflowCard.vue index 3f85a43257574..78924f7e9824d 100644 --- a/packages/editor-ui/src/components/WorkflowCard.vue +++ b/packages/editor-ui/src/components/WorkflowCard.vue @@ -93,7 +93,10 @@ const actions = computed(() => { }); } - if (workflowPermissions.value.move && settingsStore.planName.toLowerCase() !== 'community') { + if ( + workflowPermissions.value.move && + String(settingsStore.planName).toLowerCase() !== 'community' + ) { items.push({ label: locale.baseText('workflows.item.move'), value: WORKFLOW_LIST_ITEM_ACTIONS.MOVE, From 5574f43f78638982baba3974a8f970c120912af0 Mon Sep 17 00:00:00 2001 From: Csaba Tuncsik Date: Wed, 17 Jul 2024 11:42:33 +0200 Subject: [PATCH 4/8] test: Remove unnecessary `waitFor` --- packages/editor-ui/src/components/CredentialCard.test.ts | 5 +---- packages/editor-ui/src/components/WorkflowCard.test.ts | 6 ------ 2 files changed, 1 insertion(+), 10 deletions(-) diff --git a/packages/editor-ui/src/components/CredentialCard.test.ts b/packages/editor-ui/src/components/CredentialCard.test.ts index 06f767f6ab5a9..9f9c7f075c03e 100644 --- a/packages/editor-ui/src/components/CredentialCard.test.ts +++ b/packages/editor-ui/src/components/CredentialCard.test.ts @@ -1,5 +1,5 @@ import { setActivePinia } from 'pinia'; -import { waitFor, within } from '@testing-library/vue'; +import { within } from '@testing-library/vue'; import userEvent from '@testing-library/user-event'; import { createTestingPinia } from '@pinia/testing'; import { createComponentRenderer } from '@/__tests__/render'; @@ -83,9 +83,6 @@ describe('CredentialCard', () => { if (!actions) { throw new Error('Actions menu not found'); } - await waitFor(() => { - expect(actions).toBeInTheDocument(); - }); expect(actions).toHaveTextContent('Move'); }); }); diff --git a/packages/editor-ui/src/components/WorkflowCard.test.ts b/packages/editor-ui/src/components/WorkflowCard.test.ts index 368708395e7dc..4088a42c295be 100644 --- a/packages/editor-ui/src/components/WorkflowCard.test.ts +++ b/packages/editor-ui/src/components/WorkflowCard.test.ts @@ -101,9 +101,6 @@ describe('WorkflowCard', () => { if (!actions) { throw new Error('Actions menu not found'); } - await waitFor(() => { - expect(actions).toBeInTheDocument(); - }); await userEvent.click(actions.querySelectorAll('li')[0]); expect(actions).not.toHaveTextContent('Move'); await waitFor(() => { @@ -167,9 +164,6 @@ describe('WorkflowCard', () => { if (!actions) { throw new Error('Actions menu not found'); } - await waitFor(() => { - expect(actions).toBeInTheDocument(); - }); expect(actions).toHaveTextContent('Move'); }); }); From a5bde164cd5af0c2be97ba7f342f756af5b28451 Mon Sep 17 00:00:00 2001 From: Csaba Tuncsik Date: Wed, 17 Jul 2024 15:46:05 +0200 Subject: [PATCH 5/8] fix(editor): Add new `isCommunityPlan` getter to settings store --- .../editor-ui/src/components/CredentialCard.test.ts | 2 +- packages/editor-ui/src/components/CredentialCard.vue | 5 +---- .../editor-ui/src/components/WorkflowCard.test.ts | 2 +- packages/editor-ui/src/components/WorkflowCard.vue | 5 +---- packages/editor-ui/src/composables/useDebugInfo.ts | 11 +++++------ packages/editor-ui/src/stores/settings.store.ts | 7 +++++-- 6 files changed, 14 insertions(+), 18 deletions(-) diff --git a/packages/editor-ui/src/components/CredentialCard.test.ts b/packages/editor-ui/src/components/CredentialCard.test.ts index 9f9c7f075c03e..06760c75da7c5 100644 --- a/packages/editor-ui/src/components/CredentialCard.test.ts +++ b/packages/editor-ui/src/components/CredentialCard.test.ts @@ -63,7 +63,7 @@ describe('CredentialCard', () => { }); it('should show Move action only if there is resource permission and not on community plan', async () => { - vi.spyOn(settingsStore, 'planName', 'get').mockReturnValue('Enterprise'); + vi.spyOn(settingsStore, 'isCommunityPlan', 'get').mockReturnValue(false); const data = createCredential({ scopes: ['credential:move'], diff --git a/packages/editor-ui/src/components/CredentialCard.vue b/packages/editor-ui/src/components/CredentialCard.vue index 18cd8d61d80a1..e86ae19228864 100644 --- a/packages/editor-ui/src/components/CredentialCard.vue +++ b/packages/editor-ui/src/components/CredentialCard.vue @@ -64,10 +64,7 @@ const actions = computed(() => { }); } - if ( - credentialPermissions.value.move && - String(settingsStore.planName).toLowerCase() !== 'community' - ) { + if (credentialPermissions.value.move && !settingsStore.isCommunityPlan) { items.push({ label: locale.baseText('credentials.item.move'), value: CREDENTIAL_LIST_ITEM_ACTIONS.MOVE, diff --git a/packages/editor-ui/src/components/WorkflowCard.test.ts b/packages/editor-ui/src/components/WorkflowCard.test.ts index 4088a42c295be..97be0e7fd4536 100644 --- a/packages/editor-ui/src/components/WorkflowCard.test.ts +++ b/packages/editor-ui/src/components/WorkflowCard.test.ts @@ -144,7 +144,7 @@ describe('WorkflowCard', () => { }); it('should show Move action only if there is resource permission and not on community plan', async () => { - vi.spyOn(settingsStore, 'planName', 'get').mockReturnValue('Enterprise'); + vi.spyOn(settingsStore, 'isCommunityPlan', 'get').mockReturnValue(false); const data = createWorkflow({ scopes: ['workflow:move'], diff --git a/packages/editor-ui/src/components/WorkflowCard.vue b/packages/editor-ui/src/components/WorkflowCard.vue index 78924f7e9824d..a77c092370778 100644 --- a/packages/editor-ui/src/components/WorkflowCard.vue +++ b/packages/editor-ui/src/components/WorkflowCard.vue @@ -93,10 +93,7 @@ const actions = computed(() => { }); } - if ( - workflowPermissions.value.move && - String(settingsStore.planName).toLowerCase() !== 'community' - ) { + if (workflowPermissions.value.move && !settingsStore.isCommunityPlan) { items.push({ label: locale.baseText('workflows.item.move'), value: WORKFLOW_LIST_ITEM_ACTIONS.MOVE, diff --git a/packages/editor-ui/src/composables/useDebugInfo.ts b/packages/editor-ui/src/composables/useDebugInfo.ts index 97ca75b1ee673..89acc06c61bbd 100644 --- a/packages/editor-ui/src/composables/useDebugInfo.ts +++ b/packages/editor-ui/src/composables/useDebugInfo.ts @@ -58,12 +58,11 @@ export function useDebugInfo() { : store.databaseType, executionMode: store.isQueueModeEnabled ? 'scaling' : 'regular', concurrency: store.settings.concurrency, - license: - store.planName === 'Community' - ? (store.planName.toLowerCase() as 'community') - : store.settings.license.environment === 'production' - ? 'enterprise (production)' - : 'enterprise (sandbox)', + license: store.isCommunityPlan + ? 'community' + : store.settings.license.environment === 'production' + ? 'enterprise (production)' + : 'enterprise (sandbox)', consumerId: store.consumerId, } as const; }; diff --git a/packages/editor-ui/src/stores/settings.store.ts b/packages/editor-ui/src/stores/settings.store.ts index c565c696febce..53bbab6a08e96 100644 --- a/packages/editor-ui/src/stores/settings.store.ts +++ b/packages/editor-ui/src/stores/settings.store.ts @@ -77,10 +77,13 @@ export const useSettingsStore = defineStore(STORES.SETTINGS, { return this.settings.databaseType; }, planName(): string { - return this.settings.license.planName ?? 'Community'; + return this.settings.license?.planName ?? 'Community'; + }, + isCommunityPlan(): boolean { + return this.planName.toLowerCase() === 'community'; }, consumerId(): string { - return this.settings.license.consumerId; + return this.settings.license?.consumerId ?? 'unknown'; }, binaryDataMode(): 'default' | 'filesystem' | 's3' { return this.settings.binaryDataMode; From 01a037660254d8d8a3d2e442c085ae885245bfb5 Mon Sep 17 00:00:00 2001 From: Csaba Tuncsik Date: Wed, 17 Jul 2024 17:13:23 +0200 Subject: [PATCH 6/8] fix(editor): Fix store getter --- packages/editor-ui/src/stores/settings.store.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/editor-ui/src/stores/settings.store.ts b/packages/editor-ui/src/stores/settings.store.ts index 53bbab6a08e96..b04a7a9467ca5 100644 --- a/packages/editor-ui/src/stores/settings.store.ts +++ b/packages/editor-ui/src/stores/settings.store.ts @@ -80,7 +80,7 @@ export const useSettingsStore = defineStore(STORES.SETTINGS, { return this.settings.license?.planName ?? 'Community'; }, isCommunityPlan(): boolean { - return this.planName.toLowerCase() === 'community'; + return this.planName.toLowerCase?.() === 'community'; }, consumerId(): string { return this.settings.license?.consumerId ?? 'unknown'; From e2288946eb2b999e391218d4c0a2f3e4029c3ea7 Mon Sep 17 00:00:00 2001 From: Csaba Tuncsik Date: Wed, 17 Jul 2024 20:27:11 +0200 Subject: [PATCH 7/8] Revert "fix(editor): Fix store getter" This reverts commit 01a037660254d8d8a3d2e442c085ae885245bfb5. --- packages/editor-ui/src/stores/settings.store.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/editor-ui/src/stores/settings.store.ts b/packages/editor-ui/src/stores/settings.store.ts index b04a7a9467ca5..53bbab6a08e96 100644 --- a/packages/editor-ui/src/stores/settings.store.ts +++ b/packages/editor-ui/src/stores/settings.store.ts @@ -80,7 +80,7 @@ export const useSettingsStore = defineStore(STORES.SETTINGS, { return this.settings.license?.planName ?? 'Community'; }, isCommunityPlan(): boolean { - return this.planName.toLowerCase?.() === 'community'; + return this.planName.toLowerCase() === 'community'; }, consumerId(): string { return this.settings.license?.consumerId ?? 'unknown'; From d5f01559fcf7a5dbd9248832ee332e5f7a5afb3f Mon Sep 17 00:00:00 2001 From: Csaba Tuncsik Date: Thu, 18 Jul 2024 14:12:06 +0200 Subject: [PATCH 8/8] fix(cli): Fix e2e controller for planName --- packages/cli/src/controllers/e2e.controller.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/cli/src/controllers/e2e.controller.ts b/packages/cli/src/controllers/e2e.controller.ts index ea9364e8548d1..3954bb1caf891 100644 --- a/packages/cli/src/controllers/e2e.controller.ts +++ b/packages/cli/src/controllers/e2e.controller.ts @@ -114,6 +114,8 @@ export class E2EController { // eslint-disable-next-line @typescript-eslint/unbound-method license.getFeatureValue = (feature: NumericLicenseFeature) => this.numericFeatures[feature] ?? UNLIMITED_LICENSE_QUOTA; + + license.getPlanName = () => 'Enterprise'; } @Post('/reset', { skipAuth: true })