Files
alighasami 3d5eaf9445
Security: Sync from Public / sync-from-public (push) Has been cancelled
Test: Benchmark Nightly / build (push) Has been cancelled
Test: Benchmark Nightly / Notify Cats on failure (push) Has been cancelled
CI: Python / Checks (push) Has been cancelled
Test: Evals Python / Workflow Comparison Python (push) Has been cancelled
Util: Check Docs URLs / check-docs-urls (push) Has been cancelled
Test: Visual Storybook / Cloudflare Pages (push) Has been cancelled
Test: E2E Performance / build-and-test-performance (push) Has been cancelled
Test: Workflows Nightly / Run Workflow Tests (push) Has been cancelled
Util: Cleanup CI Docker Images / Delete stale CI images (push) Has been cancelled
Test: Benchmark Destroy Env / build (push) Has been cancelled
Util: Update Node Popularity / update-popularity (push) Has been cancelled
Test: E2E Coverage Weekly / Coverage Tests (push) Has been cancelled
first commit
2026-03-17 16:22:57 +03:30

576 lines
21 KiB
TypeScript

import { nanoid } from 'nanoid';
import { test, expect } from '../../../fixtures/base';
import type { n8nPage } from '../../../pages/n8nPage';
test.describe(
'Data Table details view',
{
annotation: [{ type: 'owner', description: 'Adore' }],
},
() => {
let testDataTableName: string;
const COLUMN_NAMES = {
name: 'name',
age: 'age',
active: 'active',
birthday: 'birthday',
} as const;
const generateTestData = () => [
{
name: `User ${nanoid(8)}`,
age: '30',
active: 'true',
birthday: '2024-01-15',
},
{
name: `User ${nanoid(8)}`,
age: '25',
active: 'false',
birthday: '2024-06-20',
},
{
name: `User ${nanoid(8)}`,
age: '45',
active: 'true',
birthday: '2024-12-10',
},
];
const addColumnsAndGetIds = async (
n8n: n8nPage,
method: 'header' | 'table',
): Promise<{
nameColumn: string;
ageColumn: string;
activeColumn: string;
birthdayColumn: string;
}> => {
const addColumnFn =
method === 'header'
? n8n.dataTableDetails.addColumn.bind(n8n.dataTableDetails)
: n8n.dataTableDetails.addColumn.bind(n8n.dataTableDetails);
await addColumnFn(COLUMN_NAMES.name, 'string', method);
await addColumnFn(COLUMN_NAMES.age, 'number', method);
await addColumnFn(COLUMN_NAMES.active, 'boolean', method);
await addColumnFn(COLUMN_NAMES.birthday, 'date', method);
const visibleColumns = n8n.dataTableDetails.getVisibleColumns();
await expect(visibleColumns).toHaveCount(7);
await expect(n8n.dataTableDetails.getColumnHeaderByName(COLUMN_NAMES.name)).toBeVisible();
await expect(n8n.dataTableDetails.getColumnHeaderByName(COLUMN_NAMES.age)).toBeVisible();
await expect(n8n.dataTableDetails.getColumnHeaderByName(COLUMN_NAMES.active)).toBeVisible();
await expect(n8n.dataTableDetails.getColumnHeaderByName(COLUMN_NAMES.birthday)).toBeVisible();
return {
nameColumn: await n8n.dataTableDetails.getColumnIdByName(COLUMN_NAMES.name),
ageColumn: await n8n.dataTableDetails.getColumnIdByName(COLUMN_NAMES.age),
activeColumn: await n8n.dataTableDetails.getColumnIdByName(COLUMN_NAMES.active),
birthdayColumn: await n8n.dataTableDetails.getColumnIdByName(COLUMN_NAMES.birthday),
};
};
const fillRowData = async (
n8n: n8nPage,
rowIndex: number,
columnIds: {
nameColumn: string;
ageColumn: string;
activeColumn: string;
birthdayColumn: string;
},
data: { name: string; age: string; active: string; birthday: string },
skipFirstDoubleClick: boolean = false,
) => {
await n8n.dataTableDetails.setCellValue(rowIndex, columnIds.nameColumn, data.name, 'string', {
skipDoubleClick: skipFirstDoubleClick,
});
await n8n.dataTableDetails.setCellValue(rowIndex, columnIds.ageColumn, data.age, 'number');
await n8n.dataTableDetails.setCellValue(
rowIndex,
columnIds.activeColumn,
data.active,
'boolean',
);
await n8n.dataTableDetails.setCellValue(
rowIndex,
columnIds.birthdayColumn,
data.birthday,
'date',
);
};
const verifyCellValues = async (
n8n: n8nPage,
columnIds: {
nameColumn: string;
ageColumn: string;
activeColumn: string;
birthdayColumn: string;
},
testData: Array<{ name: string; age: string; active: string; birthday: string }>,
) => {
const firstRowNameValue = await n8n.dataTableDetails.getCellValue(
0,
columnIds.nameColumn,
'string',
);
expect(firstRowNameValue).toContain(testData[0].name);
const secondRowAgeValue = await n8n.dataTableDetails.getCellValue(
1,
columnIds.ageColumn,
'number',
);
expect(secondRowAgeValue).toContain(testData[1].age);
const thirdRowActiveValue = await n8n.dataTableDetails.getCellValue(
2,
columnIds.activeColumn,
'boolean',
);
expect(thirdRowActiveValue).toBe(testData[2].active);
const firstRowBirthdayValue = await n8n.dataTableDetails.getCellValue(
0,
columnIds.birthdayColumn,
'date',
);
expect(firstRowBirthdayValue).toContain(testData[0].birthday);
};
test.beforeEach(async ({ n8n, api }) => {
await api.enableFeature('sharing');
await api.enableFeature('folders');
await api.enableFeature('advancedPermissions');
await api.enableFeature('projectRole:admin');
await api.enableFeature('projectRole:editor');
await api.setMaxTeamProjectsQuota(-1);
await n8n.goHome();
await n8n.sideBar.clickPersonalMenuItem();
testDataTableName = `Data Table ${nanoid(8)}`;
await n8n.projectTabs.clickDataTablesTab();
await n8n.dataTable.clickAddDataTableAction();
await n8n.dataTableComposer.createNewDataTable(testDataTableName);
});
test('Should display empty state with default columns', async ({ n8n }) => {
const dataTableDetailsContainer = n8n.dataTableDetails.getPageWrapper();
await expect(dataTableDetailsContainer).toBeVisible();
const emptyStateMessage = n8n.dataTableDetails.getNoRowsMessage();
await expect(emptyStateMessage).toBeVisible();
const visibleColumns = n8n.dataTableDetails.getVisibleColumns();
await expect(visibleColumns).toHaveCount(3);
await expect(n8n.dataTableDetails.getColumnHeaderByName('id')).toBeVisible();
await expect(n8n.dataTableDetails.getColumnHeaderByName('createdAt')).toBeVisible();
await expect(n8n.dataTableDetails.getColumnHeaderByName('updatedAt')).toBeVisible();
});
test('Should add columns of different types and rows from the header buttons', async ({
n8n,
}) => {
await expect(n8n.dataTableDetails.getPageWrapper()).toBeVisible();
const columnIds = await addColumnsAndGetIds(n8n, 'header');
const testData = generateTestData();
await n8n.dataTableDetails.addRow();
await expect(n8n.dataTableDetails.getNoRowsMessage()).toBeHidden();
await fillRowData(n8n, 0, columnIds, testData[0], true);
await n8n.dataTableDetails.addRow();
await fillRowData(n8n, 1, columnIds, testData[1], true);
await n8n.dataTableDetails.addRow();
await fillRowData(n8n, 2, columnIds, testData[2], true);
await verifyCellValues(n8n, columnIds, testData);
});
test('Should add columns of different types and rows from the table buttons', async ({
n8n,
}) => {
await expect(n8n.dataTableDetails.getPageWrapper()).toBeVisible();
const columnIds = await addColumnsAndGetIds(n8n, 'table');
const testData = generateTestData();
await n8n.dataTableDetails.addRowFromTable();
await expect(n8n.dataTableDetails.getNoRowsMessage()).toBeHidden();
await fillRowData(n8n, 0, columnIds, testData[0], true);
await n8n.dataTableDetails.addRowFromTable();
await fillRowData(n8n, 1, columnIds, testData[1], true);
await n8n.dataTableDetails.addRowFromTable();
await fillRowData(n8n, 2, columnIds, testData[2], true);
await verifyCellValues(n8n, columnIds, testData);
});
test('Should automatically move to second page when adding 21st row', async ({ n8n }) => {
await expect(n8n.dataTableDetails.getPageWrapper()).toBeVisible();
await n8n.dataTableDetails.addColumn(COLUMN_NAMES.name, 'string', 'header');
for (let i = 0; i < 20; i++) {
await n8n.dataTableDetails.addRow();
// This loop was enough to break it, as we'd get transaction lock errors
// eslint-disable-next-line playwright/no-wait-for-timeout
await n8n.page.waitForTimeout(150);
}
const rowsOnPage1 = n8n.dataTableDetails.getDataRows();
await expect(rowsOnPage1).toHaveCount(20);
await n8n.dataTableDetails.addRow();
const rowsOnPage2 = n8n.dataTableDetails.getDataRows();
await expect(rowsOnPage2).toHaveCount(1);
});
test('Should select and delete rows', async ({ n8n }) => {
await expect(n8n.dataTableDetails.getPageWrapper()).toBeVisible();
await n8n.dataTableDetails.addColumn(COLUMN_NAMES.name, 'string', 'header');
const nameColumn = await n8n.dataTableDetails.getColumnIdByName(COLUMN_NAMES.name);
const rowData = ['Row 1', 'Row 2', 'Row 3', 'Row 4', 'Row 5'];
for (let i = 0; i < rowData.length; i++) {
await n8n.dataTableDetails.addRow();
// eslint-disable-next-line playwright/no-wait-for-timeout
await n8n.page.waitForTimeout(150);
await n8n.dataTableDetails.setCellValue(i, nameColumn, rowData[i], 'string', {
skipDoubleClick: true,
});
}
const initialRows = n8n.dataTableDetails.getDataRows();
await expect(initialRows).toHaveCount(5);
await n8n.dataTableDetails.selectRow(1);
await n8n.dataTableDetails.selectRow(3);
const selectedItemsInfo = n8n.dataTableDetails.getSelectedItemsInfo();
await expect(selectedItemsInfo).toBeVisible();
await expect(selectedItemsInfo).toContainText('2');
await n8n.dataTableDetails.deleteSelectedRows();
const remainingRows = n8n.dataTableDetails.getDataRows();
await expect(remainingRows).toHaveCount(3);
await expect(selectedItemsInfo).toBeHidden();
const row0Value = await n8n.dataTableDetails.getCellValue(0, nameColumn, 'string');
expect(row0Value).toContain('Row 1');
const row1Value = await n8n.dataTableDetails.getCellValue(1, nameColumn, 'string');
expect(row1Value).toContain('Row 3');
const row2Value = await n8n.dataTableDetails.getCellValue(2, nameColumn, 'string');
expect(row2Value).toContain('Row 5');
});
test('Should clear selection', async ({ n8n }) => {
await expect(n8n.dataTableDetails.getPageWrapper()).toBeVisible();
await n8n.dataTableDetails.addColumn(COLUMN_NAMES.name, 'string', 'header');
const nameColumn = await n8n.dataTableDetails.getColumnIdByName(COLUMN_NAMES.name);
for (let i = 0; i < 3; i++) {
await n8n.dataTableDetails.addRow();
await n8n.dataTableDetails.setCellValue(i, nameColumn, `Row ${i + 1}`, 'string', {
skipDoubleClick: true,
});
}
await n8n.dataTableDetails.selectRow(0);
await n8n.dataTableDetails.selectRow(1);
await n8n.dataTableDetails.selectRow(2);
const selectedItemsInfo = n8n.dataTableDetails.getSelectedItemsInfo();
await expect(selectedItemsInfo).toBeVisible();
await expect(selectedItemsInfo).toContainText('3');
await n8n.dataTableDetails.clearSelection();
await expect(selectedItemsInfo).toBeHidden();
const rows = n8n.dataTableDetails.getDataRows();
await expect(rows).toHaveCount(3);
});
test('Should add columns of each type with rows and then delete all columns', async ({
n8n,
}) => {
await expect(n8n.dataTableDetails.getPageWrapper()).toBeVisible();
const columnIds = await addColumnsAndGetIds(n8n, 'header');
const testData = generateTestData().slice(0, 2);
await n8n.dataTableDetails.addRow();
await fillRowData(n8n, 0, columnIds, testData[0], true);
await n8n.dataTableDetails.addRow();
await fillRowData(n8n, 1, columnIds, testData[1], true);
const rows = n8n.dataTableDetails.getDataRows();
await expect(rows).toHaveCount(2);
await n8n.dataTableDetails.deleteColumn(COLUMN_NAMES.name);
await expect(n8n.dataTableDetails.getVisibleColumns()).toHaveCount(6);
await n8n.dataTableDetails.deleteColumn(COLUMN_NAMES.age);
await expect(n8n.dataTableDetails.getVisibleColumns()).toHaveCount(5);
await n8n.dataTableDetails.deleteColumn(COLUMN_NAMES.active);
await expect(n8n.dataTableDetails.getVisibleColumns()).toHaveCount(4);
await n8n.dataTableDetails.deleteColumn(COLUMN_NAMES.birthday);
await expect(n8n.dataTableDetails.getVisibleColumns()).toHaveCount(3);
await expect(n8n.dataTableDetails.getColumnHeaderByName('id')).toBeVisible();
await expect(n8n.dataTableDetails.getColumnHeaderByName('createdAt')).toBeVisible();
await expect(n8n.dataTableDetails.getColumnHeaderByName('updatedAt')).toBeVisible();
await expect(rows).toHaveCount(2);
});
test('Should rename data table from breadcrumbs', async ({ n8n }) => {
await expect(n8n.dataTableDetails.getPageWrapper()).toBeVisible();
const nameBreadcrumb = n8n.dataTableDetails.getDataTableBreadcrumb();
const initialName = (await nameBreadcrumb.textContent())?.toString();
const newName = `Renamed Table ${nanoid(8)}`;
await n8n.dataTableDetails.renameDataTable(newName);
await expect(nameBreadcrumb).toContainText(newName);
expect(initialName).not.toEqual(newName);
});
test.fixme('Should filter correctly using column filters', async ({ n8n }) => {
await expect(n8n.dataTableDetails.getPageWrapper()).toBeVisible();
await n8n.dataTableDetails.setPageSize('10');
await n8n.dataTableDetails.addColumn(COLUMN_NAMES.name, 'string', 'header');
await n8n.dataTableDetails.addColumn(COLUMN_NAMES.age, 'number', 'header');
await n8n.dataTableDetails.addColumn(COLUMN_NAMES.active, 'boolean', 'header');
await n8n.dataTableDetails.addColumn(COLUMN_NAMES.birthday, 'date', 'header');
const nameColumn = await n8n.dataTableDetails.getColumnIdByName(COLUMN_NAMES.name);
const ageColumn = await n8n.dataTableDetails.getColumnIdByName(COLUMN_NAMES.age);
const activeColumn = await n8n.dataTableDetails.getColumnIdByName(COLUMN_NAMES.active);
const birthdayColumn = await n8n.dataTableDetails.getColumnIdByName(COLUMN_NAMES.birthday);
const rowsData = [
{ name: 'User 1', age: '20', active: 'true', birthday: '2024-01-01' },
{ name: 'User 2', age: '21', active: 'true', birthday: '2024-01-02' },
{ name: 'User 3', age: '22', active: 'true', birthday: '2024-01-03' },
{ name: 'User 4', age: '23', active: 'true', birthday: '2024-01-04' },
{ name: 'User 5', age: '24', active: 'true', birthday: '2024-01-05' },
{ name: 'User 6', age: '25', active: 'false', birthday: '2024-01-06' },
{ name: 'User 7', age: '20', active: 'false', birthday: '2024-01-07' },
{ name: 'User 8', age: '21', active: 'false', birthday: '2024-01-08' },
{ name: 'User 9', age: '22', active: 'false', birthday: '2024-01-09' },
{ name: 'User 10', age: '23', active: 'false', birthday: '2024-01-10' },
{ name: 'User 11', age: '24', active: 'true', birthday: '2024-01-11' },
{ name: 'User 12', age: '25', active: 'true', birthday: '2024-01-12' },
{ name: 'User 13', age: '20', active: 'true', birthday: '2024-01-13' },
{ name: 'User 14', age: '21', active: 'false', birthday: '2024-01-14' },
{ name: 'User 15', age: '22', active: 'false', birthday: '2024-01-15' },
] as const;
for (let i = 0; i < 15; i++) {
await n8n.dataTableDetails.addRow();
const rowIndexOnPage = i % 10;
await n8n.dataTableDetails.setCellValue(
rowIndexOnPage,
nameColumn,
rowsData[i].name,
'string',
{
skipDoubleClick: true,
},
);
await n8n.dataTableDetails.setCellValue(
rowIndexOnPage,
ageColumn,
rowsData[i].age,
'number',
);
await n8n.dataTableDetails.setCellValue(
rowIndexOnPage,
activeColumn,
rowsData[i].active,
'boolean',
);
await n8n.dataTableDetails.setCellValue(
rowIndexOnPage,
birthdayColumn,
rowsData[i].birthday,
'date',
);
}
await expect(n8n.dataTableDetails.getDataRows()).toHaveCount(5);
await n8n.dataTableDetails.setTextFilter(COLUMN_NAMES.name, 'User 1');
await expect(n8n.dataTableDetails.getDataRows()).toHaveCount(7);
await n8n.dataTableDetails.clearColumnFilter(COLUMN_NAMES.name);
await expect(n8n.dataTableDetails.getDataRows()).toHaveCount(10);
await n8n.dataTableDetails.setNumberFilter(COLUMN_NAMES.age, '22', 'greaterThan');
await expect(n8n.dataTableDetails.getDataRows()).toHaveCount(6);
await n8n.dataTableDetails.clearColumnFilter(COLUMN_NAMES.age);
await expect(n8n.dataTableDetails.getDataRows()).toHaveCount(10);
await n8n.dataTableDetails.setBooleanFilter(COLUMN_NAMES.active, true);
await expect(n8n.dataTableDetails.getDataRows()).toHaveCount(8);
await n8n.dataTableDetails.clearColumnFilter(COLUMN_NAMES.active);
await expect(n8n.dataTableDetails.getDataRows()).toHaveCount(10);
await n8n.dataTableDetails.setDateFilter(COLUMN_NAMES.birthday, '2024-01-10', 'greaterThan');
await expect(n8n.dataTableDetails.getDataRows()).toHaveCount(5);
await n8n.dataTableDetails.clearColumnFilter(COLUMN_NAMES.birthday);
await expect(n8n.dataTableDetails.getDataRows()).toHaveCount(10);
await n8n.dataTableDetails.setBooleanFilter(COLUMN_NAMES.active, true);
await n8n.dataTableDetails.setNumberFilter(COLUMN_NAMES.age, '22', 'greaterThan');
await expect(n8n.dataTableDetails.getDataRows()).toHaveCount(4);
});
test('Should reorder columns using drag and drop', async ({ n8n }) => {
await expect(n8n.dataTableDetails.getPageWrapper()).toBeVisible();
await n8n.dataTableDetails.addColumn(COLUMN_NAMES.name, 'string', 'header');
await n8n.dataTableDetails.addColumn(COLUMN_NAMES.age, 'number', 'header');
await n8n.dataTableDetails.addColumn(COLUMN_NAMES.active, 'boolean', 'header');
await n8n.dataTableDetails.addColumn(COLUMN_NAMES.birthday, 'date', 'header');
await n8n.dataTableDetails.addColumn('email', 'string', 'header');
const initialOrder = await n8n.dataTableDetails.getColumnOrder();
expect(initialOrder).toContain(COLUMN_NAMES.name);
expect(initialOrder).toContain(COLUMN_NAMES.age);
expect(initialOrder).toContain(COLUMN_NAMES.active);
expect(initialOrder).toContain(COLUMN_NAMES.birthday);
expect(initialOrder).toContain('email');
const nameIndex = initialOrder.indexOf(COLUMN_NAMES.name);
const activeIndex = initialOrder.indexOf(COLUMN_NAMES.active);
const emailIndex = initialOrder.indexOf('email');
await n8n.dataTableDetails.dragColumnToPosition(COLUMN_NAMES.active, COLUMN_NAMES.name);
const orderAfterFirstDrag = await n8n.dataTableDetails.getColumnOrder();
const newActiveIndex = orderAfterFirstDrag.indexOf(COLUMN_NAMES.active);
const newNameIndex = orderAfterFirstDrag.indexOf(COLUMN_NAMES.name);
expect(newActiveIndex).toBeLessThan(newNameIndex);
expect(activeIndex).toBeGreaterThan(nameIndex);
await n8n.dataTableDetails.dragColumnToPosition('email', COLUMN_NAMES.age);
const orderAfterSecondDrag = await n8n.dataTableDetails.getColumnOrder();
const emailIndexAfter = orderAfterSecondDrag.indexOf('email');
const ageIndexAfter = orderAfterSecondDrag.indexOf(COLUMN_NAMES.age);
expect(emailIndexAfter).toBeLessThan(ageIndexAfter);
expect(emailIndex).toBeGreaterThan(initialOrder.indexOf(COLUMN_NAMES.age));
await n8n.dataTableDetails.dragColumnToPosition(COLUMN_NAMES.birthday, COLUMN_NAMES.name);
const finalOrder = await n8n.dataTableDetails.getColumnOrder();
const birthdayFinalIndex = finalOrder.indexOf(COLUMN_NAMES.birthday);
const nameFinalIndex = finalOrder.indexOf(COLUMN_NAMES.name);
expect(birthdayFinalIndex).toBeLessThan(nameFinalIndex);
});
test('Should search and filter rows globally', async ({ n8n }) => {
await expect(n8n.dataTableDetails.getPageWrapper()).toBeVisible();
await n8n.dataTableDetails.addColumn(COLUMN_NAMES.name, 'string', 'header');
await n8n.dataTableDetails.addColumn(COLUMN_NAMES.age, 'number', 'header');
const nameColumn = await n8n.dataTableDetails.getColumnIdByName(COLUMN_NAMES.name);
const ageColumn = await n8n.dataTableDetails.getColumnIdByName(COLUMN_NAMES.age);
const testData = [
{ name: 'Alice Johnson', age: '25' },
{ name: 'Bob Smith', age: '30' },
{ name: 'Charlie Brown', age: '35' },
{ name: 'Diana Prince', age: '28' },
{ name: 'Eve Adams', age: '32' },
{ name: 'Frank Miller', age: '29' },
];
for (let i = 0; i < testData.length; i++) {
await n8n.dataTableDetails.addRow();
await n8n.dataTableDetails.setCellValue(i, nameColumn, testData[i].name, 'string', {
skipDoubleClick: true,
});
await n8n.dataTableDetails.setCellValue(i, ageColumn, testData[i].age, 'number');
}
await expect(n8n.dataTableDetails.getDataRows()).toHaveCount(6);
// Test search for partial name match
await n8n.dataTableDetails.search('Alice');
await expect(n8n.dataTableDetails.getDataRows()).toHaveCount(1);
const aliceValue = await n8n.dataTableDetails.getCellValue(0, nameColumn, 'string');
expect(aliceValue).toContain('Alice Johnson');
// Test search for last name
await n8n.dataTableDetails.search('Smith');
await expect(n8n.dataTableDetails.getDataRows()).toHaveCount(1);
const bobValue = await n8n.dataTableDetails.getCellValue(0, nameColumn, 'string');
expect(bobValue).toContain('Bob Smith');
// Test search across all columns (search by age)
await n8n.dataTableDetails.search('30');
await expect(n8n.dataTableDetails.getDataRows()).toHaveCount(1);
const bobAgeValue = await n8n.dataTableDetails.getCellValue(0, ageColumn, 'number');
expect(bobAgeValue).toContain('30');
// Test search with multiple results
await n8n.dataTableDetails.search('a');
const multipleResultsCount = await n8n.dataTableDetails.getDataRows().count();
expect(multipleResultsCount).toBeGreaterThan(1);
// Clear search and verify all rows are shown
await n8n.dataTableDetails.clearSearch();
await expect(n8n.dataTableDetails.getDataRows()).toHaveCount(6);
// Test case-insensitive search
await n8n.dataTableDetails.search('ALICE');
await expect(n8n.dataTableDetails.getDataRows()).toHaveCount(1);
const aliceCaseValue = await n8n.dataTableDetails.getCellValue(0, nameColumn, 'string');
expect(aliceCaseValue).toContain('Alice Johnson');
// Clear search for next test
await n8n.dataTableDetails.clearSearch();
await expect(n8n.dataTableDetails.getDataRows()).toHaveCount(6);
// test search combined with column filter
await n8n.dataTableDetails.setNumberFilter(COLUMN_NAMES.age, '29', 'greaterThan');
await n8n.dataTableDetails.search('Adams');
await expect(n8n.dataTableDetails.getDataRows()).toHaveCount(1);
const adamValue = await n8n.dataTableDetails.getCellValue(0, nameColumn, 'string');
expect(adamValue).toContain('Eve Adams');
});
},
);