Files
n8n-enterprise-unlocked/packages/frontend/editor-ui/src/components/ParameterInputList.test.ts

203 lines
5.6 KiB
TypeScript

import { createComponentRenderer } from '@/__tests__/render';
import ParameterInputList from './ParameterInputList.vue';
import { createTestingPinia } from '@pinia/testing';
import { mockedStore } from '@/__tests__/utils';
import { useNDVStore } from '@/stores/ndv.store';
import * as workflowHelpers from '@/composables/useWorkflowHelpers';
import {
TEST_NODE_NO_ISSUES,
TEST_PARAMETERS,
TEST_NODE_VALUES,
TEST_NODE_WITH_ISSUES,
FIXED_COLLECTION_PARAMETERS,
TEST_ISSUE,
} from './ParameterInputList.test.constants';
import { FORM_NODE_TYPE, FORM_TRIGGER_NODE_TYPE } from 'n8n-workflow';
import type { Workflow } from 'n8n-workflow';
import type { INodeUi } from '../Interface';
import type { MockInstance } from 'vitest';
import { useWorkflowsStore } from '@/stores/workflows.store';
vi.mock('vue-router', async () => {
const actual = await vi.importActual('vue-router');
const params = {};
const location = {};
return {
...actual,
useRouter: () => ({
push: vi.fn(),
}),
useRoute: () => ({
params,
location,
}),
};
});
let ndvStore: ReturnType<typeof mockedStore<typeof useNDVStore>>;
let workflowStore: ReturnType<typeof mockedStore<typeof useWorkflowsStore>>;
const renderComponent = createComponentRenderer(ParameterInputList, {
props: {
hideDelete: true,
indent: true,
isReadOnly: false,
},
global: {
stubs: {
ParameterInputFull: { template: '<div data-test-id="parameter-input"></div>' },
Suspense: { template: '<div data-test-id="suspense-stub"><slot></slot></div>' },
},
},
});
describe('ParameterInputList', () => {
beforeEach(() => {
createTestingPinia();
ndvStore = mockedStore(useNDVStore);
workflowStore = mockedStore(useWorkflowsStore);
});
it('renders', () => {
ndvStore.activeNode = TEST_NODE_NO_ISSUES;
expect(() =>
renderComponent({
props: {
parameters: TEST_PARAMETERS,
nodeValues: TEST_NODE_VALUES,
},
}),
).not.toThrow();
});
it('renders fixed collection inputs correctly', () => {
ndvStore.activeNode = TEST_NODE_NO_ISSUES;
const { getAllByTestId, getByText } = renderComponent({
props: {
parameters: TEST_PARAMETERS,
nodeValues: TEST_NODE_VALUES,
},
});
// Should render labels for all parameters
FIXED_COLLECTION_PARAMETERS.forEach((parameter) => {
expect(getByText(parameter.displayName)).toBeInTheDocument();
});
// Should render input placeholders for all fixed collection parameters
expect(getAllByTestId('suspense-stub')).toHaveLength(FIXED_COLLECTION_PARAMETERS.length);
});
it('renders fixed collection inputs correctly with issues', () => {
ndvStore.activeNode = TEST_NODE_WITH_ISSUES;
const { getByText, getByTestId } = renderComponent({
props: {
parameters: TEST_PARAMETERS,
nodeValues: TEST_NODE_VALUES,
},
});
// Should render labels for all parameters
FIXED_COLLECTION_PARAMETERS.forEach((parameter) => {
expect(getByText(parameter.displayName)).toBeInTheDocument();
});
// Should render error message for fixed collection parameter
expect(
getByTestId(`${FIXED_COLLECTION_PARAMETERS[0].name}-parameter-input-issues-container`),
).toBeInTheDocument();
expect(getByText(TEST_ISSUE)).toBeInTheDocument();
});
it('renders notice correctly', () => {
ndvStore.activeNode = TEST_NODE_NO_ISSUES;
const { getByText } = renderComponent({
props: {
parameters: TEST_PARAMETERS,
nodeValues: TEST_NODE_VALUES,
},
});
expect(getByText('Note: This is a notice with')).toBeInTheDocument();
expect(getByText('notice link')).toBeInTheDocument();
expect(getByText('notice link').getAttribute('href')).toEqual('notice.n8n.io');
});
it('renders callout correctly', () => {
ndvStore.activeNode = TEST_NODE_NO_ISSUES;
const { getByTestId, getByText } = renderComponent({
props: {
parameters: TEST_PARAMETERS,
nodeValues: TEST_NODE_VALUES,
},
});
expect(getByText('Tip: This is a callout with')).toBeInTheDocument();
expect(getByText('callout link')).toBeInTheDocument();
expect(getByText('callout link').getAttribute('href')).toEqual('callout.n8n.io');
expect(getByText('and action!')).toBeInTheDocument();
expect(getByTestId('callout-dismiss-icon')).toBeInTheDocument();
});
describe('updateFormParameters', () => {
const workflowHelpersMock: MockInstance = vi.spyOn(workflowHelpers, 'useWorkflowHelpers');
const formParameters = [
{
displayName: 'TRIGGER NOTICE',
name: 'triggerNotice',
type: 'notice',
default: '',
},
];
afterAll(() => {
workflowHelpersMock.mockRestore();
});
it('should show triggerNotice if Form Trigger not connected', () => {
ndvStore.activeNode = { name: 'From', type: FORM_NODE_TYPE, parameters: {} } as INodeUi;
workflowHelpersMock.mockReturnValue({
getCurrentWorkflow: vi.fn(() => {
return {
getParentNodes: vi.fn(() => []),
nodes: {},
};
}),
});
const { getByText } = renderComponent({
props: {
parameters: formParameters,
nodeValues: {},
},
});
expect(getByText('TRIGGER NOTICE')).toBeInTheDocument();
});
it('should not show triggerNotice if Form Trigger is connected', () => {
ndvStore.activeNode = { name: 'From', type: FORM_NODE_TYPE, parameters: {} } as INodeUi;
workflowStore.workflowObject = {
getParentNodes: vi.fn(() => ['Form Trigger']),
nodes: {
'Form Trigger': {
type: FORM_TRIGGER_NODE_TYPE,
parameters: {},
},
},
} as unknown as Workflow;
const { queryByText } = renderComponent({
props: {
parameters: formParameters,
nodeValues: {},
},
});
const el = queryByText('TRIGGER NOTICE');
expect(el).not.toBeInTheDocument();
});
});
});