How to Write Test Cases for Infinite Scroll (With Examples)

How to Write Test Cases for Infinite Scroll (With Examples)

April 20, 2026 · 19 min read · How-To Guides

How to Write Test Cases for Infinite Scroll (With Examples)

Infinite scroll is a UI pattern that loads content dynamically as the user scrolls toward the bottom of a list or feed. Testing it requires verifying that data fetches correctly, rendering stays stable, interactions remain usable, and failure modes are handled gracefully. This guide walks through a complete test‑case workflow: defining test‑case anatomy, building a concrete matrix of 20+ examples, prioritizing them, linking to requirements, and augmenting manual designs with autonomous exploration. Every section contains actionable steps, tables, or code snippets you can copy into your test repository today.

Understanding Infinite Scroll Behavior

Before writing test cases, clarify what the infinite‑scroll component does under the hood. Most implementations consist of three collaborating parts:

  1. Viewport detector – a scroll listener (often IntersectionObserver or a scroll‑event handler) that fires when the user nears the bottom threshold.
  2. Data loader – an asynchronous request (REST, GraphQL, WebSocket) that asks the backend for the next page of items, usually identified by a cursor, offset, or timestamp.
  3. Renderer – a function that appends the newly received items to the DOM or RecyclerView, updates internal state, and may adjust placeholders or loading spinners.

Key behavioral contracts to test:

Understanding these contracts lets you map each test case to a specific verification point, avoiding overlap and ensuring high signal.

Anatomy of a Good Test Case for Infinite Scroll

A test case that survives review and automation follows a strict structure:

ElementPurposeExample for Infinite Scroll
IDUnique identifier (e.g., IS-001)IS-001
TitleConcise description of what is verified“Initial load shows first page and loading spinner appears on scroll near bottom”
PreconditionsRequired state before execution“App is launched, user is logged in, network is stable, backend returns page 1 with 20 items”
StepsOrdered actions the tester or script performs1. Wait for list to render
2. Scroll down until the last item is within 150 px of viewport bottom
3. Observe network request
4. Verify UI
Expected ResultObservable outcome that determines PASS/FAIL“A second network request for page 2 is issued, a spinner shows while waiting, and after response the list contains 40 items with no duplicates”
Test TypeFunctional, negative, performance, accessibility, etc.Functional
PriorityP0 (must), P1 (should), P2 (could)P0
TraceabilityLink to requirement or user storyREQ-INF-03: Load next page on scroll
Automation FlagIndicates if case is scripted, manual, or hybridAutomated (Playwright)
NotesAny special setup, flakiness mitigation, or data‑seed notesUse mock server that delays page 2 by 300 ms to observe spinner

Keep each element explicit; vague preconditions like “app is ready” lead to irreproducible results. When you write the steps, phrase them as imperative commands that a test runner can follow without interpretation (e.g., “swipe up 800 px” rather than “scroll a bit”).

Positive Test Cases (Normal Operation)

Positive cases confirm the happy path: data loads, UI updates, and the user can continue scrolling indefinitely. Below is a matrix of 12 core positive cases. Each row follows the anatomy defined above.

