feat(catalog): add saved packages, preview and bulk price editing
This commit is contained in:
1 parent
867113d5d4
commit
047cd9f3dd
48 files changed
+7712
No files matched your search
@@ -0,0 +1,156 @@
|
||||
import { beforeEach, expect, it, vi } from "vitest";
|
||||
|
||||
const mocks = vi.hoisted(() => ({
|
||||
permission: vi.fn(),
|
||||
create: vi.fn(),
|
||||
save: vi.fn(),
|
||||
get: vi.fn(),
|
||||
list: vi.fn(),
|
||||
preview: vi.fn(),
|
||||
publish: vi.fn(),
|
||||
export: vi.fn(),
|
||||
audit: vi.fn(),
|
||||
hotel: vi.fn(),
|
||||
refresh: vi.fn(),
|
||||
}));
|
||||
vi.mock("@/lib/admin/guard", () => ({ requirePermission: mocks.permission }));
|
||||
vi.mock("@/lib/permissions", () => ({
|
||||
PERMS: { CATALOG_VIEW: "view", CATALOG_EDIT: "edit" },
|
||||
}));
|
||||
vi.mock("@/features/catalog/server/packages", () => ({
|
||||
createCatalogPackageCommand: mocks.create,
|
||||
saveCatalogPackageCommand: mocks.save,
|
||||
getCatalogPackageCommand: mocks.get,
|
||||
listCatalogPackagesCommand: mocks.list,
|
||||
previewCatalogPackageCommand: mocks.preview,
|
||||
publishCatalogPackageCommand: mocks.publish,
|
||||
}));
|
||||
vi.mock("@/features/catalog/server/package-messages", () => ({
|
||||
packageMessage: async (m: string) => m,
|
||||
}));
|
||||
vi.mock("@/features/catalog/server/errors", () => ({
|
||||
catalogFailure: (e: Error) => ({ message: e.message }),
|
||||
}));
|
||||
vi.mock("@/lib/services/catalog-git-queue", () => ({
|
||||
withCatalogExport: mocks.export,
|
||||
}));
|
||||
vi.mock("@/lib/services/audit", () => ({ logAudit: mocks.audit }));
|
||||
vi.mock("@/features/catalog/server/sync-status", () => ({
|
||||
sendCatalogUpdate: mocks.hotel,
|
||||
}));
|
||||
vi.mock("next/cache", () => ({ revalidatePath: mocks.refresh }));
|
||||
|
||||
import {
|
||||
createCatalogPackage,
|
||||
getCatalogPackage,
|
||||
listCatalogPackages,
|
||||
previewCatalogPackage,
|
||||
publishCatalogPackage,
|
||||
saveCatalogPackage,
|
||||
} from "./catalog-packages";
|
||||
|
||||
beforeEach(() => {
|
||||
vi.resetAllMocks();
|
||||
mocks.permission.mockResolvedValue({ id: 7 });
|
||||
mocks.export.mockImplementation((fn) => fn());
|
||||
mocks.publish.mockResolvedValue({
|
||||
pageIds: [4],
|
||||
offerCount: 1,
|
||||
alreadyPublished: false,
|
||||
});
|
||||
mocks.hotel.mockResolvedValue({ sent: true });
|
||||
mocks.preview.mockResolvedValue({
|
||||
version: 1,
|
||||
fingerprint: "a".repeat(64),
|
||||
changedPages: 1,
|
||||
changedOffers: 1,
|
||||
conflicts: [],
|
||||
});
|
||||
});
|
||||
it("keeps draft creation, saving and preview out of live export, audit and hotel updates", async () => {
|
||||
await createCatalogPackage({
|
||||
name: "Pack",
|
||||
pageIds: [1],
|
||||
mode: "copy",
|
||||
targetParentId: -1,
|
||||
});
|
||||
await saveCatalogPackage({
|
||||
id: "id",
|
||||
version: 1,
|
||||
name: "Pack",
|
||||
draft: { pages: [], offers: [] },
|
||||
targetParentId: -1,
|
||||
});
|
||||
await getCatalogPackage("id");
|
||||
await listCatalogPackages();
|
||||
await previewCatalogPackage("id");
|
||||
expect(mocks.permission.mock.calls.map((c) => c[0])).toEqual([
|
||||
"edit",
|
||||
"edit",
|
||||
"view",
|
||||
"view",
|
||||
"view",
|
||||
]);
|
||||
expect(mocks.export).not.toHaveBeenCalled();
|
||||
expect(mocks.audit).not.toHaveBeenCalled();
|
||||
expect(mocks.hotel).not.toHaveBeenCalled();
|
||||
});
|
||||
it("reports committed publication with warnings if audit and hotel updates fail", async () => {
|
||||
mocks.audit.mockRejectedValue(Error("audit down"));
|
||||
mocks.hotel.mockRejectedValue(Error("hotel down"));
|
||||
const result = await publishCatalogPackage({
|
||||
id: "id",
|
||||
version: 1,
|
||||
fingerprint: "a".repeat(64),
|
||||
});
|
||||
expect(result).toMatchObject({
|
||||
ok: true,
|
||||
data: { pageIds: [4], warnings: expect.any(Array) },
|
||||
});
|
||||
if (result.ok) expect(result.data.warnings).toHaveLength(2);
|
||||
expect(mocks.permission).toHaveBeenCalledWith("edit");
|
||||
});
|
||||
it("does not report a rollback if an export wrapper fails after commit", async () => {
|
||||
mocks.export.mockImplementation(async (fn) => {
|
||||
await fn();
|
||||
throw Error("export failed");
|
||||
});
|
||||
expect(
|
||||
await publishCatalogPackage({
|
||||
id: "id",
|
||||
version: 1,
|
||||
fingerprint: "a".repeat(64),
|
||||
}),
|
||||
).toMatchObject({
|
||||
ok: true,
|
||||
data: { warnings: ["Package published, but export scheduling failed."] },
|
||||
});
|
||||
});
|
||||
it("reports a transaction failure without sending hotel updates or audit", async () => {
|
||||
mocks.publish.mockRejectedValue(Error("live conflict"));
|
||||
expect(
|
||||
await publishCatalogPackage({
|
||||
id: "id",
|
||||
version: 1,
|
||||
fingerprint: "a".repeat(64),
|
||||
}),
|
||||
).toEqual({ ok: false, error: "live conflict" });
|
||||
expect(mocks.audit).not.toHaveBeenCalled();
|
||||
expect(mocks.hotel).not.toHaveBeenCalled();
|
||||
});
|
||||
it("does not repeat external side effects for an already published package", async () => {
|
||||
mocks.publish.mockResolvedValue({
|
||||
pageIds: [4],
|
||||
offerCount: 1,
|
||||
alreadyPublished: true,
|
||||
});
|
||||
expect(
|
||||
await publishCatalogPackage({
|
||||
id: "id",
|
||||
version: 1,
|
||||
fingerprint: "a".repeat(64),
|
||||
}),
|
||||
).toMatchObject({ ok: true, data: { alreadyPublished: true } });
|
||||
expect(mocks.audit).not.toHaveBeenCalled();
|
||||
expect(mocks.hotel).not.toHaveBeenCalled();
|
||||
});
|
||||
Reference in new issue
Block a user