diff --git a/packages/editor-ui/src/components/ExecutionsList.vue b/packages/editor-ui/src/components/ExecutionsList.vue
index e9c8e99292..3045185a4c 100644
--- a/packages/editor-ui/src/components/ExecutionsList.vue
+++ b/packages/editor-ui/src/components/ExecutionsList.vue
@@ -126,13 +126,13 @@
#{{ execution.id }}
-
+
({{ $locale.baseText('executionsList.retryOf') }} #{{ execution.retryOf }})
-
+
({{ $locale.baseText('executionsList.successRetry') }} #{{
diff --git a/packages/editor-ui/src/components/__tests__/ExecutionsList.test.ts b/packages/editor-ui/src/components/__tests__/ExecutionsList.test.ts
index dd238c617f..acafa33217 100644
--- a/packages/editor-ui/src/components/__tests__/ExecutionsList.test.ts
+++ b/packages/editor-ui/src/components/__tests__/ExecutionsList.test.ts
@@ -1,5 +1,5 @@
import { vi, describe, it, expect } from 'vitest';
-import Vue from 'vue';
+import { merge } from 'lodash-es';
import { PiniaVuePlugin } from 'pinia';
import { createTestingPinia } from '@pinia/testing';
import { render } from '@testing-library/vue';
@@ -7,15 +7,29 @@ import userEvent from '@testing-library/user-event';
import { faker } from '@faker-js/faker';
import { STORES } from '@/constants';
import ExecutionsList from '@/components/ExecutionsList.vue';
-import { externalHooks } from '@/mixins/externalHooks';
-import { genericHelpers } from '@/mixins/genericHelpers';
-import { executionHelpers } from '@/mixins/executionsHelpers';
import { i18nInstance } from '@/plugins/i18n';
import type { IWorkflowDb } from '@/Interface';
import type { IExecutionsSummary } from 'n8n-workflow';
-import { retry, waitAllPromises } from '@/__tests__/utils';
+import { retry, SETTINGS_STORE_DEFAULT_STATE, waitAllPromises } from '@/__tests__/utils';
import { useWorkflowsStore } from '@/stores';
+let pinia: ReturnType;
+
+const generateUndefinedNullOrString = () => {
+ switch (Math.floor(Math.random() * 4)) {
+ case 0:
+ return undefined;
+ case 1:
+ return null;
+ case 2:
+ return faker.datatype.uuid();
+ case 3:
+ return '';
+ default:
+ return undefined;
+ }
+};
+
const workflowDataFactory = (): IWorkflowDb => ({
createdAt: faker.date.past().toDateString(),
updatedAt: faker.date.past().toDateString(),
@@ -38,83 +52,71 @@ const executionDataFactory = (): IExecutionsSummary => ({
workflowName: faker.datatype.string(),
status: faker.helpers.arrayElement(['failed', 'success']),
nodeExecutionStatus: {},
+ retryOf: generateUndefinedNullOrString(),
+ retrySuccessId: generateUndefinedNullOrString(),
});
-const workflowsData = Array.from({ length: 10 }, workflowDataFactory);
+const generateWorkflowsData = () => Array.from({ length: 10 }, workflowDataFactory);
-const executionsData = Array.from({ length: 2 }, () => ({
- count: 20,
- results: Array.from({ length: 10 }, executionDataFactory),
- estimated: false,
-}));
-
-const renderOptions = {
- pinia: createTestingPinia({
- initialState: {
- [STORES.SETTINGS]: {
- settings: {
- templates: {
- enabled: true,
- host: 'https://api.n8n.io/api/',
- },
- license: {
- environment: 'development',
- },
- deployment: {
- type: 'default',
- },
- enterprise: {
- advancedExecutionFilters: true,
- },
- },
- },
- },
- }),
- propsData: {
- autoRefreshEnabled: false,
- },
- i18n: i18nInstance,
- stubs: ['font-awesome-icon'],
- mixins: [externalHooks, genericHelpers, executionHelpers],
-};
-
-function TelemetryPlugin(vue: typeof Vue): void {
- Object.defineProperty(vue, '$telemetry', {
- get() {
- return {
- track: () => {},
- };
- },
- });
- Object.defineProperty(vue.prototype, '$telemetry', {
- get() {
- return {
- track: () => {},
- };
- },
- });
-}
+const generateExecutionsData = () =>
+ Array.from({ length: 2 }, () => ({
+ count: 20,
+ results: Array.from({ length: 10 }, executionDataFactory),
+ estimated: false,
+ }));
const renderComponent = async () => {
- const renderResult = render(ExecutionsList, renderOptions);
+ const renderResult = render(
+ ExecutionsList,
+ {
+ pinia,
+ propsData: {
+ autoRefreshEnabled: false,
+ },
+ i18n: i18nInstance,
+ stubs: ['font-awesome-icon'],
+ },
+ (vue) => {
+ vue.use(PiniaVuePlugin);
+ vue.prototype.$telemetry = {
+ track: () => {},
+ };
+ },
+ );
await waitAllPromises();
return renderResult;
};
-Vue.use(TelemetryPlugin);
-Vue.use(PiniaVuePlugin);
-
describe('ExecutionsList.vue', () => {
- const workflowsStore: ReturnType = useWorkflowsStore();
+ let workflowsStore: ReturnType;
+ let workflowsData: IWorkflowDb[];
+ let executionsData: Array<{
+ count: number;
+ results: IExecutionsSummary[];
+ estimated: boolean;
+ }>;
+
beforeEach(() => {
+ workflowsData = generateWorkflowsData();
+ executionsData = generateExecutionsData();
+
+ pinia = createTestingPinia({
+ initialState: {
+ [STORES.SETTINGS]: {
+ settings: merge(SETTINGS_STORE_DEFAULT_STATE.settings, {
+ enterprise: {
+ advancedExecutionFilters: true,
+ },
+ }),
+ },
+ },
+ });
+ workflowsStore = useWorkflowsStore();
+
vi.spyOn(workflowsStore, 'fetchAllWorkflows').mockResolvedValue(workflowsData);
vi.spyOn(workflowsStore, 'getCurrentExecutions').mockResolvedValue([]);
});
- afterEach(() => {
- vi.clearAllMocks();
- });
-
it('should render empty list', async () => {
vi.spyOn(workflowsStore, 'getPastExecutions').mockResolvedValueOnce({
count: 0,
@@ -182,4 +184,17 @@ describe('ExecutionsList.vue', () => {
expect(getByTestId('select-visible-executions-checkbox')).toBeInTheDocument();
expect(queryByTestId('select-all-executions-checkbox')).not.toBeInTheDocument();
});
+
+ it('should show "retry" data when appropriate', async () => {
+ vi.spyOn(workflowsStore, 'getPastExecutions').mockResolvedValue(executionsData[0]);
+ const retryOf = executionsData[0].results.filter((execution) => execution.retryOf);
+ const retrySuccessId = executionsData[0].results.filter(
+ (execution) => !execution.retryOf && execution.retrySuccessId,
+ );
+
+ const { queryAllByText } = await renderComponent();
+
+ expect(queryAllByText(/Retry of/).length).toBe(retryOf.length);
+ expect(queryAllByText(/Success retry/).length).toBe(retrySuccessId.length);
+ });
});
diff --git a/packages/workflow/src/Interfaces.ts b/packages/workflow/src/Interfaces.ts
index 6e92e9ef7c..0038858844 100644
--- a/packages/workflow/src/Interfaces.ts
+++ b/packages/workflow/src/Interfaces.ts
@@ -1959,8 +1959,8 @@ export interface IExecutionsSummary {
id: string;
finished?: boolean;
mode: WorkflowExecuteMode;
- retryOf?: string;
- retrySuccessId?: string;
+ retryOf?: string | null;
+ retrySuccessId?: string | null;
waitTill?: Date;
startedAt: Date;
stoppedAt?: Date;
|