feat(cms): improve catalog, editorial recovery and operations
This commit is contained in:
1 parent
2fead134e6
commit
c389c3893d
122 files changed
+8137
-703
No files matched your search
@@ -0,0 +1,83 @@
|
||||
import { beforeEach, expect, it, vi } from "vitest";
|
||||
|
||||
const state = vi.hoisted(() => ({
|
||||
version: 0,
|
||||
update: vi.fn(),
|
||||
insert: vi.fn(),
|
||||
permission: vi.fn(),
|
||||
}));
|
||||
vi.mock("@/lib/admin/guard", () => ({ requirePermission: state.permission }));
|
||||
vi.mock("@/lib/permissions", () => ({ PERMS: { NEWS_EDIT: "news.edit" } }));
|
||||
vi.mock("@/lib/db", async () => {
|
||||
const tx = {
|
||||
insert: (table: unknown) => ({
|
||||
values: (value: unknown) => {
|
||||
state.insert(table, value);
|
||||
return { onDuplicateKeyUpdate: async () => {} };
|
||||
},
|
||||
}),
|
||||
select: () => ({
|
||||
from: () => ({
|
||||
where: () => ({ for: async () => [{ version: state.version }] }),
|
||||
}),
|
||||
}),
|
||||
update: (table: unknown) => ({
|
||||
set: (value: unknown) => {
|
||||
state.update(table, value);
|
||||
return { where: async () => {} };
|
||||
},
|
||||
}),
|
||||
};
|
||||
return {
|
||||
...(await import("@/db/schema")),
|
||||
db: { transaction: async (fn: (value: typeof tx) => unknown) => fn(tx) },
|
||||
};
|
||||
});
|
||||
|
||||
import { ArticleDrafts } from "@/db/article-editor";
|
||||
import { autosaveArticle } from "./article-recovery";
|
||||
|
||||
function draft() {
|
||||
const form = new FormData();
|
||||
form.set("title", "Incomplete title");
|
||||
form.set("status", "published");
|
||||
form.set("fullStory", "Work in progress");
|
||||
return form;
|
||||
}
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks();
|
||||
state.version = 0;
|
||||
state.permission.mockResolvedValue({ id: 17 });
|
||||
});
|
||||
it("stores incomplete editor content only in a private draft table even when publication is selected", async () => {
|
||||
expect(await autosaveArticle("new", 0, draft())).toEqual({
|
||||
ok: true,
|
||||
version: 1,
|
||||
});
|
||||
expect(state.permission).toHaveBeenCalledWith("news.edit");
|
||||
expect(state.insert).toHaveBeenCalledWith(
|
||||
ArticleDrafts,
|
||||
expect.objectContaining({ userId: 17, articleKey: "new" }),
|
||||
);
|
||||
expect(state.update).toHaveBeenCalledOnce();
|
||||
expect(state.update).toHaveBeenCalledWith(
|
||||
ArticleDrafts,
|
||||
expect.objectContaining({ version: 1 }),
|
||||
);
|
||||
});
|
||||
it("does not replace a more recent draft from another tab", async () => {
|
||||
state.version = 4;
|
||||
expect(await autosaveArticle("new", 3, draft())).toEqual({ ok: false });
|
||||
expect(state.update).not.toHaveBeenCalled();
|
||||
});
|
||||
it("does not access storage when the editor permission is denied", async () => {
|
||||
state.permission.mockRejectedValue(new Error("denied"));
|
||||
await expect(autosaveArticle("new", 0, draft())).rejects.toThrow("denied");
|
||||
expect(state.insert).not.toHaveBeenCalled();
|
||||
});
|
||||
it("rejects excessive article content before writing", async () => {
|
||||
const form = draft();
|
||||
form.set("fullStory", "x".repeat(500_001));
|
||||
await expect(autosaveArticle("new", 0, form)).rejects.toThrow("draftInvalid");
|
||||
expect(state.insert).not.toHaveBeenCalled();
|
||||
});
|
||||
Reference in new issue
Block a user