diff --git a/tests/ui-testing/playwright-tests/Dashboards/dashboard-table-pagination.spec.js b/tests/ui-testing/playwright-tests/Dashboards/dashboard-table-pagination.spec.js
index 93b5115fce..6e8095bb19 100644
--- a/tests/ui-testing/playwright-tests/Dashboards/dashboard-table-pagination.spec.js
+++ b/tests/ui-testing/playwright-tests/Dashboards/dashboard-table-pagination.spec.js
@@ -1113,11 +1113,9 @@ test.describe("Dashboard Table Chart Pagination Feature - PromQL Tables", () =>
const queryEditor = pm.chartTypeSelector.queryEditor;
await queryEditor.waitFor({ state: "visible", timeout: 10000 });
- // Focus on the editor and enter a PromQL query using keyboard.type for reliable Monaco input
+ // Fill the Monaco input directly; typing lets autocomplete corrupt the query
await queryEditor.getByRole('code').click();
- await page.keyboard.press('Control+a');
- await page.keyboard.type('cpu_usage{}');
- await page.keyboard.press('Escape'); // Dismiss any Monaco autocomplete suggestions
+ await queryEditor.locator('.inputarea').fill('cpu_usage{}');
// Apply
await pm.dashboardPanelActions.applyAndWaitForPromQLQuery();
@@ -1155,14 +1153,19 @@ test.describe("Dashboard Table Chart Pagination Feature - PromQL Tables", () =>
const paginationInfo = pm.dashboardPanelConfigs.tableRowCount;
await expect(paginationInfo).toHaveText(/^\s*\d+-\d+\s+of\s+\d+\s*$/, { timeout: 15000 });
- // Only the footer's presence and range shape are checked; the page-size count is wrong today (#15544) and its fix adds the exact assertion.
- const paginationText = await paginationInfo.textContent();
- expect(paginationText.trim()).toMatch(/^\d+-\d+\s+of\s+\d+$/);
+ // The page size must bound the range: "1-10 of N" with N > 10, never "1-N of N" (#15544).
+ const paginationText = (await paginationInfo.textContent()).trim();
+ const match = paginationText.match(/^1-(\d+)\s+of\s+(\d+)$/);
+ expect(match, `unexpected footer text "${paginationText}"`).not.toBeNull();
+ expect(Number(match[1])).toBe(10);
+ expect(Number(match[2])).toBeGreaterThanOrEqual(12);
- // Verify we're on the first page (starts with "1-")
- expect(paginationText.trim().startsWith('1-')).toBe(true);
+ const nextPage = page.locator('[data-test="dashboard-table-pagination-next-page"]');
+ await expect(nextPage).toBeVisible();
+ await nextPage.click();
+ await expect(paginationInfo).toHaveText(new RegExp(`^\\s*11-\\d+\\s+of\\s+${match[2]}\\s*$`));
- testLogger.info(`Verified PromQL table pagination: ${paginationText.trim()}`);
+ testLogger.info(`Verified PromQL table pagination: ${paginationText}`);
// Clean up - save panel first before navigating back
await pm.dashboardPanelActions.savePanel();
diff --git a/web/src/components/dashboards/panels/PromQLTableChart.spec.ts b/web/src/components/dashboards/panels/PromQLTableChart.spec.ts
index 25e4f6ba0b..a34a72af21 100644
--- a/web/src/components/dashboards/panels/PromQLTableChart.spec.ts
+++ b/web/src/components/dashboards/panels/PromQLTableChart.spec.ts
@@ -430,6 +430,47 @@ describe("PromQLTableChart", () => {
});
});
+ describe("Legend footer pagination", () => {
+ const twelveRows = Array.from({ length: 12 }, (_, i) => ({
+ __legend__: "series1",
+ timestamp: `2023-01-01T00:${String(i).padStart(2, "0")}:00Z`,
+ value: i,
+ }));
+
+ const mountPaginated = () =>
+ createWrapper({
+ data: { columns: mockTableData.columns, rows: twelveRows },
+ config: { ...mockConfig, table_pagination: true, table_pagination_rows_per_page: 10 },
+ });
+
+ it("shows the page range, page size and navigation from the table's pagination state", async () => {
+ wrapper = mountPaginated();
+ await flushPromises();
+
+ expect(wrapper.find('[data-test="dashboard-table-row-count"]').text()).toBe("1-10 of 12");
+ expect(wrapper.find('[data-test="dashboard-table-pagination-next-page"]').exists()).toBe(
+ true,
+ );
+ expect(wrapper.find('[data-test="dashboard-table-pagination-last-page"]').exists()).toBe(
+ true,
+ );
+ expect(wrapper.find('[data-test="dashboard-table-rows-per-page-select"]').text()).toContain(
+ "10",
+ );
+ });
+
+ it("reaches the remaining rows on the next page", async () => {
+ wrapper = mountPaginated();
+ await flushPromises();
+
+ await wrapper.find('[data-test="dashboard-table-pagination-next-page"]').trigger("click");
+ await flushPromises();
+
+ expect(wrapper.find('[data-test="dashboard-table-row-count"]').text()).toBe("11-12 of 12");
+ expect(wrapper.findAll('tbody tr[data-test^="o2-table-row-"]').length).toBe(2);
+ });
+ });
+
describe("Event Handling", () => {
it("should emit row-click when TableRenderer emits row-click", async () => {
wrapper = createWrapper();
diff --git a/web/src/components/dashboards/panels/PromQLTableChart.vue b/web/src/components/dashboards/panels/PromQLTableChart.vue
index bb0c529330..61c30f2d3e 100644
--- a/web/src/components/dashboards/panels/PromQLTableChart.vue
+++ b/web/src/components/dashboards/panels/PromQLTableChart.vue
@@ -65,13 +65,12 @@ along with this program. If not, see