From fa572bbca4397b1cc42668530497444630ed17eb Mon Sep 17 00:00:00 2001 From: Csaba Tuncsik Date: Mon, 9 Dec 2024 15:22:09 +0100 Subject: [PATCH] fix(editor): Update concurrency UI considering different types of instances (#12068) --- .../ConcurrentExecutionsHeader.test.ts | 28 +++++-- .../executions/ConcurrentExecutionsHeader.vue | 34 ++++++--- .../global/GlobalExecutionsList.vue | 10 +++ .../global/GlobalExecutionsListItem.test.ts | 65 +++++++++++++++- .../global/GlobalExecutionsListItem.vue | 29 +++---- ...balExecutionsListItemQueuedTooltip.test.ts | 76 +++++++++++++++++++ .../GlobalExecutionsListItemQueuedTooltip.vue | 67 ++++++++++++++++ .../workflow/WorkflowExecutionsSidebar.vue | 8 ++ .../src/plugins/i18n/locales/en.json | 8 +- 9 files changed, 286 insertions(+), 39 deletions(-) create mode 100644 packages/editor-ui/src/components/executions/global/GlobalExecutionsListItemQueuedTooltip.test.ts create mode 100644 packages/editor-ui/src/components/executions/global/GlobalExecutionsListItemQueuedTooltip.vue diff --git a/packages/editor-ui/src/components/executions/ConcurrentExecutionsHeader.test.ts b/packages/editor-ui/src/components/executions/ConcurrentExecutionsHeader.test.ts index 7e7c45b8d4..9089fa2934 100644 --- a/packages/editor-ui/src/components/executions/ConcurrentExecutionsHeader.test.ts +++ b/packages/editor-ui/src/components/executions/ConcurrentExecutionsHeader.test.ts @@ -46,13 +46,12 @@ describe('ConcurrentExecutionsHeader', () => { }, ); - it('should show tooltip on hover and call "goToUpgrade" on click', async () => { - const windowOpenSpy = vi.spyOn(window, 'open').mockImplementation(() => null); - - const { container, getByText, getByRole, queryByRole } = renderComponent({ + it('should show tooltip on hover with Upgrade link and emit "goToUpgrade" on click when on cloud', async () => { + const { container, getByText, getByRole, queryByRole, emitted } = renderComponent({ props: { runningExecutionsCount: 2, concurrencyCap: 5, + isCloudDeployment: true, }, }); @@ -68,6 +67,25 @@ describe('ConcurrentExecutionsHeader', () => { await userEvent.click(getByText('Upgrade now')); - expect(windowOpenSpy).toHaveBeenCalled(); + expect(emitted().goToUpgrade).toHaveLength(1); + }); + + it('should show tooltip on hover with Viev docs link when self-hosted', async () => { + const { container, getByText, getByRole, queryByRole } = renderComponent({ + props: { + runningExecutionsCount: 2, + concurrencyCap: 5, + }, + }); + + const tooltipTrigger = container.querySelector('svg') as SVGSVGElement; + + expect(tooltipTrigger).toBeVisible(); + expect(queryByRole('tooltip')).not.toBeInTheDocument(); + + await userEvent.hover(tooltipTrigger); + + expect(getByRole('tooltip')).toBeVisible(); + expect(getByText('View docs')).toBeVisible(); }); }); diff --git a/packages/editor-ui/src/components/executions/ConcurrentExecutionsHeader.vue b/packages/editor-ui/src/components/executions/ConcurrentExecutionsHeader.vue index 9ff4600546..0cf3c220ff 100644 --- a/packages/editor-ui/src/components/executions/ConcurrentExecutionsHeader.vue +++ b/packages/editor-ui/src/components/executions/ConcurrentExecutionsHeader.vue @@ -1,15 +1,18 @@ - diff --git a/packages/editor-ui/src/components/executions/global/GlobalExecutionsList.vue b/packages/editor-ui/src/components/executions/global/GlobalExecutionsList.vue index 38aeddda80..01b72dde50 100644 --- a/packages/editor-ui/src/components/executions/global/GlobalExecutionsList.vue +++ b/packages/editor-ui/src/components/executions/global/GlobalExecutionsList.vue @@ -16,6 +16,7 @@ import { getResourcePermissions } from '@/permissions'; import { useSettingsStore } from '@/stores/settings.store'; import ProjectHeader from '@/components/Projects/ProjectHeader.vue'; import ConcurrentExecutionsHeader from '@/components/executions/ConcurrentExecutionsHeader.vue'; +import { usePageRedirectionHelper } from '@/composables/usePageRedirectionHelper'; const props = withDefaults( defineProps<{ @@ -40,6 +41,7 @@ const telemetry = useTelemetry(); const workflowsStore = useWorkflowsStore(); const executionsStore = useExecutionsStore(); const settingsStore = useSettingsStore(); +const pageRedirectionHelper = usePageRedirectionHelper(); const isMounted = ref(false); const allVisibleSelected = ref(false); @@ -317,6 +319,10 @@ async function onAutoRefreshToggle(value: boolean) { executionsStore.stopAutoRefreshInterval(); } } + +const goToUpgrade = () => { + void pageRedirectionHelper.goToUpgrade('concurrency', 'upgrade-concurrency'); +}; - - + {{ statusText }} - + diff --git a/packages/editor-ui/src/components/executions/global/GlobalExecutionsListItemQueuedTooltip.test.ts b/packages/editor-ui/src/components/executions/global/GlobalExecutionsListItemQueuedTooltip.test.ts new file mode 100644 index 0000000000..b200822799 --- /dev/null +++ b/packages/editor-ui/src/components/executions/global/GlobalExecutionsListItemQueuedTooltip.test.ts @@ -0,0 +1,76 @@ +import userEvent from '@testing-library/user-event'; +import { createComponentRenderer } from '@/__tests__/render'; +import GlobalExecutionsListItemQueuedTooltip from '@/components/executions/global/GlobalExecutionsListItemQueuedTooltip.vue'; + +const renderComponent = createComponentRenderer(GlobalExecutionsListItemQueuedTooltip); + +describe('GlobalExecutionsListItemQueuedTooltip', () => { + it('should not throw error when rendered', async () => { + expect(() => + renderComponent({ + props: { + status: 'waiting', + concurrencyCap: 0, + }, + slots: { + default: 'Waiting', + }, + }), + ).not.toThrow(); + }); + + it('should show waiting indefinitely tooltip', async () => { + const { getByText } = renderComponent({ + props: { + status: 'waiting', + concurrencyCap: 0, + }, + slots: { + default: 'Waiting', + }, + }); + + await userEvent.hover(getByText('Waiting')); + + expect(getByText(/waiting indefinitely/)).toBeVisible(); + }); + + it('should show queued tooltip for self-hosted', async () => { + const { getByText } = renderComponent({ + props: { + status: 'new', + concurrencyCap: 0, + }, + slots: { + default: 'Queued', + }, + }); + + await userEvent.hover(getByText('Queued')); + + expect(getByText(/instance is limited/)).toBeVisible(); + expect(getByText('View docs')).toBeVisible(); + }); + + it('should show queued tooltip for cloud', async () => { + const { getByText, emitted } = renderComponent({ + props: { + status: 'new', + concurrencyCap: 0, + isCloudDeployment: true, + }, + slots: { + default: 'Queued', + }, + }); + + await userEvent.hover(getByText('Queued')); + + expect(getByText(/plan is limited/)).toBeVisible(); + expect(getByText('Upgrade now')).toBeVisible(); + + await userEvent.click(getByText('Upgrade now')); + + expect(emitted().goToUpgrade).toHaveLength(1); + }); +}); diff --git a/packages/editor-ui/src/components/executions/global/GlobalExecutionsListItemQueuedTooltip.vue b/packages/editor-ui/src/components/executions/global/GlobalExecutionsListItemQueuedTooltip.vue new file mode 100644 index 0000000000..666f9b7668 --- /dev/null +++ b/packages/editor-ui/src/components/executions/global/GlobalExecutionsListItemQueuedTooltip.vue @@ -0,0 +1,67 @@ + + + + + diff --git a/packages/editor-ui/src/components/executions/workflow/WorkflowExecutionsSidebar.vue b/packages/editor-ui/src/components/executions/workflow/WorkflowExecutionsSidebar.vue index 443a3d0f5d..b43f67708d 100644 --- a/packages/editor-ui/src/components/executions/workflow/WorkflowExecutionsSidebar.vue +++ b/packages/editor-ui/src/components/executions/workflow/WorkflowExecutionsSidebar.vue @@ -15,6 +15,7 @@ import { getResourcePermissions } from '@/permissions'; import { useI18n } from '@/composables/useI18n'; import { useSettingsStore } from '@/stores/settings.store'; import ConcurrentExecutionsHeader from '@/components/executions/ConcurrentExecutionsHeader.vue'; +import { usePageRedirectionHelper } from '@/composables/usePageRedirectionHelper'; type AutoScrollDeps = { activeExecutionSet: boolean; cardsMounted: boolean; scroll: boolean }; @@ -39,6 +40,7 @@ const i18n = useI18n(); const executionsStore = useExecutionsStore(); const settingsStore = useSettingsStore(); +const pageRedirectionHelper = usePageRedirectionHelper(); const mountedItems = ref([]); const autoScrollDeps = ref({ @@ -169,6 +171,10 @@ function scrollToActiveCard(): void { } } } + +const goToUpgrade = () => { + void pageRedirectionHelper.goToUpgrade('concurrency', 'upgrade-concurrency'); +};