import "reflect-metadata"; import { container } from "tsyringe"; import { configureDIContainer, resetDIContainer } from "../../../apps/companion/main/di-config"; import { DI_TOKENS } from "../../../apps/companion/main/di-tokens"; import { OverlaySyncService } from "@gridpilot/automation/application/services/OverlaySyncService"; import { LoggerPort } from "@gridpilot/automation/application/ports/LoggerPort"; import { IAutomationLifecycleEmitter, LifecycleCallback } from "@gridpilot/automation/infrastructure//IAutomationLifecycleEmitter"; import { AutomationEventPublisherPort, AutomationEvent } from "@gridpilot/automation/application/ports/AutomationEventPublisherPort"; import { ConsoleLogAdapter } from "@gridpilot/automation/infrastructure//logging/ConsoleLogAdapter"; import { describe, it, expect, beforeEach, afterEach, vi, SpyInstance } from 'vitest'; describe("OverlaySyncService Integration with ConsoleLogAdapter", () => { let consoleErrorSpy: SpyInstance<[message?: any, ...optionalParams: any[]], void>; let consoleWarnSpy: SpyInstance<[message?: any, ...optionalParams: any[]], void>; let originalNodeEnv: string | undefined; beforeEach(() => { originalNodeEnv = process.env.NODE_ENV; process.env.NODE_ENV = 'development'; resetDIContainer(); configureDIContainer(); consoleErrorSpy = vi.spyOn(console, "error").mockImplementation(() => {}); consoleWarnSpy = vi.spyOn(console, "warn").mockImplementation(() => {}); }); afterEach(() => { consoleErrorSpy.mockRestore(); consoleWarnSpy.mockRestore(); if (originalNodeEnv !== undefined) { process.env.NODE_ENV = originalNodeEnv; } resetDIContainer(); }); it("should use ConsoleLogAdapter and log messages when OverlaySyncService encounters an error", async () => { const logger = container.resolve(DI_TOKENS.Logger); const overlaySyncService = container.resolve(DI_TOKENS.OverlaySyncPort); expect(logger).toBeInstanceOf(ConsoleLogAdapter); const mockLifecycleEmitter: IAutomationLifecycleEmitter = { onLifecycle: vi.fn((_cb: LifecycleCallback) => { throw new Error("Test lifecycle emitter error"); }), offLifecycle: vi.fn(), }; const mockPublisher: AutomationEventPublisherPort = { publish: vi.fn(), }; const serviceWithMockedEmitter = new OverlaySyncService({ lifecycleEmitter: mockLifecycleEmitter, publisher: mockPublisher, logger: logger, }); const action = { id: "test-action-1", label: "Test Action" }; await serviceWithMockedEmitter.execute(action); expect(consoleErrorSpy).toHaveBeenCalledWith( expect.stringContaining("OverlaySyncService: failed to subscribe to lifecycleEmitter"), expect.any(Error), expect.objectContaining({ actionId: action.id }), ); expect(consoleWarnSpy).not.toHaveBeenCalled(); }); it("should use ConsoleLogAdapter and log warn messages when OverlaySyncService fails to publish", async () => { const logger = container.resolve(DI_TOKENS.Logger); expect(logger).toBeInstanceOf(ConsoleLogAdapter); const mockLifecycleEmitter: IAutomationLifecycleEmitter = { onLifecycle: vi.fn(), offLifecycle: vi.fn(), }; const mockPublisher: AutomationEventPublisherPort = { publish: vi.fn((_event: AutomationEvent) => { throw new Error("Test publish error"); }), }; const serviceWithMockedPublisher = new OverlaySyncService({ lifecycleEmitter: mockLifecycleEmitter, publisher: mockPublisher, logger: logger, }); const action = { id: "test-action-2", label: "Test Action" }; await serviceWithMockedPublisher.execute(action); expect(consoleWarnSpy).toHaveBeenCalledWith( expect.stringContaining("OverlaySyncService: publisher.publish failed"), expect.objectContaining({ actionId: action.id, error: expect.any(Error), }), ); expect(consoleErrorSpy).not.toHaveBeenCalled(); }); });