mirror of
https://github.com/Abdulazizzn/n8n-enterprise-unlocked.git
synced 2025-12-17 18:12:04 +00:00
fix(editor): Fix pagination and sorting issue for insights (#16288)
This commit is contained in:
committed by
GitHub
parent
8d6e796b92
commit
84c51b1bd9
@@ -1,8 +1,22 @@
|
|||||||
import userEvent from '@testing-library/user-event';
|
import userEvent from '@testing-library/user-event';
|
||||||
import { render, within } from '@testing-library/vue';
|
import { render, screen, waitFor, within } from '@testing-library/vue';
|
||||||
|
import { config } from '@vue/test-utils';
|
||||||
|
import ElementPlus from 'element-plus';
|
||||||
|
|
||||||
|
import { createComponentRenderer } from '@n8n/design-system/__tests__/render';
|
||||||
|
|
||||||
import N8nDataTableServer, { type TableHeader } from './N8nDataTableServer.vue';
|
import N8nDataTableServer, { type TableHeader } from './N8nDataTableServer.vue';
|
||||||
|
|
||||||
|
const renderComponent = createComponentRenderer(N8nDataTableServer);
|
||||||
|
|
||||||
|
const getRenderedOptions = async () => {
|
||||||
|
const dropdown = await waitFor(() => screen.getByRole('listbox'));
|
||||||
|
expect(dropdown).toBeInTheDocument();
|
||||||
|
return dropdown.querySelectorAll('.el-select-dropdown__item');
|
||||||
|
};
|
||||||
|
|
||||||
|
config.global.plugins.push(ElementPlus);
|
||||||
|
|
||||||
const itemFactory = () => ({
|
const itemFactory = () => ({
|
||||||
id: crypto.randomUUID() as string,
|
id: crypto.randomUUID() as string,
|
||||||
firstName: crypto.randomUUID() as string,
|
firstName: crypto.randomUUID() as string,
|
||||||
@@ -84,8 +98,7 @@ describe('N8nDataTableServer', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should emit options for sorting / pagination', async () => {
|
it('should emit options for sorting / pagination', async () => {
|
||||||
const { container, emitted, getByTestId } = render(N8nDataTableServer, {
|
const { container, emitted, getByTestId, findAllByRole } = renderComponent({
|
||||||
//@ts-expect-error testing-library errors due to header generics
|
|
||||||
props: { items, headers, itemsLength: 100 },
|
props: { items, headers, itemsLength: 100 },
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -93,7 +106,17 @@ describe('N8nDataTableServer', () => {
|
|||||||
await userEvent.click(container.querySelector('thead tr th')!);
|
await userEvent.click(container.querySelector('thead tr th')!);
|
||||||
await userEvent.click(within(getByTestId('pagination')).getByLabelText('page 2'));
|
await userEvent.click(within(getByTestId('pagination')).getByLabelText('page 2'));
|
||||||
|
|
||||||
expect(emitted('update:options').length).toBe(3);
|
// change the page size select option
|
||||||
|
const selectInput = await findAllByRole('combobox'); // Find the select input
|
||||||
|
await userEvent.click(selectInput[0]);
|
||||||
|
|
||||||
|
const options = await getRenderedOptions();
|
||||||
|
expect(options.length).toBe(4);
|
||||||
|
|
||||||
|
const option50 = Array.from(options).find((option) => option.textContent === '50');
|
||||||
|
await userEvent.click(option50!);
|
||||||
|
|
||||||
|
expect(emitted('update:options').length).toBeGreaterThanOrEqual(4);
|
||||||
expect(emitted('update:options')[0]).toStrictEqual([
|
expect(emitted('update:options')[0]).toStrictEqual([
|
||||||
expect.objectContaining({ sortBy: [{ id: 'id', desc: false }] }),
|
expect.objectContaining({ sortBy: [{ id: 'id', desc: false }] }),
|
||||||
]);
|
]);
|
||||||
@@ -101,6 +124,24 @@ describe('N8nDataTableServer', () => {
|
|||||||
expect.objectContaining({ sortBy: [{ id: 'id', desc: true }] }),
|
expect.objectContaining({ sortBy: [{ id: 'id', desc: true }] }),
|
||||||
]);
|
]);
|
||||||
expect(emitted('update:options')[2]).toStrictEqual([expect.objectContaining({ page: 1 })]);
|
expect(emitted('update:options')[2]).toStrictEqual([expect.objectContaining({ page: 1 })]);
|
||||||
|
expect(emitted('update:options')[3]).toStrictEqual([
|
||||||
|
expect.objectContaining({ itemsPerPage: 50 }),
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should emit options for sorting with initial sort', async () => {
|
||||||
|
const { container, emitted } = renderComponent({
|
||||||
|
props: { items, headers, itemsLength: 100, sortBy: [{ id: 'id', desc: true }] },
|
||||||
|
});
|
||||||
|
|
||||||
|
await userEvent.click(container.querySelector('thead tr th')!);
|
||||||
|
await userEvent.click(container.querySelector('thead tr th')!);
|
||||||
|
|
||||||
|
expect(emitted('update:options').length).toBe(2);
|
||||||
|
expect(emitted('update:options')[0]).toStrictEqual([expect.objectContaining({ sortBy: [] })]);
|
||||||
|
expect(emitted('update:options')[1]).toStrictEqual([
|
||||||
|
expect.objectContaining({ sortBy: [{ id: 'id', desc: false }] }),
|
||||||
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should not show the pagination if there are no items', async () => {
|
it('should not show the pagination if there are no items', async () => {
|
||||||
|
|||||||
@@ -205,7 +205,10 @@ const page = defineModel<number>('page', { default: 0 });
|
|||||||
watch(page, () => table.setPageIndex(page.value));
|
watch(page, () => table.setPageIndex(page.value));
|
||||||
|
|
||||||
const itemsPerPage = defineModel<number>('items-per-page', { default: 10 });
|
const itemsPerPage = defineModel<number>('items-per-page', { default: 10 });
|
||||||
watch(itemsPerPage, () => (page.value = 0));
|
watch(itemsPerPage, () => {
|
||||||
|
page.value = 0;
|
||||||
|
table.setPageSize(itemsPerPage.value);
|
||||||
|
});
|
||||||
|
|
||||||
const pagination = computed<PaginationState>({
|
const pagination = computed<PaginationState>({
|
||||||
get() {
|
get() {
|
||||||
@@ -225,13 +228,16 @@ const showPagination = computed(() => props.itemsLength > Math.min(...props.page
|
|||||||
const sortBy = defineModel<SortingState>('sort-by', { default: [], required: false });
|
const sortBy = defineModel<SortingState>('sort-by', { default: [], required: false });
|
||||||
|
|
||||||
function handleSortingChange(updaterOrValue: Updater<SortingState>) {
|
function handleSortingChange(updaterOrValue: Updater<SortingState>) {
|
||||||
sortBy.value =
|
const newValue =
|
||||||
typeof updaterOrValue === 'function' ? updaterOrValue(sortBy.value) : updaterOrValue;
|
typeof updaterOrValue === 'function' ? updaterOrValue(sortBy.value) : updaterOrValue;
|
||||||
|
sortBy.value = newValue;
|
||||||
|
|
||||||
|
// Use newValue instead of sortBy.value to ensure the latest value is used
|
||||||
|
// This is because of the async nature of the Vue reactivity system
|
||||||
emit('update:options', {
|
emit('update:options', {
|
||||||
page: page.value,
|
page: page.value,
|
||||||
itemsPerPage: itemsPerPage.value,
|
itemsPerPage: itemsPerPage.value,
|
||||||
sortBy: sortBy.value,
|
sortBy: newValue,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ const transformFilter = ({ id, desc }: { id: string; desc: boolean }) => {
|
|||||||
|
|
||||||
const fetchPaginatedTableData = ({
|
const fetchPaginatedTableData = ({
|
||||||
page = 0,
|
page = 0,
|
||||||
itemsPerPage = 20,
|
itemsPerPage = 25,
|
||||||
sortBy,
|
sortBy,
|
||||||
dateRange = selectedDateRange.value,
|
dateRange = selectedDateRange.value,
|
||||||
}: {
|
}: {
|
||||||
|
|||||||
Reference in New Issue
Block a user