Pagination
MailSlurp API endpoints use pagination to return lists of entities. Pagination is the process of splitting a large list of entities into smaller pages. This allows you to retrieve entities in batches and is useful for performance and usability. This post will demonstrate how to iterate over paginated results and fetch all entities.
Key points
- MailSlurp endpoints return paginated results
- Page index is zero based (0 = first page)
- Some endpoints return negative totals (this means the total is too large to count quickly)
- You accumulate all entities by looping over pages until
page.empty
orpage.last
is true
Use a timeout or sleep in any loop method to avoid rate-limiting
Counting entities
To get the total number of emails for an inbox you can do the following:
// if you need the count
const count = await inboxController.getInboxEmailCount({
inboxId: inbox.id
});
expect(count.totalElements).toBeGreaterThan(0);
These methods are also available for other endpoints and provide an accurate entity count.
Do not rely on the pagination result for counting entities. The pagination result may not be accurate if the entity count is large. Use the count methods instead.
Basics
When you are fetching a list of emails or inboxes you will receive a paginated response. The response will contain a list of entities and some pagination metadata.
const page = await emailController.getEmailsOffsetPaginated({
inboxId: [inbox.id],
page: undefined, // 0 based page index here
size: undefined // page size here
});
// properties of a page
const {
content, // the emails in this page
numberOfElements, // the number of elements in the result
empty, // is the page empty?
last, // is the page the last one?
pageable // the pagination object for paging through results
} = page;
// properties of the returned pagination
const {
pageSize, // the page size
pageNumber // the 0 based page number
} = page.pageable;
Negative totals
For some endpoints the total may be negative. This is because the total is too large to quickly count. In this case you can use the count
methods to get an accurate count.
const pagination = await emailController.getEmailsOffsetPaginated({
inboxId: [inbox.id]
});
// the total is -1, indicating that the total count is not available
expect(pagination.totalElements).toEqual(-1);
expect(pagination.totalPages).toEqual(-1);
Fetching all entities
To paginate through all entities use the following technique:
// fetch emails using offset pagination
let finished = false;
let emails = [];
let pageIndex = 0;
const pageSize = 10;
do {
// fetch next page
const page = await emailController.getEmailsOffsetPaginated({
page: pageIndex,
size: pageSize,
inboxId: [inbox.id]
});
// add to list of emails
emails.push(...page.content);
// increment page index
pageIndex++;
// add a sleep to the loop to prevent rate limiting
await sleep(100);
// mark loop finished if page is empty or on last page
if (page.empty || page.last) {
finished = true;
}
} while (!finished);
How stepping works
In this demonstrate we can step through pages using a custom page size:
// given an inbox with 7 emails
const count = await inboxController.getInboxEmailCount({
inboxId: inbox.id
});
expect(count.totalElements).toEqual(7);
// paginate to demonstrate paging
const page1 = await emailController.getEmailsOffsetPaginated({
page: 0, // 0-based index, 0 means first page
size: 3,
inboxId: [inbox.id]
});
// content and number of elements matching the page size
expect(page1.numberOfElements).toEqual(3);
expect(page1.content?.length).toEqual(3);
// is not last or empty
expect(page1.last).toEqual(false);
expect(page1.empty).toEqual(false);
// can page again to page 2
const page2 = await emailController.getEmailsOffsetPaginated({
page: 1,
size: 3,
inboxId: [inbox.id]
});
// expect 3 inboxes again
expect(page2.numberOfElements).toEqual(3);
expect(page2.content?.length).toEqual(3);
// is not last or empty again
expect(page2.last).toEqual(false);
expect(page2.empty).toEqual(false);
// now get the last page
const page3 = await emailController.getEmailsOffsetPaginated({
page: 2,
size: 3,
inboxId: [inbox.id]
});
// expect final inbox (7 - 3 - 3 = 1)
expect(page3.numberOfElements).toEqual(1);
expect(page3.content?.length).toEqual(1);
// is the last page (and not empty)
expect(page3.last).toEqual(true);
expect(page3.empty).toEqual(false);