From 1eeb788d327287d21eab7ad6f2156453ab7642c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ra=C3=BAl=20G=C3=B3mez=20Morales?= Date: Mon, 20 Jan 2025 10:59:15 +0100 Subject: [PATCH] feat(editor): VariablesView Reskin - Add Filters for missing values (#12611) --- cypress/e2e/23-variables.cy.ts | 7 +- cypress/pages/variables.ts | 5 +- .../src/components/N8nActionBox/ActionBox.vue | 4 +- .../src/components/N8nDatatable/Datatable.vue | 95 ++-- .../__snapshots__/Datatable.test.ts.snap | 146 ++--- .../src/components/N8nFormInput/FormInput.vue | 3 + .../src/components/VariablesForm.vue | 132 +++++ .../src/components/VariablesRow.test.ts | 106 ---- .../editor-ui/src/components/VariablesRow.vue | 278 ---------- .../components/VariablesUsageBadge.test.ts | 31 ++ .../src/components/VariablesUsageBadge.vue | 44 ++ .../components/layouts/PageViewLayoutList.vue | 6 +- .../layouts/ResourcesListLayout.vue | 10 +- .../src/plugins/i18n/locales/en.json | 2 + .../editor-ui/src/views/VariablesView.test.ts | 285 ++++++++-- .../editor-ui/src/views/VariablesView.vue | 519 ++++++++---------- 16 files changed, 832 insertions(+), 841 deletions(-) create mode 100644 packages/editor-ui/src/components/VariablesForm.vue delete mode 100644 packages/editor-ui/src/components/VariablesRow.test.ts delete mode 100644 packages/editor-ui/src/components/VariablesRow.vue create mode 100644 packages/editor-ui/src/components/VariablesUsageBadge.test.ts create mode 100644 packages/editor-ui/src/components/VariablesUsageBadge.vue 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 @@