Files
immich-folio/lib/__tests__/grid-columns-clamp.test.ts

117 lines
3.7 KiB
TypeScript
Raw Permalink Normal View History

import { describe, it, expect, vi, afterEach } from 'vitest';
vi.mock('@/lib/env', () => ({
env: {
IMMICH_API_URL: 'http://localhost:2283',
IMMICH_API_KEY: 'test-key',
SITE_TITLE: 'Test Gallery',
SITE_SUBTITLE: '',
CACHE_TTL: 300,
IMMICH_TIMEOUT_MS: 15000,
RATE_LIMIT_RPM: 120,
TRUSTED_PROXY_HOPS: 0,
},
normalizeApiUrl: (raw: string) => raw.replace(/\/+$/, ''),
}));
vi.mock('@/lib/secret', () => ({
resolveAuthSecret: () => 'test-auth-secret-32-chars-long-min',
}));
vi.mock('@/lib/config/parser', () => ({
loadYaml: vi.fn(),
clearYamlCache: vi.fn(),
validateUuid: (id: string) => id,
}));
import { getConfig, invalidateConfigCache, deriveGallery } from '@/lib/config';
import { loadYaml } from '@/lib/config/parser';
import type { GalleryYaml } from '@/lib/config/schema';
const ALBUM_ID = '11111111-1111-1111-1111-111111111111';
function withSettings(settings: unknown) {
vi.mocked(loadYaml).mockImplementation((filename: string) => {
if (filename === 'gallery.yaml') return { albums: [ALBUM_ID] };
if (filename === 'settings.yaml') return settings;
return null;
});
}
afterEach(() => {
invalidateConfigCache();
vi.clearAllMocks();
});
/**
* `--grid-columns` is emitted unclamped in app/[...path]/page.tsx, so a bad
* `columns` reaches `repeat()` invalid and collapses the whole grid to one
* column with no error anywhere (#633). The cover grid already clamped
* (buildCoverGridVars); the site-wide photo grid did not.
*/
describe('site-wide grid.columns / grid.gap clamping (#633)', () => {
it('clamps a negative columns count to the minimum', () => {
withSettings({ grid: { columns: -1 } });
expect(getConfig().grid.columns).toBe(1);
});
it('clamps an out-of-range columns count to the maximum', () => {
withSettings({ grid: { columns: 99 } });
expect(getConfig().grid.columns).toBe(6);
});
it('falls back to the default when columns is not a number', () => {
withSettings({ grid: { columns: 'three' as unknown as number } });
expect(getConfig().grid.columns).toBe(1); // clamp()'s min, not silently NaN
});
it('keeps a legitimate columns value', () => {
withSettings({ grid: { columns: 4 } });
expect(getConfig().grid.columns).toBe(4);
});
it('defaults columns to 3 when unset', () => {
withSettings({});
expect(getConfig().grid.columns).toBe(3);
});
it('clamps gap the same way', () => {
withSettings({ grid: { gap: -5 } });
expect(getConfig().grid.gap).toBe(0);
withSettings({ grid: { gap: 9999 } });
invalidateConfigCache();
expect(getConfig().grid.gap).toBe(48);
});
});
/**
* Same guard for a subpage's or an album's own grid override — the merged
* value (site-wide default overridden by this) is what actually reaches
* `--grid-columns`.
*/
describe('per-subpage grid override clamping (#633)', () => {
it('clamps a negative subpage columns override', () => {
const gallery = {
subpages: [{ name: 'Trips', albums: [ALBUM_ID], grid: { columns: -1 } }],
} as unknown as GalleryYaml;
const derived = deriveGallery(gallery);
expect(derived.subpages[0].grid?.columns).toBe(1);
});
it('clamps an out-of-range subpage columns override', () => {
const gallery = {
subpages: [{ name: 'Trips', albums: [ALBUM_ID], grid: { columns: 40 } }],
} as unknown as GalleryYaml;
const derived = deriveGallery(gallery);
expect(derived.subpages[0].grid?.columns).toBe(6);
});
it('keeps a legitimate subpage columns override', () => {
const gallery = {
subpages: [{ name: 'Trips', albums: [ALBUM_ID], grid: { columns: 2 } }],
} as unknown as GalleryYaml;
const derived = deriveGallery(gallery);
expect(derived.subpages[0].grid?.columns).toBe(2);
});
});