feat(catalog): undo bulk offer edits with guarded history restoration

This commit is contained in:
Simo committed 2026-09-11 10:47:46 +02:00
1 parent 13bd3695cb
commit c5a2b44807
33 files changed
+1399 -116

No files matched your search

@@ -5,6 +5,7 @@ const state = vi.hoisted(() => ({
preview: vi.fn(),
destinations: vi.fn(),
apply: vi.fn(),
undo: vi.fn(),
export: vi.fn(),
send: vi.fn(),
audit: vi.fn(),
@@ -18,6 +19,7 @@ vi.mock("@/features/catalog/server/bulk-offers", () => ({
previewBulkOffersCommand: state.preview,
listBulkOfferDestinationsCommand: state.destinations,
applyBulkOffersCommand: state.apply,
undoBulkOffersCommand: state.undo,
}));
vi.mock("@/lib/services/catalog-git-queue", () => ({
withCatalogExport: state.export,
@@ -33,6 +35,7 @@ import {
applyBulkOffers,
getBulkOfferDestinations,
previewBulkOffers,
undoBulkOffers,
} from "@/actions/catalog-bulk";
const input = { ids: [1], changes: { pageId: 2 } };
@@ -87,3 +90,20 @@ it("loads destination choices with view permission only", async () => {
expect(state.permission).toHaveBeenCalledWith("view");
expect(state.export).not.toHaveBeenCalled();
});
it("undo enforces edit access and exports only successful restores", async () => {
state.undo.mockResolvedValueOnce({ changedCount: 2 });
expect((await undoBulkOffers([10, 11])).ok).toBe(true);
expect(state.permission).toHaveBeenCalledWith("edit");
expect(state.undo).toHaveBeenCalledWith([10, 11], 1);
expect(state.export).toHaveBeenCalledTimes(1);
expect(state.send).toHaveBeenCalledTimes(1);
});
it("undo denial stops before export and a conflict does not notify", async () => {
state.permission.mockRejectedValueOnce(Error("Denied"));
await expect(undoBulkOffers([10])).rejects.toThrow("Denied");
expect(state.export).not.toHaveBeenCalled();
state.undo.mockRejectedValueOnce(Error("conflict"));
expect((await undoBulkOffers([10])).ok).toBe(false);
expect(state.send).not.toHaveBeenCalled();
});