import { randomUUID } from "node:crypto"; import { Widget, WidgetRequest, WidgetT } from "@/shared/schema"; import { expect, mock, test } from "bun:test"; import { ConsumerRequestProcessor } from "@/consumer/processor"; import { VoidLogger } from "@/shared/t"; const widgetDAOFactory = (): any => { return { retrieve: mock(async (widget: WidgetT) => { return widget; }), save: mock(async (widget: WidgetT) => { return widget; }), delete: mock(async (widget: WidgetT) => { return widget; }), }; }; test("when create request then warns when already existant and not save", async () => { const logger = new VoidLogger(); logger.warn = mock((_s) => {}); const mockWidgetDAO = widgetDAOFactory(); mockWidgetDAO.retrieve = mock(async (widget: WidgetT) => widget); const newWidgetRequest = WidgetRequest.parse({ type: "create", requestId: randomUUID(), owner: "simponic", widgetId: randomUUID(), }); const processor = new ConsumerRequestProcessor(mockWidgetDAO, logger); await processor.processRequest(newWidgetRequest); expect(mockWidgetDAO.retrieve).toHaveBeenCalledTimes(1); expect(mockWidgetDAO.save).toHaveBeenCalledTimes(0); expect(logger.warn).toHaveBeenCalledTimes(1); }); test("when create request then saves in dao if not exist", async () => { const logger = new VoidLogger(); const mockWidgetDAO = widgetDAOFactory(); mockWidgetDAO.retrieve = mock(async (_widget: WidgetT) => { return undefined; }); const newWidgetRequest = WidgetRequest.parse({ type: "create", requestId: randomUUID(), owner: "simponic", widgetId: randomUUID(), }); const processor = new ConsumerRequestProcessor(mockWidgetDAO, logger); await processor.processRequest(newWidgetRequest); expect(mockWidgetDAO.retrieve).toHaveBeenCalledTimes(1); expect(mockWidgetDAO.save).toHaveBeenCalledTimes(1); }); test("when delete request then fails and warns if not exists", async () => { const logger = new VoidLogger(); logger.warn = mock((_s) => {}); const mockWidgetDAO = widgetDAOFactory(); mockWidgetDAO.retrieve = mock(async (_widget: WidgetT) => { return undefined; }); const deleteWidgetRequest = WidgetRequest.parse({ type: "delete", requestId: randomUUID(), owner: "simponic", widgetId: randomUUID(), }); const processor = new ConsumerRequestProcessor(mockWidgetDAO, logger); await processor.processRequest(deleteWidgetRequest); expect(mockWidgetDAO.retrieve).toHaveBeenCalledTimes(1); expect(mockWidgetDAO.delete).toHaveBeenCalledTimes(0); expect(logger.warn).toHaveBeenCalledTimes(1); }); test("when delete request then success if exists", async () => { const logger = new VoidLogger(); const mockWidgetDAO = widgetDAOFactory(); mockWidgetDAO.retrieve = mock(async (widget: WidgetT) => { return widget; }); const deleteWidgetRequest = WidgetRequest.parse({ type: "delete", requestId: randomUUID(), owner: "simponic", widgetId: randomUUID(), }); const processor = new ConsumerRequestProcessor(mockWidgetDAO, logger); await processor.processRequest(deleteWidgetRequest); expect(mockWidgetDAO.retrieve).toHaveBeenCalledTimes(1); expect(mockWidgetDAO.delete).toHaveBeenCalledTimes(1); }); test("when update request then deletes empty string values", async () => { const logger = new VoidLogger(); const testWidget = Widget.parse({ id: "test-widget", owner: "simponic", label: "current label", }); const mockWidgetDAO = widgetDAOFactory(); mockWidgetDAO.retrieve = mock(async (_widget: WidgetT) => testWidget); const updateWidgetRequest = WidgetRequest.parse({ type: "update", requestId: randomUUID(), owner: "simponic", widgetId: testWidget.id, label: "", }); const processor = new ConsumerRequestProcessor(mockWidgetDAO, logger); await processor.processRequest(updateWidgetRequest); expect(mockWidgetDAO.retrieve).toHaveBeenCalledTimes(1); expect(mockWidgetDAO.save).toHaveBeenCalledTimes(1); expect(mockWidgetDAO.save.mock.calls[0][0]).toEqual( Widget.parse({ id: "test-widget", owner: "simponic" }), // "label" has been removed ); }); test("when update attempts to overwrite owner then update fails and warns", async () => { const logger = new VoidLogger(); logger.warn = mock((_s) => {}); const testWidget = Widget.parse({ id: "test-widget", owner: "simponic", label: "current label", }); const mockWidgetDAO = widgetDAOFactory(); mockWidgetDAO.retrieve = mock(async (_widget: WidgetT) => testWidget); const newWidgetRequest = WidgetRequest.parse({ type: "update", requestId: randomUUID(), owner: "newOwner", widgetId: testWidget.id, }); const processor = new ConsumerRequestProcessor(mockWidgetDAO, logger); await processor.processRequest(newWidgetRequest); expect(mockWidgetDAO.retrieve).toHaveBeenCalledTimes(1); expect(mockWidgetDAO.save).toHaveBeenCalledTimes(0); expect(logger.warn).toHaveBeenCalledTimes(1); }); test("when update mutable attribute field unspecified then not overwritten", async () => { const logger = new VoidLogger(); const testWidget = Widget.parse({ id: "test-widget", owner: "simponic", label: "non-overwritten label", }); const mockWidgetDAO = widgetDAOFactory(); mockWidgetDAO.retrieve = mock(async (_widget: WidgetT) => testWidget); const newWidgetRequest = WidgetRequest.parse({ type: "update", requestId: randomUUID(), owner: testWidget.owner, widgetId: testWidget.id, description: "", }); const processor = new ConsumerRequestProcessor(mockWidgetDAO, logger); await processor.processRequest(newWidgetRequest); expect(mockWidgetDAO.retrieve).toHaveBeenCalledTimes(1); expect(mockWidgetDAO.save).toHaveBeenCalledTimes(1); expect(mockWidgetDAO.save.mock.calls[0][0]).toEqual( Widget.parse({ id: "test-widget", owner: "simponic", label: "non-overwritten label", }), ); });