assessment-model/src/app/lib/portfolioUserConfig.test.ts
Khalim Conn-Kowlessar 633c127620 feat(home): per-user portfolio config planning layer + /api/me routes
TDD'd pure planning core (planFolderReorder with payload validation,
groupPortfoliosForHome with starred float + recency, planFolderDeletion
encoding unfile-then-delete, buildStarChange owning starred_at-as-flag),
applied by thin route handlers: folder create/rename/delete/reorder,
per-portfolio config upsert, and the grouped home read.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-07 15:12:07 +00:00

114 lines
3.3 KiB
TypeScript

import { describe, expect, it } from "vitest";
import {
buildStarChange,
groupPortfoliosForHome,
planFolderDeletion,
planFolderReorder,
} from "./portfolioUserConfig";
describe("planFolderReorder", () => {
it("renumbers every folder to its index in the requested order", () => {
const plan = planFolderReorder({
currentIds: [1n, 2n, 3n],
orderedIds: [3n, 1n, 2n],
});
expect(plan).toEqual({
updates: [
{ id: 3n, position: 0 },
{ id: 1n, position: 1 },
{ id: 2n, position: 2 },
],
});
});
it("rejects an order naming a folder the user does not have", () => {
const plan = planFolderReorder({
currentIds: [1n, 2n],
orderedIds: [2n, 99n],
});
expect(plan).toEqual({
error: "Folder order does not match your folders",
});
});
it("rejects an order that lists the same folder twice", () => {
const plan = planFolderReorder({
currentIds: [1n, 2n],
orderedIds: [1n, 1n, 2n],
});
expect(plan).toEqual({
error: "Folder order does not match your folders",
});
});
});
describe("groupPortfoliosForHome", () => {
it("groups portfolios into folders ordered by position, with the rest unfiled", () => {
const grouped = groupPortfoliosForHome({
portfolios: [{ id: 1n }, { id: 2n }, { id: 3n }],
configs: [
{ portfolioId: 1n, folderId: 10n, starredAt: null },
{ portfolioId: 2n, folderId: 11n, starredAt: null },
],
folders: [
{ id: 10n, name: "SHDF Wave 3", position: 1 },
{ id: 11n, name: "Demos", position: 0 },
],
});
expect(grouped.folders).toEqual([
{ id: 11n, name: "Demos", portfolios: [{ id: 2n }] },
{ id: 10n, name: "SHDF Wave 3", portfolios: [{ id: 1n }] },
]);
expect(grouped.unfiled).toEqual([{ id: 3n }]);
});
it("floats starred portfolios to the top of their group and lists them most-recently-starred first", () => {
const grouped = groupPortfoliosForHome({
portfolios: [{ id: 1n }, { id: 2n }, { id: 3n }, { id: 4n }],
configs: [
{ portfolioId: 1n, folderId: 10n, starredAt: null },
{ portfolioId: 2n, folderId: 10n, starredAt: new Date("2026-07-01") },
{ portfolioId: 4n, folderId: null, starredAt: new Date("2026-07-05") },
],
folders: [{ id: 10n, name: "SHDF Wave 3", position: 0 }],
});
expect(grouped.folders[0].portfolios).toEqual([{ id: 2n }, { id: 1n }]);
expect(grouped.unfiled).toEqual([{ id: 4n }, { id: 3n }]);
expect(grouped.starred).toEqual([{ id: 4n }, { id: 2n }]);
});
});
describe("planFolderDeletion", () => {
it("unfiles exactly the configs in the folder, then deletes the folder", () => {
const plan = planFolderDeletion({
folderId: 10n,
configs: [
{ id: 1n, folderId: 10n },
{ id: 2n, folderId: 11n },
{ id: 3n, folderId: 10n },
{ id: 4n, folderId: null },
],
});
expect(plan).toEqual({
unfileConfigIds: [1n, 3n],
deleteFolderId: 10n,
});
});
});
describe("buildStarChange", () => {
it("starring stamps the moment, unstarring clears it", () => {
const now = new Date("2026-07-07T12:00:00Z");
expect(buildStarChange({ starred: true, now })).toEqual({ starredAt: now });
expect(buildStarChange({ starred: false, now })).toEqual({
starredAt: null,
});
});
});