fix(editor): Remove "move" action from workflow and credential on community plan (#10057)

This commit is contained in:
Csaba Tuncsik 2024-07-18 15:34:39 +02:00 committed by GitHub
parent f876f9ec8b
commit 5a9a2713b4
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 79 additions and 15 deletions

View file

@ -114,6 +114,8 @@ export class E2EController {
// eslint-disable-next-line @typescript-eslint/unbound-method
license.getFeatureValue<NumericLicenseFeature> = (feature: NumericLicenseFeature) =>
this.numericFeatures[feature] ?? UNLIMITED_LICENSE_QUOTA;
license.getPlanName = () => 'Enterprise';
}
@Post('/reset', { skipAuth: true })

View file

@ -1,9 +1,12 @@
import { setActivePinia } from 'pinia';
import { 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<typeof useSettingsStore>;
beforeEach(() => {
const pinia = createTestingPinia();
setActivePinia(pinia);
settingsStore = useSettingsStore();
});
it('should render name and home project name', () => {
@ -55,4 +61,28 @@ 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, 'isCommunityPlan', 'get').mockReturnValue(false);
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');
}
expect(actions).toHaveTextContent('Move');
});
});

View file

@ -14,6 +14,7 @@ import { useProjectsStore } from '@/stores/projects.store';
import ProjectCardBadge from '@/components/Projects/ProjectCardBadge.vue';
import { useI18n } from '@/composables/useI18n';
import { ResourceType } from '@/utils/projects.utils';
import { useSettingsStore } from '@/stores/settings.store';
const CREDENTIAL_LIST_ITEM_ACTIONS = {
OPEN: 'open',
@ -45,6 +46,7 @@ const message = useMessage();
const uiStore = useUIStore();
const credentialsStore = useCredentialsStore();
const projectsStore = useProjectsStore();
const settingsStore = useSettingsStore();
const resourceTypeLabel = computed(() => locale.baseText('generic.credential').toLowerCase());
const credentialType = computed(() => credentialsStore.getCredentialTypeByName(props.data.type));
@ -64,7 +66,7 @@ const actions = computed(() => {
});
}
if (credentialPermissions.value.move) {
if (credentialPermissions.value.move && !settingsStore.isCommunityPlan) {
items.push({
label: locale.baseText('credentials.item.move'),
value: CREDENTIAL_LIST_ITEM_ACTIONS.MOVE,

View file

@ -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<typeof createPinia>;
let windowOpenSpy: MockInstance;
let router: ReturnType<typeof useRouter>;
let settingsStore: ReturnType<typeof useSettingsStore>;
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,11 @@ describe('WorkflowCard', () => {
});
const actions = document.querySelector(`#${controllingId}`);
await waitFor(() => {
expect(actions).toBeInTheDocument();
});
await userEvent.click(actions!.querySelectorAll('li')[0]);
if (!actions) {
throw new Error('Actions menu not found');
}
await userEvent.click(actions.querySelectorAll('li')[0]);
expect(actions).not.toHaveTextContent('Move');
await waitFor(() => {
expect(router.push).toHaveBeenCalledWith({
name: VIEWS.WORKFLOW,
@ -138,4 +142,28 @@ 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, 'isCommunityPlan', 'get').mockReturnValue(false);
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');
}
expect(actions).toHaveTextContent('Move');
});
});

View file

@ -95,7 +95,7 @@ const actions = computed(() => {
});
}
if (workflowPermissions.value.move) {
if (workflowPermissions.value.move && !settingsStore.isCommunityPlan) {
items.push({
label: locale.baseText('workflows.item.move'),
value: WORKFLOW_LIST_ITEM_ACTIONS.MOVE,

View file

@ -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;
};

View file

@ -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;