IDTitlePreconditionsStepsExpected ResultPriorityTraceability
IS-001Initial load renders first page and shows loading indicator on approachApp launched, authenticated, mock API returns page 1 (20 items) with hasMore:true1. Wait for list to render
2. Scroll down until last item is within 120 px of viewport bottom
3. Observe network tab
A GET request for page 2 is triggered, a spinner appears over the list, and after 300 ms the list expands to 40 itemsP0REQ-INF-01
IS-002Subsequent scrolls trigger correct pagination offsetsPrecondition: page 1 and page 2 already loaded (40 items)1. Scroll until near bottom again
2. Check request URL/query
Request for page 3 with correct cursor/offset is sent, no duplicate request for page 2P0REQ-INF-02
IS-003List maintains item order and uniqueness after multiple loadsPrecondition: three pages loaded (60 items) each with unique IDs 1‑601. Scroll to bottom twice more
2. Collect all item IDs from DOM
IDs 1‑80 appear exactly once, in ascending orderP0REQ-INF-03
IS-004Loading spinner disappears after successful fetchPrecondition: network latency simulated 500 ms for page 31. Trigger load for page 3
2. Observe spinner visibility
Spinner is visible from request start until DOM update completes, then hiddenP1REQ-UX-05
IS-005Placeholder rows are replaced with real data without layout shiftPrecondition: server returns items with varying heights1. Enable placeholder shimmer
2. Scroll to trigger load
3. Measure viewport scroll position before and after
Scroll position change < 5 px (no jump), placeholders swapped with actual contentP1REQ-UX-06
IS-006End‑of‑list signal stops further loadsPrecondition: mock API returns hasMore:false on page 51. Scroll until page 5 loads
2. Continue scrolling to bottom
No further network requests, a “No more content” banner appearsP0REQ-INF-04
IS-007Scrolling back up does not reload already‑fetched pagesPrecondition: pages 1‑4 loaded1. Scroll to bottom to load page 4
2. Swipe up fully to top
3. Scroll down again
No new requests for pages 1‑4; only page 5 request if applicableP1REQ-PERF-01
IS-008Rapid successive scrolls (fling) trigger at most one request per viewport crossingPrecondition: network delay 400 ms1. Perform a fast fling that crosses threshold twice within 200 ms
2. Count network calls
Exactly one request for the next page is madeP1REQ-PERF-02
IS-009Scrolling works with keyboard (Page Down) as well as touchPrecondition: focusable list container1. Press Page Down repeatedly
2. Observe network
Each Page Down that reaches the threshold triggers a load, same as touchP1REQ-ACC-01
IS-010Screen‑reader announces newly added itemsPrecondition: TalkBack/VoiceOver enabled1. Trigger load for next page
2. Listen to announcements
Screen reader reads “20 new items loaded” or reads each new item as it appearsP1REQ-ACC-02
IS-011List retains scroll position after orientation changePrecondition: user scrolled halfway through page 31. Rotate device to landscape
2. Return to portrait
Scroll offset restored, same visible items, no extra requestP1REQ-UX-07
IS-012Infinite scroll works under weak 3G simulationPrecondition: network throttled to 1.6 Mbps downlink, 400 ms RTT1. Scroll to trigger load
2. Measure time from request start to UI update
Update completes within 2 seconds, spinner shown throughoutP2REQ-PERF-03

These twelve cases cover the essential functional flow, ordering, UI feedback, termination, accessibility, and basic performance under normal conditions.

Negative and Error Handling Test Cases

Infinite scroll must degrade gracefully when the backend fails, returns malformed data, or the device loses connectivity. Negative cases verify that the UI stays usable and that no corrupt state leaks.

IDTitlePreconditionsStepsExpected ResultPriorityTraceability
ISN-001Network timeout shows error banner and allows retryMock API delays page 2 beyond 10 s timeout1. Scroll to trigger page 2 load
2. Wait for timeout
Error banner appears with “Retry” button, existing items remain unchanged, spinner hiddenP0REQ-ERR-01
ISN-002HTTP 500 response displays error state without crashingMock API returns 500 Internal Server Error for page 21. Trigger load for page 2
2. Observe UI
Error banner shown, list still displays page 1 items, no JavaScript exception in consoleP0REQ-ERR-02
ISN-003Malformed JSON (missing required fields) is handled safelyMock API returns page 2 with items lacking id1. Trigger load
2. Observe rendering
Items with missing data are skipped or shown as placeholders, no crash, console logs warningP1REQ-ERR-03
ISN-004Empty response (zero items) with hasMore:true does not cause infinite loopMock API returns empty array but hasMore:true1. Trigger load
2. Observe behavior
No new rows added, spinner hidden, a temporary “Loading…” toast may appear, subsequent scrolls again trigger load (no busy‑loop)P1REQ-ERR-04
ISN-005Sudden loss of network mid‑fetch shows offline stateMock API disconnects after request headers sent1. Start scroll load
2. Drop network
3. Wait
Offline banner appears, spinner hidden, user can retry when connectivity returnsP0REQ-ERR-06
ISN-006Rapid error bursts (e.g., 5xx then timeout) do not stack multiple bannersMock API alternates 500 and timeout1. Trigger three rapid loads causing errors
2. Observe UI
Only the most recent error banner is visible, no duplicate bannersP1REQ-UX-08
ISN-007User taps retry after error, scrolling again triggers a fresh requestPrecondition: error banner visible from ISN-0011. Tap “Retry” button
2. Scroll to bottom again
New request issued, previous error cleared on successP1REQ-ERR-07
ISN-008Accessibility live region updates when error appearsPrecondition: screen reader active1. Cause network error
2. Listen to announcements
Live region announces “Error loading more items. Tap to retry.”P1REQ-ACC-03
ISN-009Error state persists across configuration changePrecondition: error banner showing1. Rotate device
2. Return to original orientation
Error banner still visible, same message, retry still functionalP1REQ-UX-09
ISN-010Server returns duplicate items; UI deduplicatesMock API returns page 2 with same IDs as page 11. Trigger load
2. Check list
No duplicate IDs appear; either duplicates are filtered out or a warning is loggedP1REQ-DATA-01

