From: Jérôme Benoit Date: Sat, 28 Feb 2026 21:16:52 +0000 (+0100) Subject: refactor(tests): consolidate MockUIService classes and remove redundant subclass X-Git-Tag: ocpp-server@v3.0.0~67 X-Git-Url: https://git.piment-noir.org/?a=commitdiff_plain;h=838a2ca01f1fcc1d25aa944179da4a5150e1ce7b;p=e-mobility-charging-stations-simulator.git refactor(tests): consolidate MockUIService classes and remove redundant subclass - Replace MockUIServiceBroadcast, MockUIServiceError, MockUIServiceNonBroadcast with single createMockUIService(MockUIServiceMode) factory - Remove redundant MockWebSocket subclass from UIServerTestUtils.ts - Re-export createUIProtocolMock as createMockUIWebSocket for UI testing - Update UIWebSocketServer.test.ts to use new factories --- diff --git a/tests/charging-station/ui-server/UIServerTestUtils.ts b/tests/charging-station/ui-server/UIServerTestUtils.ts index 64ccaae8..bc5a0458 100644 --- a/tests/charging-station/ui-server/UIServerTestUtils.ts +++ b/tests/charging-station/ui-server/UIServerTestUtils.ts @@ -21,8 +21,18 @@ import { ResponseStatus, } from '../../../src/types/index.js' import { waitForCondition } from '../helpers/StationHelpers.js' -import { MockWebSocket as BaseMockWebSocket } from '../mocks/MockWebSocket.js' +import { MockWebSocket as BaseMockWebSocket, createUIProtocolMock } from '../mocks/MockWebSocket.js' +// Re-export MockWebSocket for backward compatibility +// Note: Use createMockUIWebSocket() factory for new code +export { BaseMockWebSocket as MockWebSocket } + +/** + * Create a MockWebSocket configured for UI protocol testing. + * @param protocol - UI protocol version (default: 'ui0.0.1') + * @returns MockWebSocket instance configured for UI testing + */ +export const createMockUIWebSocket = createUIProtocolMock // Re-export waitForCondition for backward compatibility export { waitForCondition } @@ -100,31 +110,6 @@ export class MockServerResponse extends EventEmitter { } } -/** - * MockWebSocket for UI protocol testing - * - * Extends base MockWebSocket with UI-specific helper methods. - * Uses 'ui0.0.1' protocol by default. - */ -export class MockWebSocket extends BaseMockWebSocket { - constructor () { - super('ws://localhost:8080/ui') - this.protocol = 'ui0.0.1' - } - - /** - * Get last sent message parsed as ProtocolResponse - * @returns Parsed ProtocolResponse or undefined if no messages - */ - public getLastSentMessageAsResponse (): ProtocolResponse | undefined { - const lastMsg = this.getLastSentMessage() - if (lastMsg == null) { - return undefined - } - return JSON.parse(lastMsg) as ProtocolResponse - } -} - export const createMockIncomingMessage = ( overrides?: Partial ): IncomingMessage => { @@ -189,23 +174,61 @@ export const createMockBroadcastResponse = ( return [uuid, { hashId, status }] } -export class MockUIServiceBroadcast { - requestHandler (): Promise { - return Promise.resolve(undefined) - } +/** + * Mock UI service behavior mode for testing different request handler scenarios. + */ +export enum MockUIServiceMode { + /** Returns undefined (broadcast behavior - handler preserved until explicit deletion) */ + BROADCAST = 'broadcast', + /** Throws an error (error behavior - handler preserved) */ + ERROR = 'error', + /** Returns a response (non-broadcast behavior - handler deleted immediately) */ + NON_BROADCAST = 'non-broadcast', } -export class MockUIServiceError { - requestHandler (): Promise { - return Promise.reject(new Error('Request handler error')) - } +/** + * Mock UI service interface for testing UIWebSocketServer request handling. + */ +export interface MockUIService { + requestHandler: (request?: ProtocolRequest) => Promise } -export class MockUIServiceNonBroadcast { - requestHandler (request: ProtocolRequest): Promise { - return Promise.resolve([request[0], { status: ResponseStatus.SUCCESS }]) - } -} +/** + * Create a mock UI service for testing UIWebSocketServer. + * + * Consolidates MockUIServiceBroadcast, MockUIServiceError, and MockUIServiceNonBroadcast + * into a single parameterized factory. + * @param mode - Service behavior mode (defaults to BROADCAST) + * @returns Mock UI service with behavior based on mode + * @example + * ```typescript + * // Broadcast mode - returns undefined, handler preserved + * const broadcastService = createMockUIService(MockUIServiceMode.BROADCAST) + * + * // Error mode - throws error, handler preserved + * const errorService = createMockUIService(MockUIServiceMode.ERROR) + * + * // Non-broadcast mode - returns response, handler deleted + * const nonBroadcastService = createMockUIService(MockUIServiceMode.NON_BROADCAST) + * ``` + */ +export const createMockUIService = ( + mode: MockUIServiceMode = MockUIServiceMode.BROADCAST +): MockUIService => ({ + requestHandler: (request?: ProtocolRequest): Promise => { + switch (mode) { + case MockUIServiceMode.BROADCAST: + return Promise.resolve(undefined) + case MockUIServiceMode.ERROR: + return Promise.reject(new Error('Request handler error')) + case MockUIServiceMode.NON_BROADCAST: + if (request == null) { + return Promise.reject(new Error('Request required for non-broadcast mode')) + } + return Promise.resolve([request[0], { status: ResponseStatus.SUCCESS }]) + } + }, +}) export const waitForStreamFlush = async (delayMs: number): Promise => { await new Promise(resolve => { diff --git a/tests/charging-station/ui-server/UIWebSocketServer.test.ts b/tests/charging-station/ui-server/UIWebSocketServer.test.ts index 5e8bf64e..05d71e6b 100644 --- a/tests/charging-station/ui-server/UIWebSocketServer.test.ts +++ b/tests/charging-station/ui-server/UIWebSocketServer.test.ts @@ -11,13 +11,13 @@ import type { UUIDv4 } from '../../../src/types/index.js' import { UIWebSocketServer } from '../../../src/charging-station/ui-server/UIWebSocketServer.js' import { ProcedureName, ResponseStatus } from '../../../src/types/index.js' +import { MockWebSocket } from '../mocks/MockWebSocket.js' import { TEST_UUID } from './UIServerTestConstants.js' import { createMockUIServerConfiguration, - MockUIServiceBroadcast, - MockUIServiceError, - MockUIServiceNonBroadcast, - MockWebSocket, + createMockUIService, + createMockUIWebSocket, + MockUIServiceMode, } from './UIServerTestUtils.js' class TestableUIWebSocketServer extends UIWebSocketServer { @@ -41,7 +41,7 @@ await describe('UIWebSocketServer test suite', async () => { await it('should delete response handler after successful send', () => { const config = createMockUIServerConfiguration() const server = new TestableUIWebSocketServer(config) - const ws = new MockWebSocket() + const ws = createMockUIWebSocket() server.addResponseHandler(TEST_UUID, ws) expect(server.hasResponseHandler(TEST_UUID)).toBe(true) @@ -64,7 +64,7 @@ await describe('UIWebSocketServer test suite', async () => { await it('should delete handler when WebSocket not in OPEN state', () => { const config = createMockUIServerConfiguration() const server = new TestableUIWebSocketServer(config) - const ws = new MockWebSocket() + const ws = createMockUIWebSocket() ws.readyState = 0 server.addResponseHandler(TEST_UUID, ws) @@ -77,7 +77,7 @@ await describe('UIWebSocketServer test suite', async () => { await it('should handle send errors gracefully without throwing', () => { const config = createMockUIServerConfiguration() const server = new TestableUIWebSocketServer(config) - const ws = new MockWebSocket() + const ws = createMockUIWebSocket() ws.readyState = 1 ws.send = (): void => { throw new Error('WebSocket send error') @@ -92,8 +92,8 @@ await describe('UIWebSocketServer test suite', async () => { await it('should preserve broadcast handler until explicit deletion (issue #1642)', async () => { const config = createMockUIServerConfiguration() const server = new TestableUIWebSocketServer(config) - const mockService = new MockUIServiceBroadcast() - const ws = new MockWebSocket() + const mockService = createMockUIService(MockUIServiceMode.BROADCAST) + const ws = createMockUIWebSocket() server.registerMockUIService('0.0.1', mockService) server.addResponseHandler(TEST_UUID, ws) @@ -114,8 +114,8 @@ await describe('UIWebSocketServer test suite', async () => { await it('should delete non-broadcast handler immediately after response', async () => { const config = createMockUIServerConfiguration() const server = new TestableUIWebSocketServer(config) - const mockService = new MockUIServiceNonBroadcast() - const ws = new MockWebSocket() + const mockService = createMockUIService(MockUIServiceMode.NON_BROADCAST) + const ws = createMockUIWebSocket() server.registerMockUIService('0.0.1', mockService) server.addResponseHandler(TEST_UUID, ws) @@ -133,8 +133,8 @@ await describe('UIWebSocketServer test suite', async () => { await it('should preserve handler when service throws error', async () => { const config = createMockUIServerConfiguration() const server = new TestableUIWebSocketServer(config) - const mockService = new MockUIServiceError() - const ws = new MockWebSocket() + const mockService = createMockUIService(MockUIServiceMode.ERROR) + const ws = createMockUIWebSocket() server.registerMockUIService('0.0.1', mockService) server.addResponseHandler(TEST_UUID, ws) @@ -151,8 +151,8 @@ await describe('UIWebSocketServer test suite', async () => { await it('should clean up response handlers after each response', () => { const config = createMockUIServerConfiguration() const server = new TestableUIWebSocketServer(config) - const ws1 = new MockWebSocket() - const ws2 = new MockWebSocket() + const ws1 = createMockUIWebSocket() + const ws2 = createMockUIWebSocket() server.addResponseHandler('uuid-1' as UUIDv4, ws1) server.addResponseHandler('uuid-2' as UUIDv4, ws2) @@ -169,7 +169,7 @@ await describe('UIWebSocketServer test suite', async () => { await it('should clear all handlers on server stop', () => { const config = createMockUIServerConfiguration() const server = new TestableUIWebSocketServer(config) - const ws = new MockWebSocket() + const ws = createMockUIWebSocket() server.addResponseHandler(TEST_UUID, ws) expect(server.getResponseHandlersSize()).toBe(1)