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
@@ -27,12 +27,16 @@ vi.mock("next/navigation", () => ({
|
||||
throw Error(`redirect ${url}`);
|
||||
},
|
||||
}));
|
||||
vi.mock("@/lib/db", async () => ({
|
||||
...(await import("@/db/schema")),
|
||||
db: {
|
||||
vi.mock("@/lib/db", async () => {
|
||||
const database = {
|
||||
select: () => ({
|
||||
from: () => ({
|
||||
where: () => ({ limit: async () => state.rows.shift() ?? [] }),
|
||||
where: () => ({
|
||||
limit: () => {
|
||||
const result = Promise.resolve(state.rows.shift() ?? []);
|
||||
return Object.assign(result, { for: () => result });
|
||||
},
|
||||
}),
|
||||
}),
|
||||
}),
|
||||
insert: () => ({ values: state.insert }),
|
||||
@@ -42,9 +46,13 @@ vi.mock("@/lib/db", async () => ({
|
||||
return { where: async () => [{ affectedRows: 1 }] };
|
||||
},
|
||||
}),
|
||||
},
|
||||
}));
|
||||
transaction: async (fn: (tx: unknown) => unknown): Promise<unknown> =>
|
||||
fn(database),
|
||||
};
|
||||
return { ...(await import("@/db/schema")), db: database };
|
||||
});
|
||||
|
||||
import { articleEditToken } from "@/lib/article-edit-token";
|
||||
import { createArticle, updateArticle } from "./admin-articles";
|
||||
|
||||
function form(extra: Record<string, string> = {}) {
|
||||
@@ -89,11 +97,25 @@ describe("news saves", () => {
|
||||
expect(state.invalidate).toHaveBeenCalledOnce();
|
||||
});
|
||||
it("preserves the slug and clears old scheduling for immediate publication", async () => {
|
||||
state.rows = [[{ slug: "test-news", status: "draft", publishedAt: null }]];
|
||||
const existing = {
|
||||
title: "Old",
|
||||
slug: "test-news",
|
||||
image: "",
|
||||
shortStory: "",
|
||||
fullStory: "",
|
||||
status: "draft",
|
||||
publishAt: null,
|
||||
publishedAt: null,
|
||||
};
|
||||
state.rows = [[existing]];
|
||||
expect(
|
||||
(
|
||||
await updateArticle(
|
||||
form({ id: "1", publishAt: "2099-01-01T00:00:00Z" }),
|
||||
form({
|
||||
id: "1",
|
||||
baseToken: articleEditToken(existing),
|
||||
publishAt: "2099-01-01T00:00:00Z",
|
||||
}),
|
||||
)
|
||||
).ok,
|
||||
).toBe(true);
|
||||
@@ -106,6 +128,27 @@ describe("news saves", () => {
|
||||
);
|
||||
expect(state.invalidate).toHaveBeenCalledOnce();
|
||||
});
|
||||
it("rejects an outdated editor without inserting a revision or overwriting the article", async () => {
|
||||
state.rows = [
|
||||
[
|
||||
{
|
||||
title: "Changed by another editor",
|
||||
slug: "test-news",
|
||||
image: "",
|
||||
shortStory: "",
|
||||
fullStory: "",
|
||||
status: "published",
|
||||
publishAt: null,
|
||||
},
|
||||
],
|
||||
];
|
||||
expect(
|
||||
await updateArticle(form({ id: "1", baseToken: "outdated" })),
|
||||
).toEqual({ ok: false, error: "editConflict" });
|
||||
expect(state.insert).not.toHaveBeenCalled();
|
||||
expect(state.update).not.toHaveBeenCalled();
|
||||
expect(state.invalidate).not.toHaveBeenCalled();
|
||||
});
|
||||
it("rejects invalid scheduled dates before writing", async () => {
|
||||
expect(
|
||||
(await createArticle(form({ status: "scheduled", publishAt: "invalid" })))
|
||||
|
||||
Reference in new issue
Block a user