test(shared/primitives): cover Pagination branches
Hidden when totalPages <= 1, prev/next disabled state matrix at boundaries, link form when in range, aria-current for active page, mobile page label, left ellipsis / right ellipsis branches based on window position, custom ariaLabel. 11 tests covering ~30 of Pagination's branches. Refs #496. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
87
frontend/src/lib/shared/primitives/Pagination.svelte.test.ts
Normal file
87
frontend/src/lib/shared/primitives/Pagination.svelte.test.ts
Normal file
@@ -0,0 +1,87 @@
|
||||
import { describe, it, expect, afterEach } from 'vitest';
|
||||
import { cleanup, render } from 'vitest-browser-svelte';
|
||||
import Pagination from './Pagination.svelte';
|
||||
|
||||
afterEach(cleanup);
|
||||
|
||||
const makeHref = (p: number) => `/?page=${p}`;
|
||||
|
||||
describe('Pagination', () => {
|
||||
it('renders nothing when totalPages is 1 or less', async () => {
|
||||
render(Pagination, { props: { page: 0, totalPages: 1, makeHref } });
|
||||
|
||||
expect(document.querySelector('nav')).toBeNull();
|
||||
});
|
||||
|
||||
it('renders the nav when totalPages > 1', async () => {
|
||||
render(Pagination, { props: { page: 0, totalPages: 5, makeHref } });
|
||||
|
||||
expect(document.querySelector('nav')).not.toBeNull();
|
||||
});
|
||||
|
||||
it('disables the prev control on the first page', async () => {
|
||||
render(Pagination, { props: { page: 0, totalPages: 5, makeHref } });
|
||||
|
||||
const prev = document.querySelector('[data-testid="pagination-prev"]') as HTMLElement;
|
||||
expect(prev.tagName).toBe('SPAN');
|
||||
});
|
||||
|
||||
it('renders the prev control as a link when not on the first page', async () => {
|
||||
render(Pagination, { props: { page: 2, totalPages: 5, makeHref } });
|
||||
|
||||
const prev = document.querySelector('[data-testid="pagination-prev"]') as HTMLAnchorElement;
|
||||
expect(prev.tagName).toBe('A');
|
||||
expect(prev.href).toContain('page=1');
|
||||
});
|
||||
|
||||
it('disables the next control on the last page', async () => {
|
||||
render(Pagination, { props: { page: 4, totalPages: 5, makeHref } });
|
||||
|
||||
const next = document.querySelector('[data-testid="pagination-next"]') as HTMLElement;
|
||||
expect(next.tagName).toBe('SPAN');
|
||||
});
|
||||
|
||||
it('renders the next control as a link when not on the last page', async () => {
|
||||
render(Pagination, { props: { page: 0, totalPages: 5, makeHref } });
|
||||
|
||||
const next = document.querySelector('[data-testid="pagination-next"]') as HTMLAnchorElement;
|
||||
expect(next.tagName).toBe('A');
|
||||
expect(next.href).toContain('page=1');
|
||||
});
|
||||
|
||||
it('marks the active page button with aria-current=page', async () => {
|
||||
render(Pagination, { props: { page: 2, totalPages: 5, makeHref } });
|
||||
|
||||
const active = document.querySelector('[data-testid="pagination-page-3"]') as HTMLElement;
|
||||
expect(active.getAttribute('aria-current')).toBe('page');
|
||||
});
|
||||
|
||||
it('renders the mobile page label', async () => {
|
||||
render(Pagination, { props: { page: 1, totalPages: 5, makeHref } });
|
||||
|
||||
const label = document.querySelector('[data-testid="pagination-page-label"]');
|
||||
expect(label?.textContent).toContain('2');
|
||||
expect(label?.textContent).toContain('5');
|
||||
});
|
||||
|
||||
it('renders left ellipsis when current page is far enough from page 1', async () => {
|
||||
render(Pagination, { props: { page: 7, totalPages: 10, makeHref } });
|
||||
|
||||
expect(document.querySelector('[data-testid="pagination-ellipsis-left"]')).not.toBeNull();
|
||||
});
|
||||
|
||||
it('renders right ellipsis when current page is far from last', async () => {
|
||||
render(Pagination, { props: { page: 1, totalPages: 10, makeHref } });
|
||||
|
||||
expect(document.querySelector('[data-testid="pagination-ellipsis-right"]')).not.toBeNull();
|
||||
});
|
||||
|
||||
it('uses the supplied ariaLabel when provided', async () => {
|
||||
render(Pagination, {
|
||||
props: { page: 0, totalPages: 5, makeHref, ariaLabel: 'Custom pagination' }
|
||||
});
|
||||
|
||||
const nav = document.querySelector('nav');
|
||||
expect(nav?.getAttribute('aria-label')).toBe('Custom pagination');
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user