diff --git a/cypress/e2e/23-variables.cy.ts b/cypress/e2e/23-variables.cy.ts index c481f25128..a0af3c09ac 100644 --- a/cypress/e2e/23-variables.cy.ts +++ b/cypress/e2e/23-variables.cy.ts @@ -65,8 +65,11 @@ describe('Variables', () => { const editingRow = variablesPage.getters.variablesEditableRows().eq(0); variablesPage.actions.setRowValue(editingRow, 'key', key); variablesPage.actions.setRowValue(editingRow, 'value', value); - editingRow.should('contain', 'This field may contain only letters'); - variablesPage.getters.editableRowSaveButton(editingRow).should('be.disabled'); + variablesPage.actions.saveRowEditing(editingRow); + variablesPage.getters + .variablesEditableRows() + .eq(0) + .should('contain', 'This field may contain only letters'); variablesPage.actions.cancelRowEditing(editingRow); variablesPage.getters.variablesRows().should('have.length', 3); diff --git a/cypress/pages/variables.ts b/cypress/pages/variables.ts index 5fb0a64d9a..1bf344cbfc 100644 --- a/cypress/pages/variables.ts +++ b/cypress/pages/variables.ts @@ -68,7 +68,10 @@ export class VariablesPage extends BasePage { }, setRowValue: (row: Chainable>, field: 'key' | 'value', value: string) => { row.within(() => { - cy.getByTestId(`variable-row-${field}-input`).type('{selectAll}{del}').type(value); + cy.getByTestId(`variable-row-${field}-input`) + .find('input, textarea') + .type('{selectAll}{del}') + .type(value); }); }, cancelRowEditing: (row: Chainable>) => { diff --git a/packages/design-system/src/components/N8nActionBox/ActionBox.vue b/packages/design-system/src/components/N8nActionBox/ActionBox.vue index 02de38143c..b04ccb1049 100644 --- a/packages/design-system/src/components/N8nActionBox/ActionBox.vue +++ b/packages/design-system/src/components/N8nActionBox/ActionBox.vue @@ -10,8 +10,8 @@ import N8nText from '../N8nText'; interface ActionBoxProps { emoji: string; heading: string; - buttonText: string; - buttonType: ButtonType; + buttonText?: string; + buttonType?: ButtonType; buttonDisabled?: boolean; buttonIcon?: string; description: string; diff --git a/packages/design-system/src/components/N8nDatatable/Datatable.vue b/packages/design-system/src/components/N8nDatatable/Datatable.vue index 905aef4671..d3447229d1 100644 --- a/packages/design-system/src/components/N8nDatatable/Datatable.vue +++ b/packages/design-system/src/components/N8nDatatable/Datatable.vue @@ -1,5 +1,5 @@ - diff --git a/packages/editor-ui/src/components/VariablesRow.test.ts b/packages/editor-ui/src/components/VariablesRow.test.ts deleted file mode 100644 index 7d7013054f..0000000000 --- a/packages/editor-ui/src/components/VariablesRow.test.ts +++ /dev/null @@ -1,106 +0,0 @@ -import VariablesRow from './VariablesRow.vue'; -import { fireEvent } from '@testing-library/vue'; -import { setupServer } from '@/__tests__/server'; -import { afterAll, beforeAll } from 'vitest'; -import { useSettingsStore } from '@/stores/settings.store'; -import { useUsersStore } from '@/stores/users.store'; -import { createComponentRenderer } from '@/__tests__/render'; -import { createTestingPinia } from '@pinia/testing'; -import { STORES } from '@/constants'; - -const renderComponent = createComponentRenderer(VariablesRow, { - pinia: createTestingPinia({ - initialState: { - [STORES.SETTINGS]: { - settings: { - enterprise: { - variables: true, - }, - }, - }, - }, - }), - global: { - stubs: ['n8n-tooltip'], - }, -}); - -describe('VariablesRow', () => { - let server: ReturnType; - - beforeAll(() => { - server = setupServer(); - }); - - beforeEach(async () => { - await useSettingsStore().getSettings(); - await useUsersStore().loginWithCookie(); - }); - - afterAll(() => { - server.shutdown(); - }); - - const environmentVariable = { - id: '1', - name: 'key', - value: 'value', - }; - - it('should render correctly', () => { - const wrapper = renderComponent({ - props: { - data: environmentVariable, - }, - }); - - expect(wrapper.container.querySelectorAll('td')).toHaveLength(4); - }); - - it('should show edit and delete buttons on hover', async () => { - const wrapper = renderComponent({ - props: { - data: environmentVariable, - }, - }); - - await fireEvent.mouseEnter(wrapper.container); - - expect(wrapper.getByTestId('variable-row-edit-button')).toBeVisible(); - expect(wrapper.getByTestId('variable-row-delete-button')).toBeVisible(); - }); - - it('should show key and value inputs in edit mode', async () => { - const wrapper = renderComponent({ - props: { - data: environmentVariable, - editing: true, - }, - }); - - await fireEvent.mouseEnter(wrapper.container); - - expect(wrapper.getByTestId('variable-row-key-input')).toBeVisible(); - expect(wrapper.getByTestId('variable-row-key-input').querySelector('input')).toHaveValue( - environmentVariable.name, - ); - expect(wrapper.getByTestId('variable-row-value-input')).toBeVisible(); - expect(wrapper.getByTestId('variable-row-value-input').querySelector('input')).toHaveValue( - environmentVariable.value, - ); - }); - - it('should show cancel and save buttons in edit mode', async () => { - const wrapper = renderComponent({ - props: { - data: environmentVariable, - editing: true, - }, - }); - - await fireEvent.mouseEnter(wrapper.container); - - expect(wrapper.getByTestId('variable-row-cancel-button')).toBeVisible(); - expect(wrapper.getByTestId('variable-row-save-button')).toBeVisible(); - }); -}); diff --git a/packages/editor-ui/src/components/VariablesRow.vue b/packages/editor-ui/src/components/VariablesRow.vue deleted file mode 100644 index f970bd91ae..0000000000 --- a/packages/editor-ui/src/components/VariablesRow.vue +++ /dev/null @@ -1,278 +0,0 @@ - - - - - diff --git a/packages/editor-ui/src/components/VariablesUsageBadge.test.ts b/packages/editor-ui/src/components/VariablesUsageBadge.test.ts new file mode 100644 index 0000000000..a325ada897 --- /dev/null +++ b/packages/editor-ui/src/components/VariablesUsageBadge.test.ts @@ -0,0 +1,31 @@ +import { createComponentRenderer } from '@/__tests__/render'; +import VariablesUsageBadge from './VariablesUsageBadge.vue'; +import userEvent from '@testing-library/user-event'; + +const renderComponent = createComponentRenderer(VariablesUsageBadge); + +const showMessage = vi.fn(); +vi.mock('@/composables/useToast', () => ({ + useToast: () => ({ showMessage }), +})); + +const copy = vi.fn(); +vi.mock('@/composables/useClipboard', () => ({ + useClipboard: () => ({ copy }), +})); + +describe('VariablesUsageBadge', () => { + afterEach(() => { + vi.clearAllMocks(); + }); + + it('should copy to the clipboard', async () => { + const name = 'myVar'; + const output = `$vars.${name}`; + const { getByText } = renderComponent({ props: { name } }); + await userEvent.click(getByText(output)); + + expect(showMessage).toHaveBeenCalledWith(expect.objectContaining({ type: 'success' })); + expect(copy).toHaveBeenCalledWith(output); + }); +}); diff --git a/packages/editor-ui/src/components/VariablesUsageBadge.vue b/packages/editor-ui/src/components/VariablesUsageBadge.vue new file mode 100644 index 0000000000..043d7e5d17 --- /dev/null +++ b/packages/editor-ui/src/components/VariablesUsageBadge.vue @@ -0,0 +1,44 @@ + + + + + diff --git a/packages/editor-ui/src/components/layouts/PageViewLayoutList.vue b/packages/editor-ui/src/components/layouts/PageViewLayoutList.vue index b46f58d284..963da7842e 100644 --- a/packages/editor-ui/src/components/layouts/PageViewLayoutList.vue +++ b/packages/editor-ui/src/components/layouts/PageViewLayoutList.vue @@ -1,11 +1,9 @@