refactor/add tests

This commit is contained in:
Mutasem Aldmour 2024-11-13 18:49:41 +01:00
parent e661444272
commit 17a14d84ef
No known key found for this signature in database
GPG key ID: 3DFA8122BB7FD6B8
2 changed files with 215 additions and 50 deletions

View file

@ -8,10 +8,14 @@ import { useWorkflowsStore } from '@/stores/workflows.store';
import { createTestingPinia } from '@pinia/testing';
import userEvent from '@testing-library/user-event';
import { waitFor } from '@testing-library/vue';
import type { INodeExecutionData } from 'n8n-workflow';
import type { INodeExecutionData, ITaskData, ITaskMetadata } from 'n8n-workflow';
import { setActivePinia } from 'pinia';
import { useNodeTypesStore } from '../stores/nodeTypes.store';
const { openRelatedExecution } = vi.hoisted(() => ({
openRelatedExecution: vi.fn(),
}));
vi.mock('vue-router', () => {
return {
useRouter: () => ({}),
@ -20,6 +24,12 @@ vi.mock('vue-router', () => {
};
});
vi.mock('@/composables/useExecutionHelpers', () => ({
useExecutionHelpers: () => ({
openRelatedExecution,
}),
}));
const nodes = [
{
id: '1',
@ -33,49 +43,50 @@ const nodes = [
describe('RunData', () => {
it("should render pin button in output panel disabled when there's binary data", () => {
const { getByTestId } = render(
[
const { getByTestId } = render({
defaultRunItems: [
{
json: {},
binary: {
data: {
fileName: 'test.xyz',
mimeType: 'application/octet-stream',
data: '',
},
},
},
],
'binary',
);
displayMode: 'binary',
});
expect(getByTestId('ndv-pin-data')).toBeInTheDocument();
expect(getByTestId('ndv-pin-data')).toHaveAttribute('disabled');
});
it("should not render pin button in input panel when there's binary data", () => {
const { queryByTestId } = render(
[
const { queryByTestId } = render({
defaultRunItems: [
{
json: {},
binary: {
data: {
fileName: 'test.xyz',
mimeType: 'application/octet-stream',
data: '',
},
},
},
],
'binary',
undefined,
'input',
);
displayMode: 'binary',
paneType: 'input',
});
expect(queryByTestId('ndv-pin-data')).not.toBeInTheDocument();
});
it('should render data correctly even when "item.json" has another "json" key', async () => {
const { getByText, getAllByTestId, getByTestId } = render(
[
const { getByText, getAllByTestId, getByTestId } = render({
defaultRunItems: [
{
json: {
id: 1,
@ -95,8 +106,8 @@ describe('RunData', () => {
},
},
],
'schema',
);
displayMode: 'schema',
});
await userEvent.click(getByTestId('ndv-pin-data'));
await waitFor(() => getAllByTestId('run-data-schema-item'), { timeout: 1000 });
@ -105,8 +116,8 @@ describe('RunData', () => {
});
it('should render view and download buttons for PDFs', async () => {
const { getByTestId } = render(
[
const { getByTestId } = render({
defaultRunItems: [
{
json: {},
binary: {
@ -118,8 +129,8 @@ describe('RunData', () => {
},
},
],
'binary',
);
displayMode: 'binary',
});
await waitFor(() => {
expect(getByTestId('ndv-view-binary-data')).toBeInTheDocument();
@ -129,20 +140,21 @@ describe('RunData', () => {
});
it('should not render a view button for unknown content-type', async () => {
const { getByTestId, queryByTestId } = render(
[
const { getByTestId, queryByTestId } = render({
defaultRunItems: [
{
json: {},
binary: {
data: {
fileName: 'test.xyz',
mimeType: 'application/octet-stream',
data: '',
},
},
},
],
'binary',
);
displayMode: 'binary',
});
await waitFor(() => {
expect(queryByTestId('ndv-view-binary-data')).not.toBeInTheDocument();
@ -152,25 +164,32 @@ describe('RunData', () => {
});
it('should not render pin data button when there is no output data', async () => {
const { queryByTestId } = render([], 'table');
const { queryByTestId } = render({ defaultRunItems: [], displayMode: 'table' });
expect(queryByTestId('ndv-pin-data')).not.toBeInTheDocument();
});
it('should disable pin data button when data is pinned', async () => {
const { getByTestId } = render([], 'table', [{ json: { name: 'Test' } }]);
const { getByTestId } = render({
defaultRunItems: [],
displayMode: 'table',
pinnedData: [{ json: { name: 'Test' } }],
});
const pinDataButton = getByTestId('ndv-pin-data');
expect(pinDataButton).toBeDisabled();
});
it('should enable pin data button when data is not pinned', async () => {
const { getByTestId } = render([{ json: { name: 'Test' } }], 'table');
const { getByTestId } = render({
defaultRunItems: [{ json: { name: 'Test' } }],
displayMode: 'table',
});
const pinDataButton = getByTestId('ndv-pin-data');
expect(pinDataButton).toBeEnabled();
});
it('should not render pagination on binary tab', async () => {
const { queryByTestId } = render(
Array.from({ length: 11 }).map((_, i) => ({
const { queryByTestId } = render({
defaultRunItems: Array.from({ length: 11 }).map((_, i) => ({
json: {
data: {
id: i,
@ -180,17 +199,19 @@ describe('RunData', () => {
binary: {
data: {
a: 'b',
data: '',
mimeType: '',
},
},
})),
'binary',
);
displayMode: 'binary',
});
expect(queryByTestId('ndv-data-pagination')).not.toBeInTheDocument();
});
it('should render pagination with binary data on non-binary tab', async () => {
const { getByTestId } = render(
Array.from({ length: 11 }).map((_, i) => ({
const { getByTestId } = render({
defaultRunItems: Array.from({ length: 11 }).map((_, i) => ({
json: {
data: {
id: i,
@ -200,20 +221,171 @@ describe('RunData', () => {
binary: {
data: {
a: 'b',
data: '',
mimeType: '',
},
},
})),
'json',
);
displayMode: 'json',
});
expect(getByTestId('ndv-data-pagination')).toBeInTheDocument();
});
const render = (
outputData: unknown[],
displayMode: IRunDataDisplayMode,
pinnedData?: INodeExecutionData[],
paneType: NodePanelType = 'output',
) => {
it('should render sub-execution link in header', async () => {
const metadata: ITaskMetadata = {
subExecution: {
workflowId: 'xyz',
executionId: '123',
},
subExecutionsCount: 1,
};
const { getByTestId } = render({
defaultRunItems: [
{
json: {},
},
],
displayMode: 'table',
paneType: 'output',
metadata,
});
expect(getByTestId('related-execution-link')).toBeInTheDocument();
expect(getByTestId('related-execution-link')).toHaveTextContent('Inspect Sub-Execution 123');
expect(getByTestId('ndv-items-count')).toHaveTextContent('1 item, 1 sub-execution');
getByTestId('related-execution-link').click();
expect(openRelatedExecution).toHaveBeenCalledWith(metadata, 'table');
});
it('should render parent-execution link in header', async () => {
const metadata: ITaskMetadata = {
parentExecution: {
workflowId: 'xyz',
executionId: '123',
},
};
const { getByTestId } = render({
defaultRunItems: [
{
json: {},
},
],
displayMode: 'table',
paneType: 'output',
metadata,
});
expect(getByTestId('related-execution-link')).toBeInTheDocument();
expect(getByTestId('related-execution-link')).toHaveTextContent('Inspect Parent Execution 123');
expect(getByTestId('ndv-items-count')).toHaveTextContent('1 item');
getByTestId('related-execution-link').click();
expect(openRelatedExecution).toHaveBeenCalledWith(metadata, 'table');
});
it('should render sub-execution link in header with multiple items', async () => {
const metadata: ITaskMetadata = {
subExecution: {
workflowId: 'xyz',
executionId: '123',
},
subExecutionsCount: 3,
};
const { getByTestId } = render({
defaultRunItems: [
{
json: {},
},
{
json: {},
},
],
displayMode: 'json',
paneType: 'output',
metadata,
});
expect(getByTestId('related-execution-link')).toBeInTheDocument();
expect(getByTestId('related-execution-link')).toHaveTextContent('Inspect Sub-Execution 123');
expect(getByTestId('ndv-items-count')).toHaveTextContent('2 items, 3 sub-executions');
getByTestId('related-execution-link').click();
expect(openRelatedExecution).toHaveBeenCalledWith(metadata, 'json');
});
it('should render sub-execution link in header with multiple runs', async () => {
const metadata: ITaskMetadata = {
subExecution: {
workflowId: 'xyz',
executionId: '123',
},
subExecutionsCount: 3,
};
const { getByTestId, queryByTestId } = render({
runs: [
{
startTime: new Date().getTime(),
executionTime: new Date().getTime(),
data: {
main: [[{ json: {} }]],
},
source: [null],
metadata,
},
{
startTime: new Date().getTime(),
executionTime: new Date().getTime(),
data: {
main: [[{ json: {} }]],
},
source: [null],
metadata,
},
],
displayMode: 'json',
paneType: 'output',
metadata,
});
expect(getByTestId('related-execution-link')).toBeInTheDocument();
expect(getByTestId('related-execution-link')).toHaveTextContent('Inspect Sub-Execution 123');
expect(queryByTestId('ndv-items-count')).not.toBeInTheDocument();
expect(getByTestId('run-selector')).toBeInTheDocument();
getByTestId('related-execution-link').click();
expect(openRelatedExecution).toHaveBeenCalledWith(metadata, 'json');
});
const render = ({
defaultRunItems,
displayMode,
pinnedData,
paneType = 'output',
metadata,
runs,
}: {
defaultRunItems?: INodeExecutionData[];
displayMode: IRunDataDisplayMode;
pinnedData?: INodeExecutionData[];
paneType?: NodePanelType;
metadata?: ITaskMetadata;
runs?: ITaskData[];
}) => {
const defaultRun: ITaskData = {
startTime: new Date().getTime(),
executionTime: new Date().getTime(),
data: {
main: [defaultRunItems ?? [{ json: {} }]],
},
source: [null],
metadata,
};
const pinia = createTestingPinia({
stubActions: false,
initialState: {
@ -246,16 +418,7 @@ describe('RunData', () => {
data: {
resultData: {
runData: {
'Test Node': [
{
startTime: new Date().getTime(),
executionTime: new Date().getTime(),
data: {
main: [outputData],
},
source: [null],
},
],
'Test Node': runs ?? [defaultRun],
},
},
},

View file

@ -1413,6 +1413,7 @@ defineExpose({ enterEditMode });
activeTaskMetadata && hasReleatedExectuion && !(paneType === 'input' && hasInputOverwrite)
"
:class="$style.relatedExecutionInfo"
data-test-id="related-execution-link"
@click.stop="openRelatedExecution(activeTaskMetadata, displayMode)"
>
<N8nIcon icon="external-link-alt" size="xsmall" />
@ -1494,6 +1495,7 @@ defineExpose({ enterEditMode });
activeTaskMetadata && hasReleatedExectuion && !(paneType === 'input' && hasInputOverwrite)
"
:class="$style.relatedExecutionInfo"
data-test-id="related-execution-link"
@click.stop="openRelatedExecution(activeTaskMetadata, displayMode)"
>
<N8nIcon icon="external-link-alt" size="xsmall" />