Таблицы на веб-страницах часто используются для отображения данных в
структурированном виде. В автоматизированном тестировании критически
важно проверять корректность их сортировки. В Protractor работа с
таблицами строится на взаимодействии с элементами DOM,
используя CSS-селекторы, XPath и
методы element и
element.all.
Для начала необходимо выделить следующие компоненты таблицы:
<th>), на
которые кликают для сортировки.<tr>),
содержащие ячейки данных (<td>).let table = element(by.css('table#myTable'));
let headers = table.all(by.css('th'));
let rows = table.all(by.css('tbody tr'));
element(by.css('table#myTable')) — основной контейнер
таблицы.table.all(by.css('th')) — список всех заголовков,
доступных для сортировки.table.all(by.css('tbody tr')) — строки данных, по
которым будет проверяться порядок.Для проверки сортировки необходимо извлечь значения из ячеек:
async function getColumnValues(columnIndex) {
return await rows.map(async (row) => {
let cell = row.all(by.css('td')).get(columnIndex);
return cell.getText();
});
}
columnIndex указывает номер колонки, которую нужно
проверять.map возвращает массив всех значений ячеек в
указанной колонке.Для взаимодействия с заголовком таблицы используют метод
click():
async function sortByColumn(columnIndex) {
let header = headers.get(columnIndex);
await header.click();
await browser.sleep(500); // ожидание завершения сортировки
}
ExpectedConditions, чтобы дождаться обновления
DOM.let EC = protractor.ExpectedConditions;
await browser.wait(EC.stalenessOf(rows.first()), 5000);
rows = table.all(by.css('tbody tr')); // обновляем строки после сортировки
Чтобы проверить, что данные отсортированы корректно, извлечённый массив значений сравнивают с отсортированной версией:
async function isSortedAscending(columnIndex) {
let values = await getColumnValues(columnIndex);
let sorted = [...values].sort((a, b) => a.localeCompare(b));
return JSON.stringify(values) === JSON.stringify(sorted);
}
async function isSortedDescending(columnIndex) {
let values = await getColumnValues(columnIndex);
let sorted = [...values].sort((a, b) => b.localeCompare(a));
return JSON.stringify(values) === JSON.stringify(sorted);
}
localeCompare учитывает локализацию текста, что важно
при работе с кириллицей или другими национальными алфавитами.JSON.stringify позволяет убедиться, что
порядок элементов точный, а не просто отсортирован по содержимому.Текстовое сравнение подходит не всегда. Для чисел и дат лучше приводить значения к нужному типу:
async function getNumericColumnValues(columnIndex) {
let values = await getColumnValues(columnIndex);
return values.map(value => parseFloat(value.replace(',', '.')));
}
async function getDateColumnValues(columnIndex) {
let values = await getColumnValues(columnIndex);
return values.map(value => new Date(value));
}
parseFloat с заменой запятой на точку
важно для корректной работы с числовыми форматами в разных локалях.Date для удобного
сравнения.Многие таблицы меняют порядок сортировки по повторным кликам на один и тот же заголовок (возрастание → убывание → сброс). Пример универсальной функции:
async function toggleSort(columnIndex, order = 'asc') {
let header = headers.get(columnIndex);
let attempts = 0;
let sorted = false;
while (!sorted && attempts < 3) {
await header.click();
await browser.sleep(500);
if (order === 'asc') {
sorted = await isSortedAscending(columnIndex);
} else {
sorted = await isSortedDescending(columnIndex);
}
attempts++;
}
if (!sorted) {
throw new Error(`Колонка ${columnIndex} не отсортирована в порядке ${order}`);
}
}
ExpectedConditions для
ожидания изменения DOM вместо browser.sleep, чтобы тесты
были стабильными.map и
reduce для обработки массивов, чтобы избежать излишней
нагрузки на браузер.Если таблица подгружается по мере прокрутки
(infinite scroll), необходимо реализовать ленивую
выборку строк:
async function getAllRows() {
let allRows = [];
let currentCount = 0;
let newRows;
do {
newRows = await table.all(by.css('tbody tr')).count();
if (newRows > currentCount) {
allRows = await table.all(by.css('tbody tr')).getText();
currentCount = newRows;
await browser.executeScript('window.scrollTo(0, document.body.scrollHeight);');
await browser.sleep(500);
}
} while (newRows > currentCount);
return allRows;
}
executeScript позволяет прокрутить
страницу для подгрузки данных.Для проверки сортировки удобно интегрировать функции в тестовые фреймворки:
it('Должен сортировать таблицу по возрастанию', async () => {
await toggleSort(2, 'asc'); // сортировка по третьей колонке
expect(await isSortedAscending(2)).toBe(true);
});
it('Должен сортировать таблицу по убыванию', async () => {
await toggleSort(2, 'desc'); // сортировка по третьей колонке
expect(await isSortedDescending(2)).toBe(true);
});
async/await)
обеспечивает стабильность и последовательность операций.