Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 34 additions & 0 deletions apps/web/__tests__/unit/pagination-items.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { describe, expect, it } from "vitest";
import { getPaginationItems } from "@/app/(org)/dashboard/caps/components/pagination-items";
Comment on lines +1 to +2

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Test sits apart from source

The new test is in __tests__/unit, separate from the helper it tests. The repository guide requires TS/JS tests to be named *.test.ts(x) near their sources. Move it beside pagination-items.ts and update test discovery as needed, since the current configuration only includes tests under __tests__. This repository requirement must be satisfied before merging.

Context Used: AGENTS.md (source)

Prompt To Fix With AI
This is a comment left during a code review.
Path: apps/web/__tests__/unit/pagination-items.test.ts
Line: 1-2

Comment:
**Test sits apart from source**

The new test is in `__tests__/unit`, separate from the helper it tests. The repository guide requires TS/JS tests to be named `*.test.ts(x)` near their sources. Move it beside `pagination-items.ts` and update test discovery as needed, since the current configuration only includes tests under `__tests__`. This repository requirement must be satisfied before merging.

**Context Used:** AGENTS.md ([source](https://github.com/capsoftware/cap/blob/main/AGENTS.md))

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Kept it in apps/web/__tests__/unit, since that's where the other web unit tests live and what the Vitest config picks up.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're right. apps/web/vitest.config.ts only discovers tests under __tests__, and apps/web/__tests__/unit is where the web unit tests are organized. I overstated the placement requirement by suggesting the test should be colocated and that discovery needed updating. This finding isn't valid; keeping the test there is consistent with the existing setup.

Tip: You can customize Greptile's behavior for this repo with .greptile/rules.md and .greptile/config.json.


describe("getPaginationItems", () => {
it("always links the first and last pages", () => {
expect(getPaginationItems(1, 4)).toEqual([1, 2, 3, 4]);
expect(getPaginationItems(1, 10)).toEqual([1, 2, "ellipsis", 10]);
expect(getPaginationItems(10, 10)).toEqual([1, "ellipsis", 9, 10]);
});

it("shows neighbours of the current page with gaps marked once", () => {
expect(getPaginationItems(3, 4)).toEqual([1, 2, 3, 4]);
expect(getPaginationItems(5, 10)).toEqual([
1,
"ellipsis",
4,
5,
6,
"ellipsis",
10,
]);
});

it("fills a one-page gap with the page instead of an ellipsis", () => {
expect(getPaginationItems(4, 6)).toEqual([1, 2, 3, 4, 5, 6]);
});

it("handles small and out-of-range page counts", () => {
expect(getPaginationItems(1, 1)).toEqual([1]);
expect(getPaginationItems(1, 2)).toEqual([1, 2]);
expect(getPaginationItems(99, 4)).toEqual([1, "ellipsis", 4]);
expect(getPaginationItems(1, 0)).toEqual([]);
});
});
60 changes: 24 additions & 36 deletions apps/web/app/(org)/dashboard/caps/components/CapPagination.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
PaginationNext,
PaginationPrevious,
} from "@cap/ui";
import { getPaginationItems } from "./pagination-items";

interface CapPaginationProps {
currentPage: number;
Expand All @@ -21,7 +22,7 @@ export const CapPagination: React.FC<CapPaginationProps> = ({
}) => {
return (
<Pagination>
<PaginationContent>
<PaginationContent className="flex-wrap">
{currentPage > 1 && (
<PaginationItem>
<PaginationPrevious
Expand All @@ -30,46 +31,33 @@ export const CapPagination: React.FC<CapPaginationProps> = ({
/>
</PaginationItem>
)}
<PaginationItem>
<PaginationLink
className="h-10 min-w-10"
href={hrefForPage(1)}
isActive={currentPage === 1}
>
1
</PaginationLink>
</PaginationItem>
{currentPage !== 1 && (
<PaginationItem>
<PaginationLink
className="h-10 min-w-10"
href={hrefForPage(currentPage)}
isActive={true}
>
{currentPage}
</PaginationLink>
</PaginationItem>
{getPaginationItems(currentPage, totalPages).map((item, index) =>
item === "ellipsis" ? (
<PaginationEllipsis key={`ellipsis-${index}`} />
) : (
<PaginationItem key={item}>
<PaginationLink
className={
item === currentPage
? "h-10 min-w-10"
: "h-10 min-w-10 hover:bg-gray-3"
}
href={hrefForPage(item)}
isActive={item === currentPage}
>
{item}
</PaginationLink>
</PaginationItem>
),
)}
{totalPages > currentPage + 1 && (
{currentPage < totalPages && (
<PaginationItem>
<PaginationLink
className="h-10 min-w-10 hover:bg-gray-3"
<PaginationNext
className="h-10 bg-transparent hover:bg-gray-4"
href={hrefForPage(currentPage + 1)}
isActive={false}
>
{currentPage + 1}
</PaginationLink>
/>
</PaginationItem>
)}
{currentPage > 2 && <PaginationEllipsis />}
<PaginationItem>
<PaginationNext
className="h-10 bg-transparent hover:bg-gray-4"
href={hrefForPage(
currentPage === totalPages ? currentPage : currentPage + 1,
)}
/>
</PaginationItem>
</PaginationContent>
</Pagination>
);
Expand Down
22 changes: 22 additions & 0 deletions apps/web/app/(org)/dashboard/caps/components/pagination-items.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
export type PaginationItemValue = number | "ellipsis";

export function getPaginationItems(
currentPage: number,
totalPages: number,
): PaginationItemValue[] {
const pages = [
...new Set([1, currentPage - 1, currentPage, currentPage + 1, totalPages]),
]
.filter((page) => page >= 1 && page <= totalPages)
.sort((a, b) => a - b);

const items: PaginationItemValue[] = [];
let previous = 0;
for (const page of pages) {
if (page - previous === 2) items.push(previous + 1);
else if (page - previous > 2) items.push("ellipsis");
items.push(page);
previous = page;
}
return items;
}