These ten negative cases ensure resilience against flaky networks, bad payloads, and edge‑case server behaviors. Prioritize those that could lead to data loss or crashes (P0) and those that affect user trust (P1).

Edge and Boundary Conditions

Edge cases push the component to its limits: very large lists, extremely fast/slow scroll, memory pressure, and unusual input devices. They often surface only in production after prolonged use.

IDTitlePreconditionsStepsExpected ResultPriorityTraceability
ISE-001Very first scroll (list empty) triggers load if threshold metPrecondition: list rendered with zero items, placeholder shows “Loading…”1. Scroll down immediately (even 10 px)Request for page 1 fires, placeholder replaced with real itemsP0REQ-INF-05
ISE-002Scrolling past the bottom when hasMore:false shows no spinnerPrecondition: end‑of‑list reached1. Attempt to fling further down
2. Observe UI
No spinner, no request, “End of list” stays visibleP1REQ-UX-10
ISE-003List with item heights exceeding viewport (e.g., full‑screen cards) still triggers correctlyPrecondition: each item = 100 vh1. Scroll until one card fully visible
2. Continue slight scroll
Load triggers when the last card’s bottom nears threshold, no missed triggersP1REQ-UX-11
ISE-004Rapid orientation changes during pending load do not cause duplicate requestsPrecondition: network latency 800 ms for page 31. Trigger load
2. Rotate landscape → portrait → landscape quickly
3. Wait for response
Only one request for page 3 is made, UI updates onceP1REQ-PERF-04
ISE-005Low memory device: app does not OOM after scrolling 200 pagesPrecondition: emulator with 512 MB RAM, each item ~10 KB1. Scroll continuously for 5 minutes
2. Monitor memory
Memory growth plateaus (due to view recycling), no crashP0REQ-RES-01
ISE-006Scrolling with a connected mouse wheel on web triggers loadsPrecondition: desktop Chrome, focus on list1. Rotate mouse wheel downwards until threshold
2. Observe network
Request fired same as touchP1REQ-ACC-04
ISE-007Touch start outside list (e.g., on header) still propagates to scroll listenerPrecondition: fixed header above list1. Place finger on header, drag down into list area
2. Continue to threshold
Load triggers as if started inside listP1REQ-UX-12
ISE-008Programmatic scroll (e.g., scrollTo) triggers load if it crosses thresholdPrecondition: list at top1. Execute window.scrollTo(0, document.body.height - 300)
2. Observe
Load fires, consistent with user‑initiated scrollP1REQ-API-01
ISE-009Scrolling while a modal dialog is open does not trigger background loadsPrecondition: modal overlay covering list1. Open modal
2. Attempt to scroll behind it (gesture blocked)
3. Close modal
4. Scroll to threshold
No request while modal open; after dismiss, normal behavior resumesP1REQ-MODAL-01
ISE-010List with sticky header/footer maintains correct threshold calculationPrecondition: 56 px header, 44 px footer1. Scroll until last item is within threshold of viewport (excluding footer)
2. Observe
Load fires at correct visual point, not obscured by fixed elementsP1REQ-LAYOUT-02

These ten edge cases address scenarios that are easy to overlook but can cause silent failures, excessive battery drain, or crashes in the wild. Mark those that could lead to OOM or infinite loops as P0.

Performance and Load Considerations

Performance testing for infinite scroll goes beyond measuring a single request; it looks at frame rate, jank, memory, and network utilization over extended sessions. Use profiling tools (Android Studio Profiler, Chrome DevTools, Instruments) alongside automated scripts.

Performance Test Matrix

