fix(editor): Fix sub-execution links in empty output tables (#12781)
Some checks failed
Test Master / install-and-build (push) Waiting to run
Test Master / Unit tests (18.x) (push) Blocked by required conditions
Test Master / Unit tests (20.x) (push) Blocked by required conditions
Test Master / Unit tests (22.4) (push) Blocked by required conditions
Test Master / Lint (push) Blocked by required conditions
Test Master / Notify Slack on failure (push) Blocked by required conditions
Benchmark Docker Image CI / build (push) Has been cancelled

This commit is contained in:
Milorad FIlipović 2025-01-22 16:31:23 +01:00 committed by GitHub
parent 358d2843e5
commit 114ed88368
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 120 additions and 11 deletions

View file

@ -0,0 +1,110 @@
import { createComponentRenderer } from '@/__tests__/render';
import RunDataTable from '@/components/RunDataTable.vue';
import { createTestingPinia } from '@pinia/testing';
import { cleanup } from '@testing-library/vue';
vi.mock('vue-router', () => {
const push = vi.fn();
const resolve = vi.fn().mockReturnValue({ href: 'https://test.com' });
return {
useRouter: () => ({
push,
resolve,
}),
useRoute: () => ({}),
RouterLink: vi.fn(),
};
});
const { trackOpeningRelatedExecution, resolveRelatedExecutionUrl } = vi.hoisted(() => ({
trackOpeningRelatedExecution: vi.fn(),
resolveRelatedExecutionUrl: vi.fn().mockReturnValue('https://test.com'),
}));
vi.mock('@/composables/useExecutionHelpers', () => ({
useExecutionHelpers: () => ({
trackOpeningRelatedExecution,
resolveRelatedExecutionUrl,
}),
}));
const renderComponent = createComponentRenderer(RunDataTable, {
props: {
node: {
parameters: {
keepOnlySet: false,
values: {},
options: {},
},
id: '820ea733-d8a6-4379-8e73-88a2347ea003',
name: 'Set',
type: 'n8n-nodes-base.set',
typeVersion: 1,
position: [380, 1060],
disabled: false,
},
distanceFromActive: 0,
pageOffset: 0,
runIndex: 0,
totalRuns: 0,
mappingEnabled: false,
hasDefaultHoverState: false,
search: '',
},
global: {
plugins: [createTestingPinia()],
},
});
describe('RunDataTable.vue', () => {
beforeEach(cleanup);
it('renders empty table correctly', () => {
const emptyInputData = [
{
json: {},
index: 0,
pairedItem: { item: 0 },
metadata: { subExecution: { executionId: '123', workflowId: '123abcd' } },
},
,
];
const emptyMessage = "This is an item, but it's empty.";
const { getByTestId, getByText } = renderComponent({
props: {
inputData: emptyInputData,
},
});
expect(getByText(emptyMessage)).toBeInTheDocument();
// Sub-execution button should be link (ADO-3057)
expect(getByTestId('debug-sub-execution')).toBeInTheDocument();
expect(getByTestId('debug-sub-execution').tagName).toBe('A');
expect(getByTestId('debug-sub-execution').getAttribute('href')).toBe('https://test.com');
});
it('renders table with items correctly', () => {
const inputData = {
json: { firstName: 'John', lastName: 'Doe' },
index: 0,
pairedItem: { item: 0 },
metadata: { subExecution: { executionId: '123', workflowId: '123abcd' } },
};
const { getByTestId, getAllByText } = renderComponent({
props: {
inputData: [inputData],
},
});
expect(getByTestId('debug-sub-execution')).toBeInTheDocument();
expect(getByTestId('debug-sub-execution').tagName).toBe('A');
expect(getByTestId('debug-sub-execution').getAttribute('href')).toBe('https://test.com');
// All keys from the input data should be rendered
Object.keys(inputData.json).forEach((key) => {
expect(getAllByText(key)).not.toHaveLength(0);
});
// Also, all values from the input data should be rendered
Object.values(inputData.json).forEach((value) => {
expect(getAllByText(value)).not.toHaveLength(0);
});
});
});

View file

@ -451,12 +451,13 @@ watch(focusedMappableInput, (curr) => {
<N8nIconButton
v-if="tableData.metadata.data[index1]"
v-show="showExecutionLink(index1)"
element="a"
type="secondary"
icon="external-link-alt"
data-test-id="debug-sub-execution"
size="mini"
:href="resolveRelatedExecutionUrl(tableData.metadata.data[index1])"
target="_blank"
:href="resolveRelatedExecutionUrl(tableData.metadata.data[index1])"
@click="trackOpeningRelatedExecution(tableData.metadata.data[index1], 'table')"
/>
</N8nTooltip>
@ -584,20 +585,18 @@ watch(focusedMappableInput, (curr) => {
placement="left"
:hide-after="0"
>
<a
<N8nIconButton
v-if="tableData.metadata.data[index1]"
v-show="showExecutionLink(index1)"
:href="resolveRelatedExecutionUrl(tableData.metadata.data[index1])"
element="a"
type="secondary"
icon="external-link-alt"
data-test-id="debug-sub-execution"
size="mini"
target="_blank"
:href="resolveRelatedExecutionUrl(tableData.metadata.data[index1])"
@click="trackOpeningRelatedExecution(tableData.metadata.data[index1], 'table')"
>
<N8nIconButton
type="secondary"
icon="external-link-alt"
data-test-id="debug-sub-execution"
size="mini"
/>
</a>
/>
</N8nTooltip>
</td>
<td