PluginProbe ʕ •ᴥ•ʔ
Presto Player / trunk
Presto Player vtrunk
4.3.0 4.2.4 4.2.3 4.2.2 4.2.0 4.2.1 trunk 1.10.0 1.10.1 1.10.2 1.11.0 1.12.0 1.13.0 1.14.0 1.14.1 1.5.10 1.5.11 1.5.12 1.5.13 1.5.14 1.5.15 1.5.5 1.5.6 1.5.7 1.5.8 1.5.9 1.6.0 1.6.1 1.6.10 1.6.11 1.6.12 1.6.13 1.6.2 1.6.3 1.6.4 1.6.5 1.6.6 1.6.7 1.6.8 1.6.9 1.7.0 1.7.1 1.7.2 1.8.0 1.8.1 1.8.2 1.8.3 1.8.4 1.8.5 1.8.6 1.9.0 1.9.1 1.9.10 1.9.11 1.9.12 1.9.13 1.9.14 1.9.2 1.9.3 1.9.4 1.9.5 1.9.6 1.9.7 1.9.8 1.9.9 2.0.0 2.0.1 2.0.10 2.0.11 2.0.12 2.0.13 2.0.14 2.0.15 2.0.16 2.0.2 2.0.3 2.0.4 2.0.5 2.0.6 2.0.7 2.0.8 2.0.9 2.1.0 2.2.0 2.2.1 2.2.2 2.2.3 2.2.3-beta1 2.3.0 2.3.1 2.3.2 2.3.3 3.0.0 3.0.0-beta1 3.0.1 3.0.2 3.0.3 3.0.4 3.0.5 3.0.6 3.0.7 3.0.8 3.1.0 3.1.1 3.1.2 3.1.3 4.0.0 4.0.1 4.0.2 4.0.3 4.0.4 4.0.5 4.0.6 4.0.7 4.0.8 4.1.0 4.1.1 4.1.2 4.1.3 4.1.4
presto-player / src / admin / dashboard / components / test / RankedTable.spec.js
presto-player / src / admin / dashboard / components / test Last commit date
RankedTable.spec.js 1 month ago StatCard.spec.js 1 month ago TruncatedTitle.spec.js 1 month ago
RankedTable.spec.js
163 lines
1 import { render, screen, fireEvent } from "@testing-library/react";
2 import RankedTable from "../RankedTable";
3
4 const cols = [
5 {
6 key: "name",
7 header: "Name",
8 cellClassName: "name-cell",
9 render: (r) => r.name,
10 },
11 ];
12
13 const makeRows = (n, offset = 0) =>
14 Array.from({ length: n }, (_, i) => ({
15 id: offset + i + 1,
16 name: `row-${offset + i + 1}`,
17 }));
18
19 const renderTable = (props = {}) =>
20 render(
21 <RankedTable
22 title="Top"
23 columns={cols}
24 rows={props.rows ?? makeRows(10)}
25 pagination={
26 props.pagination === null
27 ? undefined
28 : {
29 currentPage: 1,
30 totalItems: 12,
31 totalPages: 2,
32 perPage: 10,
33 onPageChange: jest.fn(),
34 ...props.pagination,
35 }
36 }
37 emptyState={props.emptyState}
38 rowAction={props.rowAction}
39 onRowClick={props.onRowClick}
40 />
41 );
42
43 describe("RankedTable", () => {
44 it('hides the pagination footer when totalPages <= 1', () => {
45 renderTable({
46 rows: makeRows(3),
47 pagination: { totalItems: 3, totalPages: 1 },
48 });
49 expect(screen.queryByText(/of \d+ items/i)).not.toBeInTheDocument();
50 });
51
52 it('displays "1–10 of 12 items" on the first page of a two-page set', () => {
53 renderTable({
54 rows: makeRows(10),
55 pagination: { currentPage: 1, totalItems: 12, totalPages: 2, perPage: 10 },
56 });
57 expect(screen.getByText(/1\s*[–-]\s*10\s+of\s+12\s+items/i)).toBeInTheDocument();
58 });
59
60 it('displays "11–12 of 12 items" on the last (partial) page', () => {
61 renderTable({
62 rows: makeRows(2, 10),
63 pagination: { currentPage: 2, totalItems: 12, totalPages: 2, perPage: 10 },
64 });
65 expect(screen.getByText(/11\s*[–-]\s*12\s+of\s+12\s+items/i)).toBeInTheDocument();
66 });
67
68 it("calls onPageChange with the clicked page number", () => {
69 const onPageChange = jest.fn();
70 renderTable({
71 rows: makeRows(10),
72 pagination: { currentPage: 1, totalItems: 12, totalPages: 2, perPage: 10, onPageChange },
73 });
74 fireEvent.click(screen.getByText("2"));
75 expect(onPageChange).toHaveBeenCalledWith(2);
76 });
77
78 it("renders the empty state when rows is empty", () => {
79 const empty = <div data-testid="empty">No items</div>;
80 renderTable({ rows: [], emptyState: empty });
81 expect(screen.getByTestId("empty")).toBeInTheDocument();
82 // No data rows when empty.
83 expect(screen.queryAllByRole("row")).toHaveLength(0);
84 });
85
86 it("renders a trailing action cell when rowAction is provided", () => {
87 renderTable({
88 rows: makeRows(2),
89 rowAction: (r) => <button type="button">action-{r.id}</button>,
90 });
91 expect(screen.getByRole("button", { name: "action-1" })).toBeInTheDocument();
92 expect(screen.getByRole("button", { name: "action-2" })).toBeInTheDocument();
93 });
94
95 it("calls onRowClick with the row when a body row is clicked", () => {
96 const onRowClick = jest.fn();
97 renderTable({ rows: makeRows(3), onRowClick });
98 const bodyRows = screen.getAllByRole("row").slice(1); // skip header
99 fireEvent.click(bodyRows[1]);
100 expect(onRowClick).toHaveBeenCalledWith(
101 expect.objectContaining({ id: 2, name: "row-2" })
102 );
103 });
104
105 describe("paginated windowing", () => {
106 const renderPaged = (currentPage, totalPages) =>
107 renderTable({
108 rows: makeRows(5),
109 pagination: {
110 currentPage,
111 totalItems: totalPages * 5,
112 totalPages,
113 perPage: 5,
114 onPageChange: jest.fn(),
115 },
116 });
117
118 const pageButtons = () =>
119 Array.from(document.querySelectorAll('nav[role="navigation"] li'))
120 .map((li) => li.textContent.trim())
121 .filter((t) => /^\d+$/.test(t));
122
123 it("renders every page button when totalPages <= 7", () => {
124 renderPaged(3, 7);
125 expect(pageButtons()).toEqual(["1", "2", "3", "4", "5", "6", "7"]);
126 // No ellipses needed below the threshold.
127 expect(screen.queryByText("•••")).not.toBeInTheDocument();
128 });
129
130 it("shows only a right-side ellipsis when current page is near the start", () => {
131 renderPaged(1, 17);
132 // First 5 pages + ellipsis + last page.
133 expect(pageButtons()).toEqual(["1", "2", "3", "4", "5", "17"]);
134 expect(screen.getAllByText("•••")).toHaveLength(1);
135 });
136
137 it("shows ellipses on both sides when current page is in the middle", () => {
138 renderPaged(11, 17);
139 // First + ellipsis + (current±1) + ellipsis + last — the exact preview
140 // shown in the AskUserQuestion: 1 ... 10 [11] 12 ... 17.
141 expect(pageButtons()).toEqual(["1", "10", "11", "12", "17"]);
142 expect(screen.getAllByText("•••")).toHaveLength(2);
143 });
144
145 it("shows only a left-side ellipsis when current page is near the end", () => {
146 renderPaged(17, 17);
147 expect(pageButtons()).toEqual(["1", "13", "14", "15", "16", "17"]);
148 expect(screen.getAllByText("•••")).toHaveLength(1);
149 });
150
151 it("keeps the last page reachable on every page", () => {
152 // Iterating across every page in a 17-page set, the last page button
153 // must always be present so users can never get stuck mid-pager.
154 for (let p = 1; p <= 17; p++) {
155 const { unmount } = renderPaged(p, 17);
156 expect(pageButtons()).toContain("17");
157 unmount();
158 }
159 });
160 });
161
162 });
163