IDTitlePreconditionsStepsMetricsAcceptance ThresholdPriority
ISP-001Average frame time stays under 16 ms during scroll with loadingDevice Pixel 4, API 33, 60 fps target1. Record timeline while scrolling continuously for 30 s
2. Capture frame timestamps
95 % of frames ≤ 16 ms≤ 2 % jank framesP0
ISP-002Memory growth per 100 items loaded stays below 2 MBAndroid emulator 2 GB RAM1. Load 20 pages (≈4000 items)
2. Take heap snapshot before/after
Delta ≤ 2 MB≤ 2 MBP0
ISP-003Network utilization does not exceed 50 % of available bandwidth during idle scrollWi‑Fi 20 Mbps1. Throttle to 5 Mbps
2. Scroll slowly (no new loads)
3. Monitor TX/RX
Idle traffic ≤ 250 kbps≤ 500 kbpsP1
ISP-004Time from scroll threshold to first visible new item (TTI) < 300 ms on 3GNetwork throttled to 1.6 Mbps downlink, 400 ms RTT1. Trigger load
2. Measure from scroll event to DOM insertion of first new item
TTI ≤ 300 ms≤ 300 msP1
ISP-005Battery drain per hour of continuous scrolling < 2 % on mid‑tier deviceNexus 5X, 3000 mAh battery1. Scroll continuously for 1 h
2. Measure battery delta
≤ 2 %≤ 2 %P2
ISP-006CPU usage during placeholder shimmer animation < 15 %Same device as ISP-0011. Enable shimmer
2. Scroll idle (no loads)
3. Sample CPU
≤ 15 % average≤ 15 %P2
ISP-007Scrolling with accessibility features enabled (large text, high contrast) does not increase TTI > 50 %Font scale 200 %, contrast enabled1. Repeat ISP-004 with accessibility on
2. Compare TTI
ΔTTI ≤ 150 ms≤ 150 msP1
ISP-008Concurrent infinite scroll instances (e.g., two tabs) do not interfereWeb app with two independent feeds1. Open two tabs, each with scroll
2. Scroll both alternately
3. Verify each loads correct page
No cross‑talk, each maintains its own offsetNo cross‑talkP1
ISP-009Long session (4 h) does not cause leak in scroll listener registrationAutomated script1. Run scroll loop for 4 h
2. Check that only one scroll listener remains active
Listener count = 1No listener leakP0
ISP-010Low‑end device (Snapdragon 450) maintains ≥ 30 fps during scroll with image loadingLow‑end Android phone1. Scroll with image‑heavy items (300 KB each)
2. Capture FPS
Average FPS ≥ 30≥ 30 fpsP0

These ten performance cases give you a quantitative baseline. Automate them using a test runner that can capture metrics (e.g., playwright trace, adb shell dumpsys gfxinfo, or ios, or Lighthouse CI). Record results in a dashboard to detect regressions early.

Prioritization and Traceability to Requirements

A test suite must align with business value. Map each test case to a requirement identifier and assign a priority based on risk, user impact, and failure cost.

Requirement Traceability Table

Requirement IDDescriptionLinked Test Cases (ID)Priority Derivation
REQ-INF-01Load next page when user approaches bottomIS-001, IS-002, IS-003, IS-007, IS-008, IS-009, IS-010, IS-011, IS-012P0 – core functionality
REQ-INF-02Prevent duplicate requests during rapid scrollIS-002, IS-008, ISN-006P0 – avoids wasted bandwidth
REQ-INF-03Show loading indicator while fetchingIS-004, IS-005, ISN-001, ISN-002P1 – UX feedback
REQ-INF-04Display end‑of‑list message when no more dataIS-006, ISE-002P0 – clear termination
REQ-ERR-01Gracefully handle network timeoutsISN-001, ISN-005P0 – prevents broken UI
REQ-ERR-02Handle HTTP error codes without crashISN-002, ISN-006P0 – stability
REQ-ERR-03Recover from malformed payloadsISN-003, ISN-004P1 – data integrity
REQ-UX-05Spinner hides on success/errorIS-004, ISN-001, ISN-002P1 – visual consistency
REQ-UX-06No layout jump when placeholders replaceIS-005, ISE-003P1 – visual stability
REQ-ACC-01Keyboard navigation triggers loadsIS-009P1 – accessibility
REQ-ACC-02Screen reader announces new itemsIS-010, ISN-008P1 –IS-010, ISN-008P1 – accessibility
REQ-ACC-04Mouse wheel worksISE-006P1 – accessibility
REQ-PERF-01No reload of already‑fetched items on scroll upIS-007P1 – efficiency
REQ-PERF-02Jank < 2 % during scrollISP-001, ISP-004, ISP-007P0 – perceived performance
REQ-PERF-03Memory boundedISP-002, ISE-005P0 – resource safety
REQ-RES-01No OOM after long sessionISE-005, ISP-009P0 – stability
REQ-MODAL-01Modal blocks background scrollISE-009P1 – interaction correctness
REQ-LAYOUT-02Sticky header/footer considered in thresholdISE-010P1 – layout correctness

