Merge branch 'main' into vineeth/dev-1295

This commit is contained in:
Vineeth Voruganti 2026-01-13 11:52:50 -05:00
commit 4062ae53e6
1 changed files with 211 additions and 210 deletions

View File

@ -1,15 +1,15 @@
import { Page } from "../src/pagination";
import { Page } from '../src/pagination'
describe("Page", () => {
let mockOriginalPage: any;
let mockItems: any[];
describe('Page', () => {
let mockOriginalPage: any
let mockItems: any[]
beforeEach(() => {
mockItems = [
{ id: "item1", name: "Item 1" },
{ id: "item2", name: "Item 2" },
{ id: "item3", name: "Item 3" },
];
{ id: 'item1', name: 'Item 1' },
{ id: 'item2', name: 'Item 2' },
{ id: 'item3', name: 'Item 3' },
]
mockOriginalPage = {
items: mockItems,
@ -20,228 +20,229 @@ describe("Page", () => {
hasNextPage: () => true,
[Symbol.asyncIterator]: async function*() {
for (const item of mockItems) {
yield item;
yield item
}
},
} as any;
});
} as any
})
describe("constructor", () => {
it("should initialize with original page", () => {
const page = new Page(mockOriginalPage);
describe('constructor', () => {
it('should initialize with original page', () => {
const page = new Page(mockOriginalPage)
expect(page["_originalPage"]).toBe(mockOriginalPage);
expect(page["_transformFunc"]).toBeUndefined();
});
expect(page['_originalPage']).toBe(mockOriginalPage)
expect(page['_transformFunc']).toBeUndefined()
})
it("should initialize with transform function", () => {
const transformFunc = (item: any) => ({ ...item, transformed: true });
const page = new Page(mockOriginalPage, transformFunc);
it('should initialize with transform function', () => {
const transformFunc = (item: any) => ({ ...item, transformed: true })
const page = new Page(mockOriginalPage, transformFunc)
expect(page["_originalPage"]).toBe(mockOriginalPage);
expect(page["_transformFunc"]).toBe(transformFunc);
});
});
expect(page['_originalPage']).toBe(mockOriginalPage)
expect(page['_transformFunc']).toBe(transformFunc)
})
})
describe("Symbol.asyncIterator", () => {
it("should iterate through items without transform", async () => {
const page = new Page(mockOriginalPage);
const items: any[] = [];
describe('Symbol.asyncIterator', () => {
it('should iterate through items without transform', async () => {
const page = new Page(mockOriginalPage)
const items: any[] = []
for await (const item of page) {
items.push(item);
items.push(item)
}
expect(items).toEqual(mockItems);
});
expect(items).toEqual(mockItems)
})
it("should iterate through items with transform", async () => {
const transformFunc = (item: any) => ({ ...item, transformed: true });
const page = new Page(mockOriginalPage, transformFunc);
const items: any[] = [];
it('should iterate through items with transform', async () => {
const transformFunc = (item: any) => ({ ...item, transformed: true })
const page = new Page(mockOriginalPage, transformFunc)
const items: any[] = []
for await (const item of page) {
items.push(item);
items.push(item)
}
expect(items).toEqual([
{ id: "item1", name: "Item 1", transformed: true },
{ id: "item2", name: "Item 2", transformed: true },
{ id: "item3", name: "Item 3", transformed: true },
]);
});
{ id: 'item1', name: 'Item 1', transformed: true },
{ id: 'item2', name: 'Item 2', transformed: true },
{ id: 'item3', name: 'Item 3', transformed: true },
])
})
it("should handle transform function that throws error", async () => {
it('should handle transform function that throws error', async () => {
const errorTransform = () => {
throw new Error("Transform error");
};
const page = new Page(mockOriginalPage, errorTransform);
throw new Error('Transform error')
}
const page = new Page(mockOriginalPage, errorTransform)
const iterate = async () => {
for await (const item of page) {
// This should throw
}
};
}
await expect(iterate()).rejects.toThrow("Transform error");
});
});
await expect(iterate()).rejects.toThrow('Transform error')
})
})
describe("get", () => {
it("should get item by index without transform", () => {
const page = new Page(mockOriginalPage);
describe('get', () => {
it('should get item by index without transform', () => {
const page = new Page(mockOriginalPage)
const item = page.get(1);
const item = page.get(1)
expect(item).toEqual(mockItems[1]);
});
expect(item).toEqual(mockItems[1])
})
it("should get item by index with transform", () => {
const transformFunc = (item: any) => ({ ...item, transformed: true });
const page = new Page(mockOriginalPage, transformFunc);
it('should get item by index with transform', () => {
const transformFunc = (item: any) => ({ ...item, transformed: true })
const page = new Page(mockOriginalPage, transformFunc)
const item = page.get(1);
const item = page.get(1)
expect(item).toEqual({ ...mockItems[1], transformed: true });
});
expect(item).toEqual({ ...mockItems[1], transformed: true })
})
it("should handle out of bounds index", () => {
const page = new Page(mockOriginalPage);
it('should handle out of bounds index', () => {
const page = new Page(mockOriginalPage)
expect(() => page.get(999)).toThrow(
"Index 999 is out of bounds for page with 3 items",
);
});
});
'Index 999 is out of bounds for page with 3 items'
)
})
})
describe("length getter", () => {
it("should return length of items array", () => {
const page = new Page(mockOriginalPage);
describe('length getter', () => {
it('should return length of items array', () => {
const page = new Page(mockOriginalPage)
expect(page.length).toBe(3);
});
expect(page.length).toBe(3)
})
it("should handle empty items array", () => {
const emptyPage = { ...mockOriginalPage, items: [] };
const page = new Page(emptyPage);
it('should handle empty items array', () => {
const emptyPage = { ...mockOriginalPage, items: [] }
const page = new Page(emptyPage)
expect(page.length).toBe(0);
});
expect(page.length).toBe(0)
})
it("should handle undefined items", () => {
const noItemsPage = { ...mockOriginalPage, items: undefined };
const page = new Page(noItemsPage);
it('should handle undefined items', () => {
const noItemsPage = { ...mockOriginalPage, items: undefined }
const page = new Page(noItemsPage)
expect(page.length).toBe(0);
});
});
expect(page.length).toBe(0)
})
})
describe("items getter", () => {
it("should return items array without transform", () => {
const page = new Page(mockOriginalPage);
describe('items getter', () => {
it('should return items array without transform', () => {
const page = new Page(mockOriginalPage)
const data = page.items;
const data = page.items
expect(data).toEqual(mockItems);
});
expect(data).toEqual(mockItems)
})
it("should return items array with transform", () => {
const transformFunc = (item: any) => ({ ...item, transformed: true });
const page = new Page(mockOriginalPage, transformFunc);
it('should return items array with transform', () => {
const transformFunc = (item: any) => ({ ...item, transformed: true })
const page = new Page(mockOriginalPage, transformFunc)
const data = page.items;
const data = page.items
expect(data).toEqual([
{ id: "item1", name: "Item 1", transformed: true },
{ id: "item2", name: "Item 2", transformed: true },
{ id: "item3", name: "Item 3", transformed: true },
]);
});
{ id: 'item1', name: 'Item 1', transformed: true },
{ id: 'item2', name: 'Item 2', transformed: true },
{ id: 'item3', name: 'Item 3', transformed: true },
])
})
it("should handle transform function returning null", () => {
const nullTransform = () => null;
const page = new Page(mockOriginalPage, nullTransform);
it('should handle transform function returning null', () => {
const nullTransform = () => null
const page = new Page(mockOriginalPage, nullTransform)
const data = page.items;
const data = page.items
expect(data).toEqual([null, null, null]);
});
});
expect(data).toEqual([null, null, null])
})
})
describe("pagination metadata getters", () => {
it("should return total from original page", () => {
const page = new Page(mockOriginalPage);
describe('pagination metadata getters', () => {
it('should return total from original page', () => {
const page = new Page(mockOriginalPage)
expect(page.total).toBe(10);
});
expect(page.total).toBe(10)
})
it("should return page number from original page", () => {
const page = new Page(mockOriginalPage);
it('should return page number from original page', () => {
const page = new Page(mockOriginalPage)
expect(page.page).toBe(1);
});
expect(page.page).toBe(1)
})
it("should return size from original page", () => {
const page = new Page(mockOriginalPage);
it('should return size from original page', () => {
const page = new Page(mockOriginalPage)
expect(page.size).toBe(3);
});
expect(page.size).toBe(3)
})
it("should return pages from original page", () => {
const page = new Page(mockOriginalPage);
it('should return pages from original page', () => {
const page = new Page(mockOriginalPage)
expect(page.pages).toBe(4);
});
expect(page.pages).toBe(4)
})
it("should handle undefined metadata", () => {
const minimalPage = { items: mockItems };
const page = new Page(minimalPage as any);
it('should handle undefined metadata', () => {
const minimalPage = { items: mockItems }
const page = new Page(minimalPage as any)
expect(page.total).toBeUndefined();
expect(page.page).toBeUndefined();
expect(page.size).toBeUndefined();
expect(page.pages).toBeUndefined();
});
});
expect(page.total).toBeUndefined()
expect(page.page).toBeUndefined()
expect(page.size).toBeUndefined()
expect(page.pages).toBeUndefined()
})
})
describe("hasNextPage getter", () => {
it("should return true when hasNextPage is true", () => {
const page = new Page(mockOriginalPage);
describe('hasNextPage getter', () => {
it('should return true when hasNextPage is true', () => {
const page = new Page(mockOriginalPage)
expect(page.hasNextPage).toBe(true);
});
expect(page.hasNextPage).toBe(true)
})
it("should return false when hasNextPage function returns false", () => {
const lastPage = { ...mockOriginalPage, hasNextPage: () => false };
const page = new Page(lastPage);
it('should return false when hasNextPage function returns false', () => {
const lastPage = { ...mockOriginalPage, hasNextPage: () => false }
expect(page.hasNextPage).toBe(false);
});
const page = new Page(lastPage)
it("should call hasNextPage function if it is a function", () => {
const hasNextPageFn = jest.fn(() => true);
const pageWithFn = { ...mockOriginalPage, hasNextPage: hasNextPageFn };
const page = new Page(pageWithFn);
expect(page.hasNextPage).toBe(false)
})
const result = page.hasNextPage;
it('should call hasNextPage function if it is a function', () => {
const hasNextPageFn = jest.fn(() => true)
const pageWithFn = { ...mockOriginalPage, hasNextPage: hasNextPageFn }
const page = new Page(pageWithFn)
expect(result).toBe(true);
expect(hasNextPageFn).toHaveBeenCalled();
});
const result = page.hasNextPage
it("should return false when hasNextPage is undefined", () => {
const noNextPage = { ...mockOriginalPage };
delete noNextPage.hasNextPage;
const page = new Page(noNextPage);
expect(result).toBe(true)
expect(hasNextPageFn).toHaveBeenCalled()
})
expect(page.hasNextPage).toBe(false);
});
});
it('should return false when hasNextPage is undefined', () => {
const noNextPage = { ...mockOriginalPage }
delete noNextPage.hasNextPage
const page = new Page(noNextPage)
describe("getNextPage", () => {
it("should return next page with same transform function", async () => {
expect(page.hasNextPage).toBe(false)
})
})
describe('getNextPage', () => {
it('should return next page with same transform function', async () => {
const nextPageData = {
items: [{ id: "item4", name: "Item 4" }],
items: [{ id: 'item4', name: 'Item 4' }],
size: 1,
total: 10,
page: 2,
@ -249,82 +250,82 @@ describe("Page", () => {
hasNextPage: () => false,
[Symbol.asyncIterator]: async function*() {
for (const item of this.items) {
yield item;
yield item
}
},
};
const transformFunc = (item: any) => ({ ...item, transformed: true });
mockOriginalPage.getNextPage = jest.fn().mockResolvedValue(nextPageData);
const page = new Page(mockOriginalPage, transformFunc);
}
const transformFunc = (item: any) => ({ ...item, transformed: true })
mockOriginalPage.getNextPage = jest.fn().mockResolvedValue(nextPageData)
const page = new Page(mockOriginalPage, transformFunc)
const nextPage = await page.getNextPage();
const nextPage = await page.getNextPage()
expect(nextPage).toBeInstanceOf(Page);
expect(nextPage!["_transformFunc"]).toBe(transformFunc);
expect(mockOriginalPage.getNextPage).toHaveBeenCalled();
});
expect(nextPage).toBeInstanceOf(Page)
expect(nextPage!['_transformFunc']).toBe(transformFunc)
expect(mockOriginalPage.getNextPage).toHaveBeenCalled()
})
it("should return null when no next page", async () => {
mockOriginalPage.getNextPage = jest.fn().mockResolvedValue(null);
const page = new Page(mockOriginalPage);
it('should return null when no next page', async () => {
mockOriginalPage.getNextPage = jest.fn().mockResolvedValue(null)
const page = new Page(mockOriginalPage)
const nextPage = await page.getNextPage();
const nextPage = await page.getNextPage()
expect(nextPage).toBeNull();
});
expect(nextPage).toBeNull()
})
it("should return null when getNextPage returns undefined", async () => {
mockOriginalPage.getNextPage = jest.fn().mockResolvedValue(undefined);
const page = new Page(mockOriginalPage);
it('should return null when getNextPage returns undefined', async () => {
mockOriginalPage.getNextPage = jest.fn().mockResolvedValue(undefined)
const page = new Page(mockOriginalPage)
const nextPage = await page.getNextPage();
const nextPage = await page.getNextPage()
expect(nextPage).toBeNull();
});
expect(nextPage).toBeNull()
})
it("should return null when getNextPage method does not exist", async () => {
const pageWithoutNext = { ...mockOriginalPage };
delete pageWithoutNext.getNextPage;
const page = new Page(pageWithoutNext);
it('should return null when getNextPage method does not exist', async () => {
const pageWithoutNext = { ...mockOriginalPage }
delete pageWithoutNext.getNextPage
const page = new Page(pageWithoutNext)
const nextPage = await page.getNextPage();
const nextPage = await page.getNextPage()
expect(nextPage).toBeNull();
});
expect(nextPage).toBeNull()
})
it("should propagate transform function to next page", async () => {
it('should propagate transform function to next page', async () => {
const nextPageData = {
items: [{ id: "item4", name: "Item 4" }],
items: [{ id: 'item4', name: 'Item 4' }],
[Symbol.asyncIterator]: async function*() {
for (const item of this.items) {
yield item;
yield item
}
},
};
const transformFunc = (item: any) => ({ ...item, count: 999 });
mockOriginalPage.getNextPage = jest.fn().mockResolvedValue(nextPageData);
const page = new Page(mockOriginalPage, transformFunc);
}
const transformFunc = (item: any) => ({ ...item, count: 999 })
mockOriginalPage.getNextPage = jest.fn().mockResolvedValue(nextPageData)
const page = new Page(mockOriginalPage, transformFunc)
const nextPage = await page.getNextPage();
const nextPage = await page.getNextPage()
expect(nextPage).not.toBeNull();
const transformedItem = nextPage!.get(0);
expect(nextPage).not.toBeNull()
const transformedItem = nextPage!.get(0)
expect(transformedItem).toEqual({
id: "item4",
name: "Item 4",
id: 'item4',
name: 'Item 4',
count: 999,
});
});
})
})
it("should handle error from getNextPage", async () => {
it('should handle error from getNextPage', async () => {
mockOriginalPage.getNextPage = jest
.fn()
.mockRejectedValue(new Error("Failed to get next page"));
const page = new Page(mockOriginalPage);
.mockRejectedValue(new Error('Failed to get next page'))
const page = new Page(mockOriginalPage)
await expect(page.getNextPage()).rejects.toThrow(
"Failed to get next page",
);
});
});
});
'Failed to get next page'
)
})
})
})