Files
portal/src/routes/(protected)/(user)/proclamations/page.server.spec.ts
T
NeilClack 93d941569e proclamation-categories: sub-category management inline in parent form
- Registry: Remove 'parent.name' from listFields (all shown records
  are top-level with no parent), remove 'parent: true' from include
  since unused
- +page.server.ts: Custom load filters to parentId=null (top-level
  only); custom upsert syncs children (create/update/delete) and
  handles P2002 duplicate-name errors; custom delete cascades to
  children first to avoid FK constraint violations
- CategoryForm.svelte: Replace parentId select dropdown with dynamic
  list of sub-category inputs. Each row has a name field and Remove
  button. Pre-populates from record.children when editing existing
  categories. Add Sub-category button appends new rows
- +page.svelte: Remove unused relationOptionsData prop from
  CategoryForm; rename submit button label from 'Update' to 'Save'
- prisma: Add ProclamationCategorySubscriptionLevel join table
  migration and regenerate client
- General: Update TipTap mock, Toast, license-keys page, proclamations
  server/route tests, README, AGENTS.md, and other admin forms
2026-07-08 10:31:28 -05:00

123 lines
3.6 KiB
TypeScript

import { describe, it, expect, vi, beforeEach } from 'vitest';
import { mockProclamation, mockCategory, createUrl } from '$lib/test-utils';
vi.mock('$lib/db', () => ({
prisma: {
proclamation: { findMany: vi.fn() },
proclamationCategory: { findMany: vi.fn() }
}
}));
import { prisma } from '$lib/db';
import { load } from './+page.server';
const proclamationFindMany = prisma.proclamation.findMany as ReturnType<typeof vi.fn>;
const categoryFindMany = prisma.proclamationCategory.findMany as ReturnType<typeof vi.fn>;
describe('(protected)/admin/proclamations page server load', () => {
beforeEach(() => {
proclamationFindMany.mockReset();
categoryFindMany.mockReset();
});
it('returns proclamations and categories with no filters', async () => {
const proclamations = [mockProclamation()];
const categories = [mockCategory()];
proclamationFindMany.mockResolvedValue(proclamations);
categoryFindMany.mockResolvedValue(categories);
const url = createUrl('/admin/proclamations');
const result = (await load({ url } as any)) as any;
expect(result.proclamations).toEqual(proclamations);
expect(result.categories[0]).toEqual(
expect.objectContaining({
...categories[0],
displayName: categories[0].name
})
);
expect(result.search).toBe('');
expect(result.categoryId).toBeNull();
});
it('passes search filter to findMany when search param is present', async () => {
proclamationFindMany.mockResolvedValue([]);
categoryFindMany.mockResolvedValue([]);
const url = createUrl('/admin/proclamations', { search: 'healing' });
await load({ url } as any);
expect(proclamationFindMany).toHaveBeenCalledWith(
expect.objectContaining({
where: { name: { contains: 'healing', mode: 'insensitive' } }
})
);
});
it('returns search string from URL params', async () => {
proclamationFindMany.mockResolvedValue([]);
categoryFindMany.mockResolvedValue([]);
const url = createUrl('/admin/proclamations', { search: 'peace' });
const result = (await load({ url } as any)) as any;
expect(result.search).toBe('peace');
});
it('passes categoryId filter when category param is present', async () => {
proclamationFindMany.mockResolvedValue([]);
categoryFindMany.mockResolvedValue([]);
const url = createUrl('/admin/proclamations', { category: '3' });
await load({ url } as any);
expect(proclamationFindMany).toHaveBeenCalledWith(
expect.objectContaining({
where: { categoryId: 3 }
})
);
});
it('returns parsed categoryId from URL params', async () => {
proclamationFindMany.mockResolvedValue([]);
categoryFindMany.mockResolvedValue([]);
const url = createUrl('/admin/proclamations', { category: '5' });
const result = (await load({ url } as any)) as any;
expect(result.categoryId).toBe(5);
});
it('combines search and category filters', async () => {
proclamationFindMany.mockResolvedValue([]);
categoryFindMany.mockResolvedValue([]);
const url = createUrl('/admin/proclamations', { search: 'love', category: '2' });
await load({ url } as any);
expect(proclamationFindMany).toHaveBeenCalledWith(
expect.objectContaining({
where: {
name: { contains: 'love', mode: 'insensitive' },
categoryId: 2
}
})
);
});
it('includes solfeggioFrequency and category relations', async () => {
proclamationFindMany.mockResolvedValue([]);
categoryFindMany.mockResolvedValue([]);
const url = createUrl('/admin/proclamations');
await load({ url } as any);
expect(proclamationFindMany).toHaveBeenCalledWith(
expect.objectContaining({
include: {
solfeggioFrequency: true,
category: { include: { parent: true } },
subscriptionLevel: true
}
})
);
});
});