Skip to content

Commit ef1083e

Browse files
committed
feat: add test, increase pagination limit
1 parent 5933435 commit ef1083e

File tree

4 files changed

+157
-24
lines changed

4 files changed

+157
-24
lines changed

src/store/reducers/operations.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import type {
88

99
import {api} from './api';
1010

11-
const DEFAULT_PAGE_SIZE = 10;
11+
const DEFAULT_PAGE_SIZE = 20;
1212

1313
export const operationsApi = api.injectEndpoints({
1414
endpoints: (build) => ({

tests/suites/tenant/diagnostics/tabs/OperationsModel.ts

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,4 +142,56 @@ export class OperationsTable extends BaseModel {
142142
async getAccessDeniedTitle(): Promise<string> {
143143
return await this.accessDeniedTitle.innerText();
144144
}
145+
146+
async getOperationsCount(): Promise<number> {
147+
// The EntitiesCount component renders a Label with the count
148+
const countLabel = await this.page
149+
.locator('.ydb-entities-count .g-label__content')
150+
.textContent();
151+
if (!countLabel) {
152+
return 0;
153+
}
154+
const match = countLabel.match(/(\d+)/);
155+
return match ? parseInt(match[1], 10) : 0;
156+
}
157+
158+
async waitForOperationsCount(expectedCount: number, timeout = 5000): Promise<void> {
159+
await this.page.waitForFunction(
160+
(expected) => {
161+
const countElement = document.querySelector(
162+
'.ydb-entities-count .g-label__content',
163+
);
164+
if (!countElement) {
165+
return false;
166+
}
167+
const text = countElement.textContent || '';
168+
const match = text.match(/(\d+)/);
169+
const currentCount = match ? parseInt(match[1], 10) : 0;
170+
return currentCount === expected;
171+
},
172+
expectedCount,
173+
{timeout},
174+
);
175+
}
176+
177+
async waitForOperationsCountToChange(previousCount: number, timeout = 5000): Promise<number> {
178+
await this.page.waitForFunction(
179+
(prev) => {
180+
const countElement = document.querySelector(
181+
'.ydb-entities-count .g-label__content',
182+
);
183+
if (!countElement) {
184+
return false;
185+
}
186+
const text = countElement.textContent || '';
187+
const match = text.match(/(\d+)/);
188+
const currentCount = match ? parseInt(match[1], 10) : 0;
189+
return currentCount !== prev;
190+
},
191+
previousCount,
192+
{timeout},
193+
);
194+
// Now get the actual new count
195+
return await this.getOperationsCount();
196+
}
145197
}

tests/suites/tenant/diagnostics/tabs/operations.test.ts

Lines changed: 103 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@ import {
1212

1313
test.describe('Operations Tab - Infinite Query', () => {
1414
test('loads initial page of operations on tab click', async ({page}) => {
15-
// Setup mocks with 30 operations (3 pages of 10)
16-
await setupOperationsMock(page, {totalOperations: 30});
15+
// Setup mocks with 80 operations (4 pages of 20)
16+
await setupOperationsMock(page, {totalOperations: 80});
1717

1818
const pageQueryParams = {
1919
schema: tenantName,
@@ -31,10 +31,13 @@ test.describe('Operations Tab - Infinite Query', () => {
3131
await diagnostics.operations.waitForTableVisible();
3232
await diagnostics.operations.waitForDataLoad();
3333

34-
// Verify initial page loaded (should have some rows)
35-
const rowCount = await diagnostics.operations.getRowCount();
36-
expect(rowCount).toBeGreaterThan(0);
37-
expect(rowCount).toBeLessThanOrEqual(20); // Reasonable page size
34+
// Wait a bit for the counter to stabilize after initial load
35+
await page.waitForTimeout(1000);
36+
37+
// Verify initial page loaded (should show count in badge)
38+
const operationsCount = await diagnostics.operations.getOperationsCount();
39+
expect(operationsCount).toBeGreaterThan(0);
40+
expect(operationsCount).toBeLessThanOrEqual(20); // Should have up to DEFAULT_PAGE_SIZE operations loaded initially
3841

3942
// Verify first row data structure
4043
const firstRowData = await diagnostics.operations.getRowData(0);
@@ -53,8 +56,8 @@ test.describe('Operations Tab - Infinite Query', () => {
5356
});
5457

5558
test('loads more operations on scroll', async ({page}) => {
56-
// Setup mocks with 30 operations (3 pages of 10)
57-
await setupOperationsMock(page, {totalOperations: 30});
59+
// Setup mocks with 80 operations (4 pages of 20)
60+
await setupOperationsMock(page, {totalOperations: 80});
5861

5962
const pageQueryParams = {
6063
schema: tenantName,
@@ -72,26 +75,32 @@ test.describe('Operations Tab - Infinite Query', () => {
7275
await diagnostics.operations.waitForTableVisible();
7376
await diagnostics.operations.waitForDataLoad();
7477

75-
// Get initial row count
76-
const initialRowCount = await diagnostics.operations.getRowCount();
77-
expect(initialRowCount).toBeGreaterThan(0);
78+
// Get initial operations count
79+
const initialOperationsCount = await diagnostics.operations.getOperationsCount();
80+
expect(initialOperationsCount).toBeGreaterThan(0);
7881

7982
// Scroll to bottom
8083
await diagnostics.operations.scrollToBottom();
8184

82-
// Wait a bit for potential loading
83-
await page.waitForTimeout(2000);
84-
85-
// Get final row count
86-
const finalRowCount = await diagnostics.operations.getRowCount();
85+
// Wait for operations count to potentially change
86+
let finalOperationsCount: number;
87+
try {
88+
finalOperationsCount = await diagnostics.operations.waitForOperationsCountToChange(
89+
initialOperationsCount,
90+
3000,
91+
);
92+
} catch (_e) {
93+
// If timeout, the count didn't change
94+
finalOperationsCount = await diagnostics.operations.getOperationsCount();
95+
}
8796

88-
// Check if more rows were loaded
89-
if (finalRowCount > initialRowCount) {
90-
// Infinite scroll worked - more rows were loaded
91-
expect(finalRowCount).toBeGreaterThan(initialRowCount);
97+
// Check if more operations were loaded
98+
if (finalOperationsCount > initialOperationsCount) {
99+
// Infinite scroll worked - more operations were loaded
100+
expect(finalOperationsCount).toBeGreaterThan(initialOperationsCount);
92101
} else {
93-
// No more data to load - row count should stay the same
94-
expect(finalRowCount).toBe(initialRowCount);
102+
// No more data to load - operations count should stay the same
103+
expect(finalOperationsCount).toBe(initialOperationsCount);
95104
}
96105
});
97106

@@ -150,4 +159,76 @@ test.describe('Operations Tab - Infinite Query', () => {
150159
const accessDeniedTitle = await diagnostics.operations.getAccessDeniedTitle();
151160
expect(accessDeniedTitle).toBe('Access denied');
152161
});
162+
163+
test('loads all operations when scrolling to the bottom multiple times', async ({page}) => {
164+
// Setup mocks with 80 operations (4 pages of 20)
165+
await setupOperationsMock(page, {totalOperations: 80});
166+
167+
const pageQueryParams = {
168+
schema: tenantName,
169+
database: tenantName,
170+
tenantPage: 'diagnostics',
171+
};
172+
173+
const tenantPageInstance = new TenantPage(page);
174+
await tenantPageInstance.goto(pageQueryParams);
175+
176+
const diagnostics = new Diagnostics(page);
177+
await diagnostics.clickTab(DiagnosticsTab.Operations);
178+
179+
// Wait for initial data
180+
await diagnostics.operations.waitForTableVisible();
181+
await diagnostics.operations.waitForDataLoad();
182+
183+
// Wait a bit for the counter to stabilize after initial load
184+
await page.waitForTimeout(2000);
185+
186+
// Get initial operations count (should be around 20)
187+
const initialOperationsCount = await diagnostics.operations.getOperationsCount();
188+
expect(initialOperationsCount).toBeGreaterThan(0);
189+
expect(initialOperationsCount).toBeLessThanOrEqual(20);
190+
191+
// Keep scrolling until all operations are loaded
192+
let previousOperationsCount = initialOperationsCount;
193+
let currentOperationsCount = initialOperationsCount;
194+
const maxScrollAttempts = 10; // Safety limit to prevent infinite loop
195+
let scrollAttempts = 0;
196+
197+
while (currentOperationsCount < 80 && scrollAttempts < maxScrollAttempts) {
198+
// Scroll to bottom
199+
await diagnostics.operations.scrollToBottom();
200+
201+
// Wait for potential loading
202+
await page.waitForTimeout(1000);
203+
204+
// Check if loading more is visible and wait for it to complete
205+
const isLoadingVisible = await diagnostics.operations.isLoadingMoreVisible();
206+
if (isLoadingVisible) {
207+
await diagnostics.operations.waitForLoadingMoreToDisappear();
208+
}
209+
210+
// Wait for operations count to change or timeout
211+
try {
212+
currentOperationsCount =
213+
await diagnostics.operations.waitForOperationsCountToChange(
214+
previousOperationsCount,
215+
3000,
216+
);
217+
} catch (_e) {
218+
// If timeout, the count didn't change - we might have reached the end
219+
currentOperationsCount = await diagnostics.operations.getOperationsCount();
220+
}
221+
222+
previousOperationsCount = currentOperationsCount;
223+
scrollAttempts++;
224+
}
225+
226+
// Verify all 80 operations were loaded
227+
expect(currentOperationsCount).toBe(80);
228+
229+
const rowCount = await diagnostics.operations.getRowCount();
230+
// Verify the last operation has the expected ID pattern
231+
const lastRowData = await diagnostics.operations.getRowData(rowCount - 1);
232+
expect(lastRowData['Operation ID']).toContain('ydb://');
233+
});
153234
});

tests/suites/tenant/diagnostics/tabs/operationsMocks.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ export const setupOperationsMock = async (page: Page, options?: OperationMockOpt
123123
const url = new URL(route.request().url());
124124
const params = Object.fromEntries(url.searchParams);
125125

126-
const requestedPageSize = parseInt(params.page_size || '10', 10);
126+
const requestedPageSize = parseInt(params.page_size || '20', 10);
127127
const pageToken = params.page_token;
128128
const kind = params.kind || 'buildindex';
129129

0 commit comments

Comments
 (0)