Navigate paginated data using cursor-based pagination
Cursor-paginated items
null
GraphQL-style pageInfo
{ "data": [ "item-001", "item-002", "item-003", "item-004", "item-005", "item-006", "item-007", "item-008", "item-009", "item-010" ], "pageInfo": { "hasNextPage": true, "hasPreviousPage": false, "startCursor": "item-001", "endCursor": "item-010" }, "totalCount": 100 }
Key concepts to verify
Testing hints
// Check initial state await expect(page.locator('[data-testid="page-info"]')).toContainText('Page 1'); await expect(page.locator('[data-testid="cursor-info"]')).toContainText('null'); // Navigate to next page await page.click('[data-testid="next-button"]'); await expect(page.locator('[data-testid="page-info"]')).toContainText('Page 2'); await expect(page.locator('[data-testid="cursor-info"]')).not.toContainText('null'); // Verify first item on page 2 await expect(page.locator('[data-testid="row-item-011"]')).toBeVisible(); // Check API response structure const response = await page.locator('[data-testid="api-response"]').textContent(); const data = JSON.parse(response || '{}'); expect(data.pageInfo.hasNextPage).toBe(true); expect(data.pageInfo.startCursor).toBe('item-011'); // Navigate to previous page await page.click('[data-testid="prev-button"]'); await expect(page.locator('[data-testid="page-info"]')).toContainText('Page 1'); await expect(page.locator('[data-testid="row-item-001"]')).toBeVisible(); // Change page size await page.selectOption('[data-testid="page-size"]', '20'); await expect(page.locator('[data-testid="items-table"] tbody tr')).toHaveCount(20); // Navigate to last page while (await page.locator('[data-testid="next-button"]').getAttribute('data-has-next') === 'true') { await page.click('[data-testid="next-button"]'); } await expect(page.locator('[data-testid="next-button"]')).toBeDisabled(); // Reset pagination await page.click('[data-testid="reset-button"]'); await expect(page.locator('[data-testid="cursor-info"]')).toContainText('null');