Skip to main content
Glama

LacyLights MCP Server

by bbernstein
pagination.test.ts14.2 kB
/** * Unit tests for pagination utility functions */ import { normalizePaginationParams, formatPaginationInfo, PAGINATION_DEFAULTS, } from '../../src/utils/pagination'; describe('Pagination Utils', () => { describe('normalizePaginationParams', () => { describe('with default values', () => { it('should return defaults when no parameters provided', () => { const result = normalizePaginationParams(); expect(result).toEqual({ page: 1, perPage: 50 }); }); it('should return defaults when undefined parameters provided', () => { const result = normalizePaginationParams(undefined, undefined); expect(result).toEqual({ page: 1, perPage: 50 }); }); }); describe('page parameter validation', () => { it('should accept valid page numbers', () => { expect(normalizePaginationParams(1, 50)).toEqual({ page: 1, perPage: 50, }); expect(normalizePaginationParams(5, 50)).toEqual({ page: 5, perPage: 50, }); expect(normalizePaginationParams(100, 50)).toEqual({ page: 100, perPage: 50, }); }); it('should enforce minimum page of 1', () => { expect(normalizePaginationParams(0, 50)).toEqual({ page: 1, perPage: 50, }); expect(normalizePaginationParams(-1, 50)).toEqual({ page: 1, perPage: 50, }); expect(normalizePaginationParams(-100, 50)).toEqual({ page: 1, perPage: 50, }); }); it('should handle decimal page numbers by flooring to minimum', () => { // Math.max will handle this correctly expect(normalizePaginationParams(0.5, 50)).toEqual({ page: 1, perPage: 50, }); expect(normalizePaginationParams(1.9, 50)).toEqual({ page: 1.9, perPage: 50, }); }); }); describe('perPage parameter validation', () => { it('should accept valid perPage values', () => { expect(normalizePaginationParams(1, 1)).toEqual({ page: 1, perPage: 1 }); expect(normalizePaginationParams(1, 25)).toEqual({ page: 1, perPage: 25, }); expect(normalizePaginationParams(1, 50)).toEqual({ page: 1, perPage: 50, }); expect(normalizePaginationParams(1, 100)).toEqual({ page: 1, perPage: 100, }); }); it('should enforce minimum perPage of 1', () => { // 0 is falsy, so it uses default of 50 expect(normalizePaginationParams(1, 0)).toEqual({ page: 1, perPage: 50 }); // Negative values still enforce minimum of 1 expect(normalizePaginationParams(1, -1)).toEqual({ page: 1, perPage: 1, }); expect(normalizePaginationParams(1, -100)).toEqual({ page: 1, perPage: 1, }); }); it('should enforce maximum perPage of 100', () => { expect(normalizePaginationParams(1, 101)).toEqual({ page: 1, perPage: 100, }); expect(normalizePaginationParams(1, 200)).toEqual({ page: 1, perPage: 100, }); expect(normalizePaginationParams(1, 1000)).toEqual({ page: 1, perPage: 100, }); }); it('should handle decimal perPage values', () => { expect(normalizePaginationParams(1, 25.5)).toEqual({ page: 1, perPage: 25.5, }); expect(normalizePaginationParams(1, 99.9)).toEqual({ page: 1, perPage: 99.9, }); }); }); describe('edge cases', () => { it('should handle both parameters being invalid', () => { expect(normalizePaginationParams(-5, -10)).toEqual({ page: 1, perPage: 1, }); expect(normalizePaginationParams(0, 200)).toEqual({ page: 1, perPage: 100, }); }); it('should handle very large numbers', () => { expect(normalizePaginationParams(999999, 999999)).toEqual({ page: 999999, perPage: 100, }); }); it('should handle zero for both parameters', () => { // 0 is falsy for both, so uses defaults (1 for page, 50 for perPage) expect(normalizePaginationParams(0, 0)).toEqual({ page: 1, perPage: 50, }); }); it('should use defaults when only page is provided', () => { expect(normalizePaginationParams(2)).toEqual({ page: 2, perPage: 50 }); expect(normalizePaginationParams(5)).toEqual({ page: 5, perPage: 50 }); }); it('should use defaults when only perPage is provided', () => { expect(normalizePaginationParams(undefined, 25)).toEqual({ page: 1, perPage: 25, }); }); }); }); describe('formatPaginationInfo', () => { describe('input validation', () => { it('should throw error when perPage is zero', () => { expect(() => formatPaginationInfo(100, 1, 0)).toThrow('perPage must be positive'); }); it('should throw error when perPage is negative', () => { expect(() => formatPaginationInfo(100, 1, -1)).toThrow('perPage must be positive'); expect(() => formatPaginationInfo(100, 1, -50)).toThrow('perPage must be positive'); }); }); describe('basic pagination calculations', () => { it('should calculate correct pagination for first page', () => { const result = formatPaginationInfo(100, 1, 50); expect(result).toEqual({ total: 100, page: 1, perPage: 50, totalPages: 2, hasMore: true, }); }); it('should calculate correct pagination for middle page', () => { const result = formatPaginationInfo(150, 2, 50); expect(result).toEqual({ total: 150, page: 2, perPage: 50, totalPages: 3, hasMore: true, }); }); it('should calculate correct pagination for last page', () => { const result = formatPaginationInfo(100, 2, 50); expect(result).toEqual({ total: 100, page: 2, perPage: 50, totalPages: 2, hasMore: false, }); }); it('should handle single page of results', () => { const result = formatPaginationInfo(25, 1, 50); expect(result).toEqual({ total: 25, page: 1, perPage: 50, totalPages: 1, hasMore: false, }); }); }); describe('edge cases with total items', () => { it('should handle empty result set', () => { const result = formatPaginationInfo(0, 1, 50); expect(result).toEqual({ total: 0, page: 1, perPage: 50, totalPages: 0, hasMore: false, }); }); it('should handle exactly one item', () => { const result = formatPaginationInfo(1, 1, 50); expect(result).toEqual({ total: 1, page: 1, perPage: 50, totalPages: 1, hasMore: false, }); }); it('should handle total equal to perPage', () => { const result = formatPaginationInfo(50, 1, 50); expect(result).toEqual({ total: 50, page: 1, perPage: 50, totalPages: 1, hasMore: false, }); }); it('should handle total one more than perPage', () => { const result = formatPaginationInfo(51, 1, 50); expect(result).toEqual({ total: 51, page: 1, perPage: 50, totalPages: 2, hasMore: true, }); }); }); describe('partial last page scenarios', () => { it('should handle partial last page correctly', () => { const result = formatPaginationInfo(75, 2, 50); expect(result).toEqual({ total: 75, page: 2, perPage: 50, totalPages: 2, hasMore: false, }); }); it('should calculate hasMore correctly for partial pages', () => { // 125 items with 50 per page = 3 pages // Page 1: items 1-50 (hasMore: true) expect(formatPaginationInfo(125, 1, 50)).toEqual({ total: 125, page: 1, perPage: 50, totalPages: 3, hasMore: true, }); // Page 2: items 51-100 (hasMore: true) expect(formatPaginationInfo(125, 2, 50)).toEqual({ total: 125, page: 2, perPage: 50, totalPages: 3, hasMore: true, }); // Page 3: items 101-125 (hasMore: false) expect(formatPaginationInfo(125, 3, 50)).toEqual({ total: 125, page: 3, perPage: 50, totalPages: 3, hasMore: false, }); }); }); describe('various page sizes', () => { it('should work with perPage of 1', () => { const result = formatPaginationInfo(5, 3, 1); expect(result).toEqual({ total: 5, page: 3, perPage: 1, totalPages: 5, hasMore: true, }); }); it('should work with perPage of 10', () => { const result = formatPaginationInfo(45, 2, 10); expect(result).toEqual({ total: 45, page: 2, perPage: 10, totalPages: 5, hasMore: true, }); }); it('should work with perPage of 100', () => { const result = formatPaginationInfo(250, 2, 100); expect(result).toEqual({ total: 250, page: 2, perPage: 100, totalPages: 3, hasMore: true, }); }); }); describe('large dataset scenarios', () => { it('should handle large total counts', () => { const result = formatPaginationInfo(10000, 50, 100); expect(result).toEqual({ total: 10000, page: 50, perPage: 100, totalPages: 100, hasMore: true, }); }); it('should correctly identify last page of large dataset', () => { const result = formatPaginationInfo(10000, 100, 100); expect(result).toEqual({ total: 10000, page: 100, perPage: 100, totalPages: 100, hasMore: false, }); }); it('should handle page beyond total pages', () => { // Page 200 when there are only 100 pages const result = formatPaginationInfo(10000, 200, 100); expect(result).toEqual({ total: 10000, page: 200, perPage: 100, totalPages: 100, hasMore: false, }); }); }); describe('real-world usage scenarios', () => { it('should handle typical fixtures list pagination (500 fixtures, 50 per page)', () => { // First page expect(formatPaginationInfo(500, 1, 50)).toEqual({ total: 500, page: 1, perPage: 50, totalPages: 10, hasMore: true, }); // Middle page expect(formatPaginationInfo(500, 5, 50)).toEqual({ total: 500, page: 5, perPage: 50, totalPages: 10, hasMore: true, }); // Last page expect(formatPaginationInfo(500, 10, 50)).toEqual({ total: 500, page: 10, perPage: 50, totalPages: 10, hasMore: false, }); }); it('should handle typical scenes list pagination (100 scenes, 50 per page)', () => { expect(formatPaginationInfo(100, 1, 50)).toEqual({ total: 100, page: 1, perPage: 50, totalPages: 2, hasMore: true, }); expect(formatPaginationInfo(100, 2, 50)).toEqual({ total: 100, page: 2, perPage: 50, totalPages: 2, hasMore: false, }); }); it('should handle typical cue list pagination (75 cues, 50 per page)', () => { expect(formatPaginationInfo(75, 1, 50)).toEqual({ total: 75, page: 1, perPage: 50, totalPages: 2, hasMore: true, }); expect(formatPaginationInfo(75, 2, 50)).toEqual({ total: 75, page: 2, perPage: 50, totalPages: 2, hasMore: false, }); }); }); }); describe('integration scenarios', () => { it('should work together for typical pagination flow', () => { // Normalize user input const params = normalizePaginationParams(2, 25); expect(params).toEqual({ page: 2, perPage: 25 }); // Format response with actual data const info = formatPaginationInfo(100, params.page, params.perPage); expect(info).toEqual({ total: 100, page: 2, perPage: 25, totalPages: 4, hasMore: true, }); }); it('should handle invalid input then format correctly', () => { // User provides invalid values const params = normalizePaginationParams(-5, 200); expect(params).toEqual({ page: 1, perPage: 100 }); // Format with normalized values const info = formatPaginationInfo(1000, params.page, params.perPage); expect(info).toEqual({ total: 1000, page: 1, perPage: 100, totalPages: 10, hasMore: true, }); }); it('should handle undefined input then format correctly', () => { // User provides no pagination params const params = normalizePaginationParams(); expect(params).toEqual({ page: 1, perPage: 50 }); // Format with defaults const info = formatPaginationInfo(150, params.page, params.perPage); expect(info).toEqual({ total: 150, page: 1, perPage: 50, totalPages: 3, hasMore: true, }); }); }); });

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/bbernstein/lacylights-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server