When you maintain this table, you can generate a coverage report (e.g., using pytest markers or JUnit tags) that shows what percentage of requirements are exercised by your automated suite. Aim for ≥ 90 % requirement coverage before marking a feature as “ready for release.”

Combining Manual Test Cases with Autonomous Exploration (SUSA)

Manual test cases give you deterministic verification of known scenarios. Autonomous exploration complements them by exercising the app in ways a human might not think of, uncovering hidden interaction paths, and validating that the infinite‑scroll component behaves correctly under varied user personas.

How SUSA Works with Infinite Scroll

SUSA (SUSATest) explores an uploaded APK or a web URL by generating realistic interaction sequences: taps, scrolls, text entry, handling dialogs, and navigating back/up. It does this for multiple persona profiles (curious, impatient, novice, adversarial, elderly, accessibility, power user, etc.). Each persona has its own timing, scroll velocity, and tolerance for errors, which means the same infinite‑scroll list is exercised under a wide range of conditions without writing a single line of test script.

When you point SUSA at a screen that contains an infinite‑scroll list, the platform will:

  1. Detect scrollable containers using accessibility heuristics.
  2. Generate scroll gestures that vary in distance, speed, and frequency according to the active persona.
  3. Monitor network requests and UI changes, flagging any deviations from expected behavior (e.g., missing spinner, duplicate request, crash).
  4. Record the full interaction trace, allowing you to replay a failing session manually or convert it into an automated script (Appium for Android, Playwright for Web).

Because SUSA learns from each run, it avoids re‑exploring dead ends (e.g., a scroll that never triggers a load because the threshold is mis‑configured) and focuses on novel paths in subsequent executions.

Integrating SUSA Results into Your Test Matrix

Take the outcomes of an SUSA run and map them to your existing test‑case IDs:

SUSA ObservationCorresponding Test Case IDAction
Spinner never appears when scrolling fast with “impatient” personaIS-004, ISN-001Add a negative case for high‑velocity scroll with simulated latency
Duplicate network request observed when “power user” performs two‑finger scroll then liftIS-008Refine duplicate‑request guard logic
Screen reader fails to announce new items for “elderly” persona with large fontIS-010, ISN-008Verify ARIA live region updates on dynamic insertion
App crashes after 150 rapid scrolls with “adversarial” persona (random taps)ISE-005, ISP-009Stress‑test memory and listener leaks
End‑of‑list banner not shown when backend returns empty array with hasMore:true for “novice” personaISN-004, ISE-002Clarify handling of empty pages

By converting SUSA findings into additional test cases (or updating existing ones), you close gaps that manual design alone might miss. Moreover, you can automate the replay of a failing SUSA session as a regression test, ensuring the same fault does not reappear.

Example: Running SUSA on a Web Infinite‑Scroll Feed


# Install the SUSA agent (once)
pip install susatest-agent

# Point SUSA at your staging URL, request a 10‑minute exploration,
# and ask for an Appium/Playwright script export on failure.
susatest explore \
    --url https://staging.example.com/feed \
    --personas curious impatient novice elderly accessibility power user \
    --duration 10m \
    --output-dir ./susa-output \
    --on-failure export-playwright \
    --export-path ./tests/susa-failed.spec.js

The command above will:

Limit SUSA usage to at most two sections in this article (this section and the checklist that follows) to stay within the guideline.

Checklist for Infinite Scroll Test Suites

Use this concise checklist before marking a story as done. Tick each item only after you have evidence (manual test pass, automated test pass, or SUSA finding) that satisfies it.

Test Your App Autonomously

Upload your APK or URL. SUSA explores like 10 real users — finds bugs, accessibility violations, and security issues. No scripts.

Try SUSA Free