mirror of
https://github.com/n8n-io/n8n.git
synced 2025-03-05 20:50:17 -08:00
refactor: Refactor ParameterInput to composition API + fix all TS errors (no-changelog) (#9006)
This commit is contained in:
parent
0ed46711f4
commit
1c7acbb629
|
@ -26,14 +26,12 @@
|
||||||
import { computed, ref } from 'vue';
|
import { computed, ref } from 'vue';
|
||||||
import { ElInput } from 'element-plus';
|
import { ElInput } from 'element-plus';
|
||||||
import { uid } from '../../utils';
|
import { uid } from '../../utils';
|
||||||
|
import type { InputSize, InputType } from '@/types/input';
|
||||||
const INPUT = ['text', 'textarea', 'number', 'password', 'email'] as const;
|
|
||||||
const SIZE = ['mini', 'small', 'medium', 'large', 'xlarge'] as const;
|
|
||||||
|
|
||||||
interface InputProps {
|
interface InputProps {
|
||||||
modelValue?: string | number;
|
modelValue?: string | number;
|
||||||
type?: (typeof INPUT)[number];
|
type?: InputType;
|
||||||
size?: (typeof SIZE)[number];
|
size?: InputSize;
|
||||||
placeholder?: string;
|
placeholder?: string;
|
||||||
disabled?: boolean;
|
disabled?: boolean;
|
||||||
readonly?: boolean;
|
readonly?: boolean;
|
||||||
|
|
|
@ -2,6 +2,7 @@ export * from './button';
|
||||||
export * from './datatable';
|
export * from './datatable';
|
||||||
export * from './form';
|
export * from './form';
|
||||||
export * from './i18n';
|
export * from './i18n';
|
||||||
|
export * from './input';
|
||||||
export * from './menu';
|
export * from './menu';
|
||||||
export * from './select';
|
export * from './select';
|
||||||
export * from './user';
|
export * from './user';
|
||||||
|
|
5
packages/design-system/src/types/input.ts
Normal file
5
packages/design-system/src/types/input.ts
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
const INPUT_TYPES = ['text', 'textarea', 'number', 'password', 'email'] as const;
|
||||||
|
const INPUT_SIZES = ['mini', 'small', 'medium', 'large', 'xlarge'] as const;
|
||||||
|
|
||||||
|
export type InputType = (typeof INPUT_TYPES)[number];
|
||||||
|
export type InputSize = (typeof INPUT_SIZES)[number];
|
File diff suppressed because it is too large
Load diff
|
@ -0,0 +1,124 @@
|
||||||
|
import { renderComponent } from '@/__tests__/render';
|
||||||
|
import ParameterInput from '@/components/ParameterInput.vue';
|
||||||
|
import type { useNDVStore } from '@/stores/ndv.store';
|
||||||
|
import type { CompletionResult } from '@codemirror/autocomplete';
|
||||||
|
import { createTestingPinia } from '@pinia/testing';
|
||||||
|
import { faker } from '@faker-js/faker';
|
||||||
|
|
||||||
|
let mockNdvState: Partial<ReturnType<typeof useNDVStore>>;
|
||||||
|
let mockCompletionResult: Partial<CompletionResult>;
|
||||||
|
import { waitFor } from '@testing-library/vue';
|
||||||
|
import userEvent from '@testing-library/user-event';
|
||||||
|
|
||||||
|
vi.mock('@/stores/ndv.store', () => {
|
||||||
|
return {
|
||||||
|
useNDVStore: vi.fn(() => mockNdvState),
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
vi.mock('@/plugins/codemirror/completions/datatype.completions', () => {
|
||||||
|
return {
|
||||||
|
datatypeCompletions: vi.fn(() => mockCompletionResult),
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
vi.mock('vue-router', () => {
|
||||||
|
const push = vi.fn();
|
||||||
|
return {
|
||||||
|
useRouter: () => ({
|
||||||
|
push,
|
||||||
|
}),
|
||||||
|
RouterLink: vi.fn(),
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('ParameterInput.vue', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
mockNdvState = {
|
||||||
|
hasInputData: true,
|
||||||
|
activeNode: {
|
||||||
|
id: faker.string.uuid(),
|
||||||
|
name: faker.word.words(3),
|
||||||
|
parameters: {},
|
||||||
|
position: [faker.number.int(), faker.number.int()],
|
||||||
|
type: 'test',
|
||||||
|
typeVersion: 1,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should render an options parameter (select)', async () => {
|
||||||
|
const { container, baseElement, emitted } = renderComponent(ParameterInput, {
|
||||||
|
pinia: createTestingPinia(),
|
||||||
|
props: {
|
||||||
|
path: 'operation',
|
||||||
|
parameter: {
|
||||||
|
displayName: 'Operation',
|
||||||
|
name: 'operation',
|
||||||
|
type: 'options',
|
||||||
|
noDataExpression: true,
|
||||||
|
displayOptions: { show: { resource: ['sheet'] } },
|
||||||
|
options: [
|
||||||
|
{
|
||||||
|
name: 'Append or Update Row',
|
||||||
|
value: 'appendOrUpdate',
|
||||||
|
description: 'Append a new row or update an existing one (upsert)',
|
||||||
|
action: 'Append or update row in sheet',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Append Row',
|
||||||
|
value: 'append',
|
||||||
|
description: 'Create a new row in a sheet',
|
||||||
|
action: 'Append row in sheet',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
default: 'appendOrUpdate',
|
||||||
|
},
|
||||||
|
modelValue: 'appendOrUpdate',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
const select = container.querySelector('input') as HTMLInputElement;
|
||||||
|
const selectTrigger = container.querySelector('.select-trigger') as HTMLElement;
|
||||||
|
expect(select).toBeInTheDocument();
|
||||||
|
expect(selectTrigger).toBeInTheDocument();
|
||||||
|
await waitFor(() => expect(select).toHaveValue('Append or Update Row'));
|
||||||
|
|
||||||
|
await userEvent.click(selectTrigger);
|
||||||
|
|
||||||
|
const options = baseElement.querySelectorAll('.list-option');
|
||||||
|
expect(options.length).toEqual(2);
|
||||||
|
expect(options[0].querySelector('.option-headline')).toHaveTextContent('Append or Update Row');
|
||||||
|
expect(options[0].querySelector('.option-description')).toHaveTextContent(
|
||||||
|
'Append a new row or update an existing one (upsert)',
|
||||||
|
);
|
||||||
|
expect(options[1].querySelector('.option-headline')).toHaveTextContent('Append Row');
|
||||||
|
expect(options[1].querySelector('.option-description')).toHaveTextContent(
|
||||||
|
'Create a new row in a sheet',
|
||||||
|
);
|
||||||
|
|
||||||
|
await userEvent.click(options[1]);
|
||||||
|
|
||||||
|
expect(emitted('update')).toContainEqual([expect.objectContaining({ value: 'append' })]);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should render a string parameter', async () => {
|
||||||
|
const { container, emitted } = renderComponent(ParameterInput, {
|
||||||
|
pinia: createTestingPinia(),
|
||||||
|
props: {
|
||||||
|
path: 'tag',
|
||||||
|
parameter: {
|
||||||
|
displayName: 'Tag',
|
||||||
|
name: 'tag',
|
||||||
|
type: 'string',
|
||||||
|
},
|
||||||
|
modelValue: '',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
const input = container.querySelector('input') as HTMLInputElement;
|
||||||
|
expect(input).toBeInTheDocument();
|
||||||
|
|
||||||
|
await userEvent.type(input, 'foo');
|
||||||
|
|
||||||
|
expect(emitted('update')).toContainEqual([expect.objectContaining({ value: 'foo' })]);
|
||||||
|
});
|
||||||
|
});
|
Loading…
Reference in a new issue