</>

Technology

Playwright

Difficulty

Intermediate

Interview Question

How do you test infinite scroll pagination in Playwright?

Answer

Scenario: Testing Infinite Scroll Pagination

Infinite scroll loads more content as the user scrolls down, rather than using traditional pagination buttons.

Strategy 1 — Scroll to Bottom, Verify More Items Load

TypeScript
import { test, expect } from '@playwright/test';

test('infinite scroll loads more products', async ({ page }) => {
  await page.goto('/products');

  // Get initial count
  const initialCount = await page.locator('.product-card').count();
  expect(initialCount).toBe(20); // First page of 20

  // Scroll to the bottom of the page
  await page.evaluate(() => window.scrollTo(0, document.body.scrollHeight));

  // Wait for new items to load
  await page.locator('.product-card').nth(20).waitFor({ state: 'visible' });

  // Verify more items loaded
  const afterScrollCount = await page.locator('.product-card').count();
  expect(afterScrollCount).toBeGreaterThan(initialCount);
  expect(afterScrollCount).toBe(40); // Second batch of 20 loaded
});

Strategy 2 — Scroll Element Container (Not Full Page)

TypeScript
test('scroll within a product list container', async ({ page }) => {
  await page.goto('/feed');

  const feed = page.locator('.infinite-feed');
  const initialItems = await page.locator('.feed-item').count();

  // Scroll to bottom of the container
  await feed.evaluate(el => el.scrollTo(0, el.scrollHeight));

  // Wait for new items
  await page.locator('.feed-item').nth(initialItems).waitFor();

  const newCount = await page.locator('.feed-item').count();
  expect(newCount).toBeGreaterThan(initialItems);
});

Strategy 3 — Scroll Multiple Times Until Target

TypeScript
test('load 100 products via infinite scroll', async ({ page }) => {
  await page.goto('/products');

  let previousCount = 0;
  let currentCount = await page.locator('.product-card').count();

  // Keep scrolling until we have 100 products or no more load
  while (currentCount < 100) {
    await page.evaluate(() => window.scrollTo(0, document.body.scrollHeight));

    // Wait for network activity to settle
    await page.waitForLoadState('networkidle');

    previousCount = currentCount;
    currentCount = await page.locator('.product-card').count();

    // Break if no new items loaded (end of list)
    if (currentCount === previousCount) break;
  }

  expect(currentCount).toBeGreaterThanOrEqual(100);
});

Strategy 4 — Keyboard-Based Scrolling

TypeScript
test('scroll using keyboard', async ({ page }) => {
  await page.goto('/news-feed');

  // Click on the page first to give it focus
  await page.locator('body').click();

  const before = await page.locator('.news-card').count();

  // Press End key to jump to page bottom
  await page.keyboard.press('End');

  // Wait for more content
  await page.locator('.news-card').nth(before).waitFor({ timeout: 5000 });

  const after = await page.locator('.news-card').count();
  expect(after).toBeGreaterThan(before);
});

Strategy 5 — Intercept API to Verify Pagination Parameters

TypeScript
test('infinite scroll sends correct pagination params', async ({ page }) => {
  const apiCalls: string[] = [];

  await page.route('/api/products*', async route => {
    apiCalls.push(route.request().url());
    await route.continue();
  });

  await page.goto('/products');

  // Scroll once
  await page.evaluate(() => window.scrollTo(0, document.body.scrollHeight));
  await page.waitForLoadState('networkidle');

  // Verify second API call has page=2 or cursor parameter
  expect(apiCalls.length).toBeGreaterThan(1);
  expect(apiCalls[1]).toContain('page=2');
  // OR check cursor: expect(apiCalls[1]).toMatch(/cursor=\w+/);
});

Verify End of List

TypeScript
test('shows end-of-list message after loading all products', async ({ page }) => {
  await page.goto('/products');

  // Keep scrolling until end message appears
  let attempts = 0;
  while (attempts < 20) {
    if (await page.locator('.end-of-list').isVisible()) break;
    await page.evaluate(() => window.scrollTo(0, document.body.scrollHeight));
    await page.waitForTimeout(500); // Allow brief load time
    attempts++;
  }

  await expect(page.locator('.end-of-list')).toBeVisible();
  await expect(page.locator('.end-of-list')).toContainText('You have reached the end');
});

Follow AutomateQA

Related Topics