From: Jérôme Benoit Date: Fri, 27 Feb 2026 22:03:44 +0000 (+0100) Subject: test: harmonize test names and add mock factories X-Git-Tag: v3~97 X-Git-Url: https://git.piment-noir.org/?a=commitdiff_plain;h=f146ae6b7443226b7e29dedcc9d55ed2810ee032;p=e-mobility-charging-stations-simulator.git test: harmonize test names and add mock factories - Replace 164 'should verify' patterns with descriptive test names - Add createLoggerMocks() and createConsoleMocks() to TestLifecycleHelpers - Add afterEach cleanup to ErrorUtils, WorkerUtils, ConfigurationUtils tests - Align all test names with TEST_STYLE_GUIDE.md conventions --- diff --git a/tests/charging-station/Helpers.test.ts b/tests/charging-station/Helpers.test.ts index b26fe190..a7b9f028 100644 --- a/tests/charging-station/Helpers.test.ts +++ b/tests/charging-station/Helpers.test.ts @@ -53,17 +53,17 @@ await describe('Helpers test suite', async () => { reservationId: 1, }) as Reservation - await it('should verify getChargingStationId()', () => { + await it('should return formatted charging station ID with index', () => { expect(getChargingStationId(1, chargingStationTemplate)).toBe(`${baseName}-00001`) }) - await it('should verify getHashId()', () => { + await it('should return consistent hash ID for same template and index', () => { expect(getHashId(1, chargingStationTemplate)).toBe( 'b4b1e8ec4fca79091d99ea9a7ea5901548010e6c0e98be9296f604b9d68734444dfdae73d7d406b6124b42815214d088' ) }) - await it('should verify validateStationInfo() - Missing stationInfo', () => { + await it('should throw when stationInfo is missing', () => { // For validation edge cases, we need to manually create invalid states // since the factory is designed to create valid configurations const stationNoInfo = createChargingStation({ baseName }) @@ -74,7 +74,7 @@ await describe('Helpers test suite', async () => { }).toThrow(new BaseError('Missing charging station information')) }) - await it('should verify validateStationInfo() - Empty stationInfo', () => { + await it('should throw when stationInfo is empty object', () => { // For validation edge cases, manually create empty stationInfo const stationEmptyInfo = createChargingStation({ baseName }) stationEmptyInfo.stationInfo = {} as ChargingStationInfo @@ -83,7 +83,7 @@ await describe('Helpers test suite', async () => { }).toThrow(new BaseError('Missing charging station information')) }) - await it('should verify validateStationInfo() - Missing chargingStationId', () => { + await it('should throw when chargingStationId is undefined', () => { const stationMissingId = createChargingStation({ baseName, stationInfo: { baseName, chargingStationId: undefined }, @@ -93,7 +93,7 @@ await describe('Helpers test suite', async () => { }).toThrow(new BaseError('Missing chargingStationId in stationInfo properties')) }) - await it('should verify validateStationInfo() - Empty chargingStationId', () => { + await it('should throw when chargingStationId is empty string', () => { const stationEmptyId = createChargingStation({ baseName, stationInfo: { baseName, chargingStationId: '' }, @@ -103,7 +103,7 @@ await describe('Helpers test suite', async () => { }).toThrow(new BaseError('Missing chargingStationId in stationInfo properties')) }) - await it('should verify validateStationInfo() - Missing hashId', () => { + await it('should throw when hashId is undefined', () => { const stationMissingHash = createChargingStation({ baseName, stationInfo: { @@ -117,7 +117,7 @@ await describe('Helpers test suite', async () => { }).toThrow(new BaseError(`${baseName}-00001: Missing hashId in stationInfo properties`)) }) - await it('should verify validateStationInfo() - Empty hashId', () => { + await it('should throw when hashId is empty string', () => { const stationEmptyHash = createChargingStation({ baseName, stationInfo: { @@ -131,7 +131,7 @@ await describe('Helpers test suite', async () => { }).toThrow(new BaseError(`${baseName}-00001: Missing hashId in stationInfo properties`)) }) - await it('should verify validateStationInfo() - Missing templateIndex', () => { + await it('should throw when templateIndex is undefined', () => { const stationMissingTemplate = createChargingStation({ baseName, stationInfo: { @@ -146,7 +146,7 @@ await describe('Helpers test suite', async () => { }).toThrow(new BaseError(`${baseName}-00001: Missing templateIndex in stationInfo properties`)) }) - await it('should verify validateStationInfo() - Invalid templateIndex (zero)', () => { + await it('should throw when templateIndex is zero', () => { const stationInvalidTemplate = createChargingStation({ baseName, stationInfo: { @@ -163,7 +163,7 @@ await describe('Helpers test suite', async () => { ) }) - await it('should verify validateStationInfo() - Missing templateName', () => { + await it('should throw when templateName is undefined', () => { const stationMissingName = createChargingStation({ baseName, stationInfo: { @@ -179,7 +179,7 @@ await describe('Helpers test suite', async () => { }).toThrow(new BaseError(`${baseName}-00001: Missing templateName in stationInfo properties`)) }) - await it('should verify validateStationInfo() - Empty templateName', () => { + await it('should throw when templateName is empty string', () => { const stationEmptyName = createChargingStation({ baseName, stationInfo: { @@ -195,7 +195,7 @@ await describe('Helpers test suite', async () => { }).toThrow(new BaseError(`${baseName}-00001: Missing templateName in stationInfo properties`)) }) - await it('should verify validateStationInfo() - Missing maximumPower', () => { + await it('should throw when maximumPower is undefined', () => { const stationMissingPower = createChargingStation({ baseName, stationInfo: { @@ -212,7 +212,7 @@ await describe('Helpers test suite', async () => { }).toThrow(new BaseError(`${baseName}-00001: Missing maximumPower in stationInfo properties`)) }) - await it('should verify validateStationInfo() - Invalid maximumPower (zero)', () => { + await it('should throw when maximumPower is zero', () => { const stationInvalidPower = createChargingStation({ baseName, stationInfo: { @@ -231,7 +231,7 @@ await describe('Helpers test suite', async () => { ) }) - await it('should verify validateStationInfo() - Missing maximumAmperage', () => { + await it('should throw when maximumAmperage is undefined', () => { const stationMissingAmperage = createChargingStation({ baseName, stationInfo: { @@ -251,7 +251,7 @@ await describe('Helpers test suite', async () => { ) }) - await it('should verify validateStationInfo() - Invalid maximumAmperage (zero)', () => { + await it('should throw when maximumAmperage is zero', () => { const stationInvalidAmperage = createChargingStation({ baseName, stationInfo: { @@ -271,7 +271,7 @@ await describe('Helpers test suite', async () => { ) }) - await it('should verify validateStationInfo() - Valid configuration passes', () => { + await it('should pass validation with complete valid configuration', () => { const validStation = createChargingStation({ baseName, stationInfo: { @@ -289,7 +289,7 @@ await describe('Helpers test suite', async () => { }).not.toThrow() }) - await it('should verify validateStationInfo() - OCPP 2.0 requires EVSE', () => { + await it('should throw for OCPP 2.0 without EVSE configuration', () => { const stationOcpp20 = createChargingStation({ baseName, connectorsCount: 0, // Ensure no EVSEs are created @@ -313,7 +313,7 @@ await describe('Helpers test suite', async () => { ) }) - await it('should verify validateStationInfo() - OCPP 2.0.1 requires EVSE', () => { + await it('should throw for OCPP 2.0.1 without EVSE configuration', () => { const stationOcpp201 = createChargingStation({ baseName, connectorsCount: 0, // Ensure no EVSEs are created @@ -337,28 +337,28 @@ await describe('Helpers test suite', async () => { ) }) - await it('should verify checkChargingStationState() - Not started or starting', t => { + await it('should return false and warn when station is not started or starting', t => { const warnMock = t.mock.method(logger, 'warn') const stationNotStarted = createChargingStation({ baseName, started: false, starting: false }) expect(checkChargingStationState(stationNotStarted, 'log prefix |')).toBe(false) expect(warnMock.mock.calls.length).toBe(1) }) - await it('should verify checkChargingStationState() - Starting returns true', t => { + await it('should return true when station is starting', t => { const warnMock = t.mock.method(logger, 'warn') const stationStarting = createChargingStation({ baseName, started: false, starting: true }) expect(checkChargingStationState(stationStarting, 'log prefix |')).toBe(true) expect(warnMock.mock.calls.length).toBe(0) }) - await it('should verify checkChargingStationState() - Started returns true', t => { + await it('should return true when station is started', t => { const warnMock = t.mock.method(logger, 'warn') const stationStarted = createChargingStation({ baseName, started: true, starting: false }) expect(checkChargingStationState(stationStarted, 'log prefix |')).toBe(true) expect(warnMock.mock.calls.length).toBe(0) }) - await it('should verify getPhaseRotationValue()', () => { + await it('should return correct phase rotation value for connector and phase count', () => { expect(getPhaseRotationValue(0, 0)).toBe('0.RST') expect(getPhaseRotationValue(1, 0)).toBe('1.NotApplicable') expect(getPhaseRotationValue(2, 0)).toBe('2.NotApplicable') @@ -373,12 +373,12 @@ await describe('Helpers test suite', async () => { expect(getPhaseRotationValue(2, 3)).toBe('2.RST') }) - await it('should verify getMaxNumberOfEvses()', () => { + await it('should return -1 for undefined EVSEs and 0 for empty object', () => { expect(getMaxNumberOfEvses(undefined)).toBe(-1) expect(getMaxNumberOfEvses({})).toBe(0) }) - await it('should verify checkTemplate()', t => { + await it('should throw for undefined or empty template', t => { const warnMock = t.mock.method(logger, 'warn') const errorMock = t.mock.method(logger, 'error') expect(() => { @@ -395,7 +395,7 @@ await describe('Helpers test suite', async () => { expect(warnMock.mock.calls.length).toBe(1) }) - await it('should verify checkConfiguration()', t => { + await it('should throw for undefined or empty configuration', t => { const errorMock = t.mock.method(logger, 'error') expect(() => { checkConfiguration(undefined, 'log prefix |', 'configuration.json') @@ -409,7 +409,7 @@ await describe('Helpers test suite', async () => { expect(errorMock.mock.calls.length).toBe(2) }) - await it('should verify checkStationInfoConnectorStatus()', t => { + await it('should warn and clear status when connector has predefined status', t => { const warnMock = t.mock.method(logger, 'warn') checkStationInfoConnectorStatus(1, {} as ConnectorStatus, 'log prefix |', 'test-template.json') expect(warnMock.mock.calls.length).toBe(0) @@ -421,7 +421,7 @@ await describe('Helpers test suite', async () => { expect(connectorStatus.status).toBeUndefined() }) - await it('should verify getBootConnectorStatus() - default to Available when no bootStatus', () => { + await it('should return Available when no bootStatus is defined', () => { const chargingStation = createChargingStation({ baseName, connectorsCount: 2 }) const connectorStatus = {} as ConnectorStatus expect(getBootConnectorStatus(chargingStation, 1, connectorStatus)).toBe( @@ -429,7 +429,7 @@ await describe('Helpers test suite', async () => { ) }) - await it('should verify getBootConnectorStatus() - use bootStatus from template', () => { + await it('should return bootStatus from template when defined', () => { const chargingStation = createChargingStation({ baseName, connectorsCount: 2 }) const connectorStatus = { bootStatus: ConnectorStatusEnum.Unavailable, @@ -439,7 +439,7 @@ await describe('Helpers test suite', async () => { ) }) - await it('should verify getBootConnectorStatus() - charging station unavailable overrides bootStatus', () => { + await it('should return Unavailable when charging station is inoperative', () => { const chargingStation = createChargingStation({ baseName, connectorDefaults: { availability: AvailabilityType.Inoperative }, @@ -453,7 +453,7 @@ await describe('Helpers test suite', async () => { ) }) - await it('should verify getBootConnectorStatus() - connector unavailable overrides bootStatus', () => { + await it('should return Unavailable when connector is inoperative', () => { const chargingStation = createChargingStation({ baseName, connectorDefaults: { availability: AvailabilityType.Inoperative }, @@ -468,7 +468,7 @@ await describe('Helpers test suite', async () => { ) }) - await it('should verify getBootConnectorStatus() - transaction in progress restores previous status', () => { + await it('should restore previous status when transaction is in progress', () => { const chargingStation = createChargingStation({ baseName, connectorsCount: 2 }) const connectorStatus = { bootStatus: ConnectorStatusEnum.Available, @@ -480,7 +480,7 @@ await describe('Helpers test suite', async () => { ) }) - await it('should verify getBootConnectorStatus() - no transaction uses bootStatus over previous status', () => { + await it('should use bootStatus over previous status when no transaction', () => { const chargingStation = createChargingStation({ baseName, connectorsCount: 2 }) const connectorStatus = { bootStatus: ConnectorStatusEnum.Available, @@ -493,35 +493,35 @@ await describe('Helpers test suite', async () => { }) // Tests for reservation helper functions - await it('should verify hasReservationExpired() - expired reservation', () => { + await it('should return true when reservation has expired', () => { expect(hasReservationExpired(createTestReservation(true))).toBe(true) }) - await it('should verify hasReservationExpired() - valid reservation', () => { + await it('should return false when reservation is still valid', () => { expect(hasReservationExpired(createTestReservation(false))).toBe(false) }) - await it('should verify hasPendingReservation() - no reservation', () => { + await it('should return false when connector has no reservation', () => { const connectorStatus = {} as ConnectorStatus expect(hasPendingReservation(connectorStatus)).toBe(false) }) - await it('should verify hasPendingReservation() - with valid reservation', () => { + await it('should return true when connector has valid pending reservation', () => { const connectorStatus = { reservation: createTestReservation(false) } as ConnectorStatus expect(hasPendingReservation(connectorStatus)).toBe(true) }) - await it('should verify hasPendingReservation() - with expired reservation', () => { + await it('should return false when connector reservation has expired', () => { const connectorStatus = { reservation: createTestReservation(true) } as ConnectorStatus expect(hasPendingReservation(connectorStatus)).toBe(false) }) - await it('should verify hasPendingReservations() - no reservations (without EVSEs)', () => { + await it('should return false when no reservations exist (connector mode)', () => { const chargingStation = createChargingStation({ baseName, connectorsCount: 2 }) expect(hasPendingReservations(chargingStation)).toBe(false) }) - await it('should verify hasPendingReservations() - with pending reservation (without EVSEs)', () => { + await it('should return true when pending reservation exists (connector mode)', () => { const chargingStation = createChargingStation({ baseName, connectorsCount: 2 }) const connectorStatus = chargingStation.connectors.get(1) if (connectorStatus != null) { @@ -530,7 +530,7 @@ await describe('Helpers test suite', async () => { expect(hasPendingReservations(chargingStation)).toBe(true) }) - await it('should verify hasPendingReservations() - no reservations (with EVSEs)', () => { + await it('should return false when no reservations exist (EVSE mode)', () => { const chargingStation = createChargingStation({ baseName, connectorsCount: 2, @@ -539,7 +539,7 @@ await describe('Helpers test suite', async () => { expect(hasPendingReservations(chargingStation)).toBe(false) }) - await it('should verify hasPendingReservations() - with pending reservation (with EVSEs)', () => { + await it('should return true when pending reservation exists (EVSE mode)', () => { const chargingStation = createChargingStation({ baseName, connectorsCount: 2, @@ -553,7 +553,7 @@ await describe('Helpers test suite', async () => { expect(hasPendingReservations(chargingStation)).toBe(true) }) - await it('should verify hasPendingReservations() - with expired reservation only (with EVSEs)', () => { + await it('should return false when only expired reservations exist (EVSE mode)', () => { const chargingStation = createChargingStation({ baseName, connectorsCount: 2, diff --git a/tests/charging-station/ocpp/2.0/OCPP20RequestService-HeartBeat.test.ts b/tests/charging-station/ocpp/2.0/OCPP20RequestService-HeartBeat.test.ts index 4fee3e52..8b19aa04 100644 --- a/tests/charging-station/ocpp/2.0/OCPP20RequestService-HeartBeat.test.ts +++ b/tests/charging-station/ocpp/2.0/OCPP20RequestService-HeartBeat.test.ts @@ -158,7 +158,7 @@ await describe('G02 - Heartbeat', async () => { }) // FR: G02.FR.06 - await it('should verify HeartBeat request conforms to OCPP 2.0 specification', () => { + await it('should build empty HeartBeat request conforming to OCPP 2.0 specification', () => { const requestParams: OCPP20HeartbeatRequest = {} const payload = (requestService as any).buildRequestPayload( diff --git a/tests/charging-station/ocpp/2.0/OCPP20VariableManager.test.ts b/tests/charging-station/ocpp/2.0/OCPP20VariableManager.test.ts index 605dd1c7..ade54289 100644 --- a/tests/charging-station/ocpp/2.0/OCPP20VariableManager.test.ts +++ b/tests/charging-station/ocpp/2.0/OCPP20VariableManager.test.ts @@ -81,7 +81,7 @@ await describe('B05/B06 - OCPP20VariableManager test suite', async () => { OCPP20VariableManager.getInstance().resetRuntimeOverrides() }) - await it('should verify that OCPP20VariableManager can be instantiated as singleton', () => { + await it('should return same instance when getInstance() called multiple times', () => { const manager1 = OCPP20VariableManager.getInstance() const manager2 = OCPP20VariableManager.getInstance() diff --git a/tests/charging-station/ui-server/UIHttpServer.test.ts b/tests/charging-station/ui-server/UIHttpServer.test.ts index 6beff662..aaf148bc 100644 --- a/tests/charging-station/ui-server/UIHttpServer.test.ts +++ b/tests/charging-station/ui-server/UIHttpServer.test.ts @@ -47,7 +47,7 @@ const createLargePayload = (status: ResponseStatus = ResponseStatus.SUCCESS) => }) await describe('UIHttpServer test suite', async () => { - await it('should verify sendResponse() deletes handler after sending', () => { + await it('should delete response handler after successful send', () => { const server = new TestableUIHttpServer(createHttpServerConfig()) const res = new MockServerResponse() @@ -61,7 +61,7 @@ await describe('UIHttpServer test suite', async () => { expect(res.statusCode).toBe(200) }) - await it('should verify sendResponse() logs error when handler not found', () => { + await it('should log error when response handler not found', () => { const server = new TestableUIHttpServer(createHttpServerConfig()) server.sendResponse([TEST_UUID, { status: ResponseStatus.SUCCESS }]) @@ -69,7 +69,7 @@ await describe('UIHttpServer test suite', async () => { expect(server.hasResponseHandler(TEST_UUID)).toBe(false) }) - await it('should verify sendResponse() sets correct status code for failure', () => { + await it('should set status code 400 for failure responses', () => { const server = new TestableUIHttpServer(createHttpServerConfig()) const res = new MockServerResponse() @@ -81,7 +81,7 @@ await describe('UIHttpServer test suite', async () => { expect(res.statusCode).toBe(400) }) - await it('should verify sendResponse() handles send errors gracefully', () => { + await it('should handle send errors gracefully without throwing', () => { const server = new TestableUIHttpServer(createHttpServerConfig()) const res = new MockServerResponse() res.end = (): never => { @@ -94,7 +94,7 @@ await describe('UIHttpServer test suite', async () => { expect(server.hasResponseHandler(TEST_UUID)).toBe(false) }) - await it('should verify sendResponse() sets correct Content-Type header', () => { + await it('should set application/json Content-Type header', () => { const server = new TestableUIHttpServer(createHttpServerConfig()) const res = new MockServerResponse() @@ -104,7 +104,7 @@ await describe('UIHttpServer test suite', async () => { expect(res.headers['Content-Type']).toBe('application/json') }) - await it('should verify response handlers cleanup', () => { + await it('should clean up response handlers after each response', () => { const server = new TestableUIHttpServer(createHttpServerConfig()) const res1 = new MockServerResponse() const res2 = new MockServerResponse() @@ -120,7 +120,7 @@ await describe('UIHttpServer test suite', async () => { expect(server.getResponseHandlersSize()).toBe(0) }) - await it('should verify handlers cleared on server stop', () => { + await it('should clear all handlers on server stop', () => { const server = new TestableUIHttpServer(createHttpServerConfig()) const res = new MockServerResponse() @@ -132,7 +132,7 @@ await describe('UIHttpServer test suite', async () => { expect(server.getResponseHandlersSize()).toBe(0) }) - await it('should verify response payload serialization', () => { + await it('should serialize response payload to JSON correctly', () => { const server = new TestableUIHttpServer(createHttpServerConfig()) const res = new MockServerResponse() const payload = { @@ -149,7 +149,7 @@ await describe('UIHttpServer test suite', async () => { expect(parsedBody.hashIdsSucceeded).toEqual(['station-1', 'station-2']) }) - await it('should verify response with error details', () => { + await it('should include error details in failure response', () => { const server = new TestableUIHttpServer(createHttpServerConfig()) const res = new MockServerResponse() const payload = { @@ -168,13 +168,13 @@ await describe('UIHttpServer test suite', async () => { expect(parsedBody.hashIdsFailed).toEqual(['station-1']) }) - await it('should verify valid HTTP configuration', () => { + await it('should create server with valid HTTP configuration', () => { const server = new UIHttpServer(createHttpServerConfig()) expect(server).toBeDefined() }) - await it('should verify HTTP server with custom config', () => { + await it('should create server with custom host and port', () => { const config = createMockUIServerConfiguration({ options: { host: 'localhost', @@ -188,7 +188,7 @@ await describe('UIHttpServer test suite', async () => { }) await describe('Gzip compression', async () => { - await it('should verify no compression when acceptsGzip is false', () => { + await it('should skip compression when acceptsGzip is false', () => { const server = new TestableUIHttpServer(createHttpServerConfig()) const res = new MockServerResponse() @@ -200,7 +200,7 @@ await describe('UIHttpServer test suite', async () => { expect(res.headers['Content-Type']).toBe('application/json') }) - await it('should verify no compression for small responses', () => { + await it('should skip compression for small response payloads', () => { const server = new TestableUIHttpServer(createHttpServerConfig()) const res = new MockServerResponse() @@ -212,7 +212,7 @@ await describe('UIHttpServer test suite', async () => { expect(res.headers['Content-Type']).toBe('application/json') }) - await it('should verify no compression below threshold', () => { + await it('should skip compression when payload below threshold', () => { const server = new TestableUIHttpServer(createHttpServerConfig()) const res = new MockServerResponse() const smallPayload = { @@ -227,7 +227,7 @@ await describe('UIHttpServer test suite', async () => { expect(res.headers['Content-Encoding']).toBeUndefined() }) - await it('should verify compression headers for large responses', async () => { + await it('should set gzip Content-Encoding header for large responses', async () => { const server = new TestableUIHttpServer(createHttpServerConfig()) const res = new MockServerResponse() @@ -242,7 +242,7 @@ await describe('UIHttpServer test suite', async () => { expect(res.headers.Vary).toBe('Accept-Encoding') }) - await it('should verify compressed response decompresses to original payload', async () => { + await it('should decompress gzip response to original payload', async () => { const server = new TestableUIHttpServer(createHttpServerConfig()) const res = new MockServerResponse() const payload = createLargePayload() @@ -263,7 +263,7 @@ await describe('UIHttpServer test suite', async () => { expect(parsedBody.data).toBe(payload.data) }) - await it('should verify no compression when acceptsGzip context is missing', () => { + await it('should skip compression when acceptsGzip context missing', () => { const server = new TestableUIHttpServer(createHttpServerConfig()) const res = new MockServerResponse() @@ -274,7 +274,7 @@ await describe('UIHttpServer test suite', async () => { expect(res.headers['Content-Type']).toBe('application/json') }) - await it('should verify acceptsGzip context cleanup after response', async () => { + await it('should cleanup acceptsGzip context after response sent', async () => { const server = new TestableUIHttpServer(createHttpServerConfig()) const res = new MockServerResponse() diff --git a/tests/charging-station/ui-server/UIServerSecurity.test.ts b/tests/charging-station/ui-server/UIServerSecurity.test.ts index d13cedfb..3c851d04 100644 --- a/tests/charging-station/ui-server/UIServerSecurity.test.ts +++ b/tests/charging-station/ui-server/UIServerSecurity.test.ts @@ -20,39 +20,39 @@ const RATE_WINDOW_EXPIRY_DELAY_MS = 110 await describe('UIServerSecurity test suite', async () => { await describe('isValidCredential()', async () => { - await it('should verify matching credentials return true', () => { + await it('should return true for matching credentials', () => { expect(isValidCredential('myPassword123', 'myPassword123')).toBe(true) }) - await it('should verify non-matching credentials return false', () => { + await it('should return false for non-matching credentials', () => { expect(isValidCredential('password1', 'password2')).toBe(false) }) - await it('should verify empty string credentials match', () => { + await it('should return true for empty string credentials', () => { expect(isValidCredential('', '')).toBe(true) }) - await it('should verify different length credentials return false', () => { + await it('should return false for different length credentials', () => { // cspell:disable-next-line expect(isValidCredential('short', 'verylongpassword')).toBe(false) }) }) await describe('createBodySizeLimiter()', async () => { - await it('should verify bytes under limit return true', () => { + await it('should return true when bytes under limit', () => { const limiter = createBodySizeLimiter(1000) expect(limiter(500)).toBe(true) }) - await it('should verify accumulated bytes exceeding limit return false', () => { + await it('should return false when accumulated bytes exceed limit', () => { const limiter = createBodySizeLimiter(1000) limiter(600) expect(limiter(500)).toBe(false) }) - await it('should verify exact limit boundary returns true', () => { + await it('should return true at exact limit boundary', () => { const limiter = createBodySizeLimiter(1000) expect(limiter(1000)).toBe(true) @@ -60,7 +60,7 @@ await describe('UIServerSecurity test suite', async () => { }) await describe('createRateLimiter()', async () => { - await it('should verify requests under limit are allowed', () => { + await it('should allow requests under rate limit', () => { const limiter = createRateLimiter(5, 1000) for (let i = 0; i < 5; i++) { @@ -68,7 +68,7 @@ await describe('UIServerSecurity test suite', async () => { } }) - await it('should verify requests exceeding limit are blocked', () => { + await it('should block requests exceeding rate limit', () => { const limiter = createRateLimiter(3, 1000) limiter('192.168.1.1') limiter('192.168.1.1') @@ -77,7 +77,7 @@ await describe('UIServerSecurity test suite', async () => { expect(limiter('192.168.1.1')).toBe(false) }) - await it('should verify window resets after time expires', async () => { + await it('should reset window after time expires', async () => { const limiter = createRateLimiter(2, 100) limiter('10.0.0.1') limiter('10.0.0.1') @@ -88,7 +88,7 @@ await describe('UIServerSecurity test suite', async () => { expect(limiter('10.0.0.1')).toBe(true) }) - await it('should verify new IPs rejected when at max tracked capacity', () => { + await it('should reject new IPs when at max tracked capacity', () => { const limiter = createRateLimiter(10, 60000, 3) expect(limiter('192.168.1.1')).toBe(true) @@ -97,7 +97,7 @@ await describe('UIServerSecurity test suite', async () => { expect(limiter('192.168.1.4')).toBe(false) }) - await it('should verify existing IPs still allowed when at capacity', () => { + await it('should allow existing IPs when at max capacity', () => { const limiter = createRateLimiter(10, 60000, 2) expect(limiter('192.168.1.1')).toBe(true) @@ -106,7 +106,7 @@ await describe('UIServerSecurity test suite', async () => { expect(limiter('192.168.1.2')).toBe(true) }) - await it('should verify expired entries cleanup when at capacity', async () => { + await it('should cleanup expired entries when at capacity', async () => { const limiter = createRateLimiter(10, 50, 2) expect(limiter('192.168.1.1')).toBe(true) expect(limiter('192.168.1.2')).toBe(true) @@ -118,23 +118,23 @@ await describe('UIServerSecurity test suite', async () => { }) await describe('isValidNumberOfStations()', async () => { - await it('should verify valid number of stations returns true', () => { + await it('should return true for valid number within limit', () => { expect(isValidNumberOfStations(50, DEFAULT_MAX_STATIONS)).toBe(true) }) - await it('should verify exceeding max stations returns false', () => { + await it('should return false when exceeding max stations', () => { expect(isValidNumberOfStations(150, DEFAULT_MAX_STATIONS)).toBe(false) }) - await it('should verify zero stations returns false', () => { + await it('should return false for zero stations', () => { expect(isValidNumberOfStations(0, DEFAULT_MAX_STATIONS)).toBe(false) }) - await it('should verify negative stations returns false', () => { + await it('should return false for negative stations', () => { expect(isValidNumberOfStations(-5, DEFAULT_MAX_STATIONS)).toBe(false) }) - await it('should verify exact max stations boundary returns true', () => { + await it('should return true at exact max stations boundary', () => { expect(isValidNumberOfStations(DEFAULT_MAX_STATIONS, DEFAULT_MAX_STATIONS)).toBe(true) }) }) diff --git a/tests/charging-station/ui-server/UIWebSocketServer.test.ts b/tests/charging-station/ui-server/UIWebSocketServer.test.ts index 0d949e26..3f546604 100644 --- a/tests/charging-station/ui-server/UIWebSocketServer.test.ts +++ b/tests/charging-station/ui-server/UIWebSocketServer.test.ts @@ -35,7 +35,7 @@ class TestableUIWebSocketServer extends UIWebSocketServer { } await describe('UIWebSocketServer test suite', async () => { - await it('should verify sendResponse() deletes handler after sending', () => { + await it('should delete response handler after successful send', () => { const config = createMockUIServerConfiguration() const server = new TestableUIWebSocketServer(config) const ws = new MockWebSocket() @@ -49,7 +49,7 @@ await describe('UIWebSocketServer test suite', async () => { expect(ws.sentMessages.length).toBe(1) }) - await it('should verify sendResponse() logs error when handler not found', () => { + await it('should log error when response handler not found', () => { const config = createMockUIServerConfiguration() const server = new TestableUIWebSocketServer(config) @@ -58,7 +58,7 @@ await describe('UIWebSocketServer test suite', async () => { expect(server.hasResponseHandler(TEST_UUID)).toBe(false) }) - await it('should verify sendResponse() deletes handler when WebSocket not open', () => { + await it('should delete handler when WebSocket not in OPEN state', () => { const config = createMockUIServerConfiguration() const server = new TestableUIWebSocketServer(config) const ws = new MockWebSocket() @@ -71,7 +71,7 @@ await describe('UIWebSocketServer test suite', async () => { expect(ws.sentMessages.length).toBe(0) }) - await it('should verify sendResponse() handles send errors gracefully', () => { + await it('should handle send errors gracefully without throwing', () => { const config = createMockUIServerConfiguration() const server = new TestableUIWebSocketServer(config) const ws = new MockWebSocket() @@ -86,7 +86,7 @@ await describe('UIWebSocketServer test suite', async () => { expect(server.hasResponseHandler(TEST_UUID)).toBe(false) }) - await it('should verify broadcast handler persistence (issue #1642)', 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() @@ -108,7 +108,7 @@ await describe('UIWebSocketServer test suite', async () => { expect(server.hasResponseHandler(TEST_UUID)).toBe(false) }) - await it('should verify non-broadcast handler immediate deletion', async () => { + await it('should delete non-broadcast handler immediately after response', async () => { const config = createMockUIServerConfiguration() const server = new TestableUIWebSocketServer(config) const mockService = new MockUIServiceNonBroadcast() @@ -127,7 +127,7 @@ await describe('UIWebSocketServer test suite', async () => { expect(server.hasResponseHandler(TEST_UUID)).toBe(false) }) - await it('should verify error handler cleanup', async () => { + await it('should preserve handler when service throws error', async () => { const config = createMockUIServerConfiguration() const server = new TestableUIWebSocketServer(config) const mockService = new MockUIServiceError() @@ -145,7 +145,7 @@ await describe('UIWebSocketServer test suite', async () => { expect(server.getResponseHandlersSize()).toBe(1) }) - await it('should verify response handlers cleanup', () => { + await it('should clean up response handlers after each response', () => { const config = createMockUIServerConfiguration() const server = new TestableUIWebSocketServer(config) const ws1 = new MockWebSocket() @@ -163,7 +163,7 @@ await describe('UIWebSocketServer test suite', async () => { expect(server.getResponseHandlersSize()).toBe(0) }) - await it('should verify handlers cleared on server stop', () => { + await it('should clear all handlers on server stop', () => { const config = createMockUIServerConfiguration() const server = new TestableUIWebSocketServer(config) const ws = new MockWebSocket() @@ -176,14 +176,14 @@ await describe('UIWebSocketServer test suite', async () => { expect(server.getResponseHandlersSize()).toBe(0) }) - await it('should verify valid WebSocket configuration', () => { + await it('should create server with valid WebSocket configuration', () => { const config = createMockUIServerConfiguration() const server = new UIWebSocketServer(config) expect(server).toBeDefined() }) - await it('should verify WebSocket server with custom config', () => { + await it('should create server with custom host and port', () => { const config = createMockUIServerConfiguration({ options: { host: 'localhost', diff --git a/tests/charging-station/ui-server/ui-services/AbstractUIService.test.ts b/tests/charging-station/ui-server/ui-services/AbstractUIService.test.ts index 78b0da79..58081dd8 100644 --- a/tests/charging-station/ui-server/ui-services/AbstractUIService.test.ts +++ b/tests/charging-station/ui-server/ui-services/AbstractUIService.test.ts @@ -27,7 +27,7 @@ class TestableUIWebSocketServer extends UIWebSocketServer { } await describe('AbstractUIService test suite', async () => { - await it('should verify sendResponse checks for response handler existence', () => { + await it('should check response handler existence before sending', () => { const config = createMockUIServerConfiguration() const server = new TestableUIWebSocketServer(config) @@ -43,7 +43,7 @@ await describe('AbstractUIService test suite', async () => { expect(server.hasResponseHandler(TEST_UUID)).toBe(false) }) - await it('should verify requestHandler returns response for LIST_CHARGING_STATIONS', async () => { + await it('should return charging stations list for LIST_CHARGING_STATIONS', async () => { const config = createMockUIServerConfiguration() const server = new TestableUIWebSocketServer(config) @@ -70,7 +70,7 @@ await describe('AbstractUIService test suite', async () => { } }) - await it('should verify requestHandler returns response for LIST_TEMPLATES', async () => { + await it('should return templates list for LIST_TEMPLATES', async () => { const config = createMockUIServerConfiguration() const server = new TestableUIWebSocketServer(config) @@ -99,7 +99,7 @@ await describe('AbstractUIService test suite', async () => { } }) - await it('should verify requestHandler returns error response for unknown procedure', async () => { + await it('should return failure response for unknown procedure', async () => { const config = createMockUIServerConfiguration() const server = new TestableUIWebSocketServer(config) @@ -123,7 +123,7 @@ await describe('AbstractUIService test suite', async () => { } }) - await it('should verify broadcast channel request tracking initialization', () => { + await it('should initialize broadcast channel expected responses to 0', () => { const config = createMockUIServerConfiguration() const server = new TestableUIWebSocketServer(config) @@ -138,7 +138,7 @@ await describe('AbstractUIService test suite', async () => { } }) - await it('should verify broadcast channel cleanup on stop', () => { + await it('should cleanup broadcast channel on service stop', () => { const config = createMockUIServerConfiguration() const server = new TestableUIWebSocketServer(config) @@ -153,7 +153,7 @@ await describe('AbstractUIService test suite', async () => { } }) - await it('should verify requestHandler handles errors gracefully', async () => { + await it('should return failure response when request handler throws', async () => { const config = createMockUIServerConfiguration() const server = new TestableUIWebSocketServer(config) @@ -176,7 +176,7 @@ await describe('AbstractUIService test suite', async () => { } }) - await it('should verify UI service initialization', () => { + await it('should initialize UI service successfully', () => { const config = createMockUIServerConfiguration() const server = new TestableUIWebSocketServer(config) @@ -190,7 +190,7 @@ await describe('AbstractUIService test suite', async () => { } }) - await it('should verify multiple service registrations', () => { + await it('should prevent duplicate service registrations', () => { const config = createMockUIServerConfiguration() const server = new TestableUIWebSocketServer(config) diff --git a/tests/exception/BaseError.test.ts b/tests/exception/BaseError.test.ts index 8349fa70..1b505abb 100644 --- a/tests/exception/BaseError.test.ts +++ b/tests/exception/BaseError.test.ts @@ -8,7 +8,7 @@ import { describe, it } from 'node:test' import { BaseError } from '../../src/exception/BaseError.js' await describe('BaseError test suite', async () => { - await it('should verify that BaseError can be instantiated', () => { + await it('should create instance with default values', () => { const baseError = new BaseError() expect(baseError).toBeInstanceOf(BaseError) expect(baseError.name).toBe('BaseError') @@ -19,7 +19,7 @@ await describe('BaseError test suite', async () => { expect(baseError.date).toBeInstanceOf(Date) }) - await it('should verify that BaseError can be instantiated with a message', () => { + await it('should create instance with custom message', () => { const baseError = new BaseError('Test message') expect(baseError).toBeInstanceOf(BaseError) expect(baseError.message).toBe('Test message') diff --git a/tests/exception/OCPPError.test.ts b/tests/exception/OCPPError.test.ts index d83b18b6..fef65af8 100644 --- a/tests/exception/OCPPError.test.ts +++ b/tests/exception/OCPPError.test.ts @@ -10,7 +10,7 @@ import { ErrorType } from '../../src/types/index.js' import { Constants } from '../../src/utils/Constants.js' await describe('OCPPError test suite', async () => { - await it('should verify that OCPPError can be instantiated', () => { + await it('should create instance with error code and default values', () => { const ocppError = new OCPPError(ErrorType.GENERIC_ERROR, '') expect(ocppError).toBeInstanceOf(OCPPError) expect(ocppError.name).toBe('OCPPError') diff --git a/tests/helpers/TestLifecycleHelpers.ts b/tests/helpers/TestLifecycleHelpers.ts index 3919b73e..075e0960 100644 --- a/tests/helpers/TestLifecycleHelpers.ts +++ b/tests/helpers/TestLifecycleHelpers.ts @@ -39,6 +39,23 @@ import { } from '../charging-station/helpers/StationHelpers.js' import { MockIdTagsCache, MockSharedLRUCache } from '../charging-station/mocks/MockCaches.js' +/** + * Result type for console mocks + */ +export interface ConsoleMockResult { + errorMock: { mock: { calls: unknown[][] } } + infoMock: { mock: { calls: unknown[][] } } + warnMock: { mock: { calls: unknown[][] } } +} + +/** + * Result type for logger mocks + */ +export interface LoggerMockResult { + errorMock: { mock: { calls: unknown[][] } } + warnMock: { mock: { calls: unknown[][] } } +} + /** * Timer APIs that can be mocked in tests */ @@ -54,6 +71,18 @@ export interface TimerHelperOptions { apis?: MockableTimerAPI[] } +/** + * Mock context type for Node.js test module + */ +interface MockContext { + mock: { + method: ( + object: object, + methodName: string + ) => { mock: { calls: unknown[][] } } + } +} + /** * Helper class for managing mock charging stations in tests * @@ -288,6 +317,81 @@ export function clearConnectorTransaction (station: ChargingStation, connectorId } } +/** + * Factory for creating centralized console mocks + * + * Reduces boilerplate in tests that need to mock console methods. + * @param t - Test context from node:test + * @param options - Which console methods to mock + * @param options.error - Whether to mock console.error + * @param options.info - Whether to mock console.info + * @param options.warn - Whether to mock console.warn + * @returns Object with console mock references + * @example + * ```typescript + * import { createConsoleMocks } from '../helpers/TestLifecycleHelpers.js' + * + * await it('should log to console', t => { + * const { errorMock, warnMock } = createConsoleMocks(t, { error: true, warn: true }) + * + * // ... test code ... + * + * expect(warnMock.mock.calls.length).toBe(1) + * }) + * ``` + */ +export function createConsoleMocks ( + t: MockContext, + options: { error?: boolean; info?: boolean; warn?: boolean } = {} +): Partial { + const result: Partial = {} + + if (options.error === true) { + result.errorMock = t.mock.method(console, 'error') + } + if (options.warn === true) { + result.warnMock = t.mock.method(console, 'warn') + } + if (options.info === true) { + result.infoMock = t.mock.method(console, 'info') + } + + return result +} + +/** + * Factory for creating centralized logger mocks + * + * Reduces boilerplate in tests that need to mock logger methods. + * @param t - Test context from node:test + * @param logger - Logger instance to mock (must have error and warn methods) + * @param logger.error - Logger error method + * @param logger.warn - Logger warn method + * @returns Object with warn and error mock references + * @example + * ```typescript + * import { createLoggerMocks } from '../helpers/TestLifecycleHelpers.js' + * import { logger } from '../../src/utils/Logger.js' + * + * await it('should handle errors', t => { + * const { warnMock, errorMock } = createLoggerMocks(t, logger) + * + * // ... test code ... + * + * expect(errorMock.mock.calls.length).toBe(1) + * }) + * ``` + */ +export function createLoggerMocks ( + t: MockContext, + logger: { error: unknown; warn: unknown } +): LoggerMockResult { + return { + errorMock: t.mock.method(logger, 'error'), + warnMock: t.mock.method(logger, 'warn'), + } +} + /** * Setup a connector with an active transaction * diff --git a/tests/types/ConfigurationData.test.ts b/tests/types/ConfigurationData.test.ts index a1651cc5..62ce324b 100644 --- a/tests/types/ConfigurationData.test.ts +++ b/tests/types/ConfigurationData.test.ts @@ -12,20 +12,20 @@ import { } from '../../src/types/ConfigurationData.js' await describe('ConfigurationData test suite', async () => { - await it('should verify ConfigurationSection enumeration', () => { + await it('should define ConfigurationSection enumeration values', () => { expect(ConfigurationSection.log).toBe('log') expect(ConfigurationSection.performanceStorage).toBe('performanceStorage') expect(ConfigurationSection.uiServer).toBe('uiServer') expect(ConfigurationSection.worker).toBe('worker') }) - await it('should verify SupervisionUrlDistribution enumeration', () => { + await it('should define SupervisionUrlDistribution enumeration values', () => { expect(SupervisionUrlDistribution.CHARGING_STATION_AFFINITY).toBe('charging-station-affinity') expect(SupervisionUrlDistribution.RANDOM).toBe('random') expect(SupervisionUrlDistribution.ROUND_ROBIN).toBe('round-robin') }) - await it('should verify ApplicationProtocolVersion enumeration', () => { + await it('should define ApplicationProtocolVersion enumeration values', () => { expect(ApplicationProtocolVersion.VERSION_11).toBe('1.1') expect(ApplicationProtocolVersion.VERSION_20).toBe('2.0') }) diff --git a/tests/utils/AsyncLock.test.ts b/tests/utils/AsyncLock.test.ts index 1ec5edd1..9f91d5ff 100644 --- a/tests/utils/AsyncLock.test.ts +++ b/tests/utils/AsyncLock.test.ts @@ -9,7 +9,7 @@ import { describe, it } from 'node:test' import { AsyncLock, AsyncLockType } from '../../src/utils/AsyncLock.js' await describe('AsyncLock test suite', async () => { - await it('should verify runExclusive() on sync fn', () => { + await it('should run synchronous functions exclusively in sequence', () => { const runs = 10 const executed: number[] = [] let count = 0 @@ -26,7 +26,7 @@ await describe('AsyncLock test suite', async () => { } }) - await it('should verify runExclusive() on async fn', () => { + await it('should run asynchronous functions exclusively in sequence', () => { const runs = 10 const executed: number[] = [] let count = 0 diff --git a/tests/utils/ConfigurationUtils.test.ts b/tests/utils/ConfigurationUtils.test.ts index 9d49f962..57529008 100644 --- a/tests/utils/ConfigurationUtils.test.ts +++ b/tests/utils/ConfigurationUtils.test.ts @@ -3,7 +3,7 @@ * @description Unit tests for configuration utility functions */ import { expect } from '@std/expect' -import { describe, it } from 'node:test' +import { afterEach, describe, it } from 'node:test' import { FileType, StorageType } from '../../src/types/index.js' import { @@ -13,19 +13,24 @@ import { handleFileException, logPrefix, } from '../../src/utils/ConfigurationUtils.js' +import { standardCleanup } from '../helpers/TestLifecycleHelpers.js' await describe('ConfigurationUtils test suite', async () => { - await it('should verify logPrefix()', () => { + afterEach(() => { + standardCleanup() + }) + + await it('should return log prefix with simulator configuration', () => { expect(logPrefix()).toContain(' Simulator configuration |') }) - await it('should verify buildPerformanceUriFilePath()', () => { + await it('should build file URI path for performance storage', () => { const result = buildPerformanceUriFilePath('test.json') expect(result).toContain('test.json') expect(result).toMatch(/^file:\/\/.*test\.json$/) }) - await it('should verify getDefaultPerformanceStorageUri()', () => { + await it('should return appropriate URI for storage types', () => { // Test JSON_FILE storage type const jsonUri = getDefaultPerformanceStorageUri(StorageType.JSON_FILE) expect(jsonUri).toMatch(/^file:\/\/.*\.json$/) @@ -42,7 +47,7 @@ await describe('ConfigurationUtils test suite', async () => { }).toThrow(Error) }) - await it('should verify handleFileException()', t => { + await it('should throw and log error for file exceptions', t => { const mockConsoleError = t.mock.method(console, 'error') const error = new Error() as NodeJS.ErrnoException error.code = 'ENOENT' @@ -52,7 +57,7 @@ await describe('ConfigurationUtils test suite', async () => { expect(mockConsoleError.mock.calls.length).toBe(1) }) - await it('should verify checkWorkerElementsPerWorker()', () => { + await it('should validate worker elements per worker configuration', () => { // These calls should not throw exceptions expect(() => { checkWorkerElementsPerWorker(undefined) diff --git a/tests/utils/ElectricUtils.test.ts b/tests/utils/ElectricUtils.test.ts index 1b1377bb..e61c09d0 100644 --- a/tests/utils/ElectricUtils.test.ts +++ b/tests/utils/ElectricUtils.test.ts @@ -8,25 +8,25 @@ import { describe, it } from 'node:test' import { ACElectricUtils, DCElectricUtils } from '../../src/utils/ElectricUtils.js' await describe('ElectricUtils test suite', async () => { - await it('should verify DCElectricUtils.power()', () => { + await it('should calculate DC power from voltage and current', () => { expect(DCElectricUtils.power(230, 1)).toBe(230) }) - await it('should verify DCElectricUtils.amperage()', () => { + await it('should calculate DC amperage from power and voltage', () => { expect(DCElectricUtils.amperage(1, 230)).toBe(0) }) - await it('should verify ACElectricUtils.powerTotal()', () => { + await it('should calculate total AC power for all phases', () => { expect(ACElectricUtils.powerTotal(3, 230, 1)).toBe(690) }) - await it('should verify ACElectricUtils.powerPerPhase()', () => { + await it('should calculate AC power per phase', () => { expect(ACElectricUtils.powerPerPhase(230, 1)).toBe(230) }) - await it('should verify ACElectricUtils.amperageTotal()', () => { + await it('should calculate total AC amperage for all phases', () => { expect(ACElectricUtils.amperageTotal(3, 1)).toBe(3) }) - await it('should verify ACElectricUtils.amperageTotalFromPower()', () => { + await it('should calculate total AC amperage from power and voltage', () => { expect(ACElectricUtils.amperageTotalFromPower(690, 230)).toBe(3) }) - await it('should verify ACElectricUtils.amperagePerPhaseFromPower()', () => { + await it('should calculate AC amperage per phase from power', () => { expect(ACElectricUtils.amperagePerPhaseFromPower(3, 690, 230)).toBe(1) }) }) diff --git a/tests/utils/ErrorUtils.test.ts b/tests/utils/ErrorUtils.test.ts index 2a0ed0b7..e7539d8a 100644 --- a/tests/utils/ErrorUtils.test.ts +++ b/tests/utils/ErrorUtils.test.ts @@ -3,7 +3,7 @@ * @description Unit tests for error handling utilities */ import { expect } from '@std/expect' -import { describe, it } from 'node:test' +import { afterEach, describe, it } from 'node:test' import { FileType, @@ -19,11 +19,16 @@ import { } from '../../src/utils/ErrorUtils.js' import { logger } from '../../src/utils/Logger.js' import { createChargingStation } from '../ChargingStationFactory.js' +import { standardCleanup } from '../helpers/TestLifecycleHelpers.js' await describe('ErrorUtils test suite', async () => { const chargingStation = createChargingStation({ baseName: 'CS-TEST' }) - await it('should verify handleFileException()', t => { + afterEach(() => { + standardCleanup() + }) + + await it('should throw or warn based on error code and options', t => { const consoleWarnMock = t.mock.method(console, 'warn') const consoleErrorMock = t.mock.method(console, 'error') const warnMock = t.mock.method(logger, 'warn') @@ -55,7 +60,7 @@ await describe('ErrorUtils test suite', async () => { expect(consoleErrorMock.mock.calls.length).toBe(1) }) - await it('should verify handleSendMessageError()', t => { + await it('should log error and optionally throw for send message errors', t => { const errorMock = t.mock.method(logger, 'error') const logPrefixMock = t.mock.method(chargingStation, 'logPrefix') const error = new Error() @@ -80,7 +85,7 @@ await describe('ErrorUtils test suite', async () => { expect(errorMock.mock.calls.length).toBe(2) }) - await it('should verify handleIncomingRequestError()', t => { + await it('should log error and return error response for incoming requests', t => { const errorMock = t.mock.method(logger, 'error') const logPrefixMock = t.mock.method(chargingStation, 'logPrefix') const error = new Error() diff --git a/tests/utils/StatisticUtils.test.ts b/tests/utils/StatisticUtils.test.ts index c2c7adc0..2cbfacc0 100644 --- a/tests/utils/StatisticUtils.test.ts +++ b/tests/utils/StatisticUtils.test.ts @@ -8,21 +8,21 @@ import { describe, it } from 'node:test' import { average, max, median, min, percentile, std } from '../../src/utils/StatisticUtils.js' await describe('StatisticUtils test suite', async () => { - await it('should verify average()', () => { + await it('should calculate arithmetic mean of array values', () => { expect(average([])).toBe(0) expect(average([0.08])).toBe(0.08) expect(average([0.25, 4.75, 3.05, 6.04, 1.01, 2.02, 5.03])).toBe(3.1642857142857146) expect(average([0.25, 4.75, 3.05, 6.04, 1.01, 2.02])).toBe(2.8533333333333335) }) - await it('should verify median()', () => { + await it('should calculate median value of array', () => { expect(median([])).toBe(0) expect(median([0.08])).toBe(0.08) expect(median([0.25, 4.75, 3.05, 6.04, 1.01, 2.02, 5.03])).toBe(3.05) expect(median([0.25, 4.75, 3.05, 6.04, 1.01, 2.02])).toBe(2.535) }) - await it('should verify min()', () => { + await it('should return minimum value from arguments', () => { expect(min()).toBe(Number.POSITIVE_INFINITY) expect(min(0, 1)).toBe(0) expect(min(1, 0)).toBe(0) @@ -30,7 +30,7 @@ await describe('StatisticUtils test suite', async () => { expect(min(-1, 0)).toBe(-1) }) - await it('should verify max()', () => { + await it('should return maximum value from arguments', () => { expect(max()).toBe(Number.NEGATIVE_INFINITY) expect(max(0, 1)).toBe(1) expect(max(1, 0)).toBe(1) @@ -38,7 +38,7 @@ await describe('StatisticUtils test suite', async () => { expect(max(-1, 0)).toBe(0) }) - await it('should verify percentile()', () => { + await it('should calculate nth percentile of array', () => { expect(percentile([], 25)).toBe(0) expect(percentile([0.08], 50)).toBe(0.08) const array0 = [0.25, 4.75, 3.05, 6.04, 1.01, 2.02, 5.03] @@ -51,7 +51,7 @@ await describe('StatisticUtils test suite', async () => { expect(percentile(array0, 100)).toBe(6.04) }) - await it('should verify std()', () => { + await it('should calculate standard deviation of array', () => { expect(std([0.25, 4.75, 3.05, 6.04, 1.01, 2.02, 5.03])).toBe(2.1879050645374383) }) }) diff --git a/tests/utils/Utils.test.ts b/tests/utils/Utils.test.ts index 8b3db1a4..69da07dd 100644 --- a/tests/utils/Utils.test.ts +++ b/tests/utils/Utils.test.ts @@ -49,7 +49,7 @@ await describe('Utils test suite', async () => { afterEach(() => { standardCleanup() }) - await it('should verify generateUUID()/validateUUID()', () => { + await it('should generate valid UUIDs and validate them correctly', () => { const uuid = generateUUID() expect(uuid).toBeDefined() expect(uuid.length).toEqual(36) @@ -70,7 +70,7 @@ await describe('Utils test suite', async () => { expect(validateUUID(true)).toBe(false) }) - await it('should verify validateIdentifierString()', () => { + await it('should validate identifier strings within length constraints', () => { expect(validateIdentifierString('550e8400-e29b-41d4-a716-446655440000', 36)).toBe(true) expect(validateIdentifierString('CSMS-TXN-12345', 36)).toBe(true) expect(validateIdentifierString('a', 36)).toBe(true) @@ -85,7 +85,7 @@ await describe('Utils test suite', async () => { expect(validateIdentifierString('valid', 4)).toBe(false) }) - await it('should verify sleep()', async t => { + await it('should sleep for specified milliseconds using timer mock', async t => { /** * Timer mock pattern for testing asynchronous timer-based operations. * Uses Node.js test module's built-in timer mocking API. @@ -129,21 +129,21 @@ await describe('Utils test suite', async () => { } }) - await it('should verify formatDurationMilliSeconds()', () => { + await it('should format milliseconds duration into human readable string', () => { expect(formatDurationMilliSeconds(0)).toBe('0 seconds') expect(formatDurationMilliSeconds(900)).toBe('0 seconds') expect(formatDurationMilliSeconds(1000)).toBe('1 second') expect(formatDurationMilliSeconds(hoursToMilliseconds(4380))).toBe('182 days 12 hours') }) - await it('should verify formatDurationSeconds()', () => { + await it('should format seconds duration into human readable string', () => { expect(formatDurationSeconds(0)).toBe('0 seconds') expect(formatDurationSeconds(0.9)).toBe('0 seconds') expect(formatDurationSeconds(1)).toBe('1 second') expect(formatDurationSeconds(hoursToSeconds(4380))).toBe('182 days 12 hours') }) - await it('should verify isValidDate()', () => { + await it('should validate date objects and timestamps correctly', () => { expect(isValidDate(undefined)).toBe(false) expect(isValidDate(-1)).toBe(true) expect(isValidDate(0)).toBe(true) @@ -153,7 +153,7 @@ await describe('Utils test suite', async () => { expect(isValidDate(new Date())).toBe(true) }) - await it('should verify convertToDate()', () => { + await it('should convert various input types to Date objects', () => { expect(convertToDate(undefined)).toBe(undefined) expect(convertToDate(null)).toBe(undefined) expect(() => convertToDate('')).toThrow(new Error("Cannot convert to date: ''")) @@ -169,7 +169,7 @@ await describe('Utils test suite', async () => { expect(date).toStrictEqual(new Date(dateStr)) }) - await it('should verify convertToInt()', () => { + await it('should convert various input types to integers', () => { expect(convertToInt(undefined)).toBe(0) expect(convertToInt(null)).toBe(0) expect(convertToInt(0)).toBe(0) @@ -190,7 +190,7 @@ await describe('Utils test suite', async () => { }).toThrow("Cannot convert to integer: 'NaN'") }) - await it('should verify convertToFloat()', () => { + await it('should convert various input types to floats', () => { expect(convertToFloat(undefined)).toBe(0) expect(convertToFloat(null)).toBe(0) expect(convertToFloat(0)).toBe(0) @@ -211,7 +211,7 @@ await describe('Utils test suite', async () => { }).toThrow("Cannot convert to float: 'NaN'") }) - await it('should verify convertToBoolean()', () => { + await it('should convert various input types to booleans', () => { expect(convertToBoolean(undefined)).toBe(false) expect(convertToBoolean(null)).toBe(false) expect(convertToBoolean('true')).toBe(true) @@ -228,14 +228,14 @@ await describe('Utils test suite', async () => { expect(convertToBoolean('NoNBoolean')).toBe(false) }) - await it('should verify secureRandom()', () => { + await it('should generate cryptographically secure random numbers between 0 and 1', () => { const random = secureRandom() expect(typeof random === 'number').toBe(true) expect(random).toBeGreaterThanOrEqual(0) expect(random).toBeLessThan(1) }) - await it('should verify roundTo()', () => { + await it('should round numbers to specified decimal places correctly', () => { expect(roundTo(0, 2)).toBe(0) expect(roundTo(0.5, 0)).toBe(1) expect(roundTo(0.5, 2)).toBe(0.5) @@ -250,7 +250,7 @@ await describe('Utils test suite', async () => { expect(roundTo(-5.015, 2)).toBe(-5.02) }) - await it('should verify getRandomFloat()', () => { + await it('should generate random floats within specified range', () => { let randomFloat = getRandomFloat() expect(typeof randomFloat === 'number').toBe(true) expect(randomFloat).toBeGreaterThanOrEqual(0) @@ -265,7 +265,7 @@ await describe('Utils test suite', async () => { expect(randomFloat).toBeLessThanOrEqual(0) }) - await it('should verify extractTimeSeriesValues()', () => { + await it('should extract numeric values from timestamped circular buffer', () => { expect( extractTimeSeriesValues( new CircularBuffer(Array, Constants.DEFAULT_CIRCULAR_BUFFER_CAPACITY) @@ -281,7 +281,7 @@ await describe('Utils test suite', async () => { expect(extractTimeSeriesValues(circularBuffer)).toEqual([1.1, 2.2, 3.3]) }) - await it('should verify isAsyncFunction()', () => { + await it('should correctly identify async functions from other types', () => { expect(isAsyncFunction(null)).toBe(false) expect(isAsyncFunction(undefined)).toBe(false) expect(isAsyncFunction(true)).toBe(false) @@ -356,7 +356,7 @@ await describe('Utils test suite', async () => { expect(isAsyncFunction(TestClass.testStaticAsync)).toBe(true) }) - await it('should verify clone()', () => { + await it('should deep clone objects, arrays, dates, maps and sets', () => { const obj = { 1: 1 } expect(clone(obj)).toStrictEqual(obj) expect(clone(obj) === obj).toBe(false) @@ -388,7 +388,7 @@ await describe('Utils test suite', async () => { expect(() => clone(weakSet)).toThrow(new Error('# could not be cloned.')) }) - await it('should verify once()', () => { + await it('should execute function only once regardless of call count', () => { let called = 0 const fn = (): number => ++called const onceFn = once(fn) @@ -403,7 +403,7 @@ await describe('Utils test suite', async () => { expect(result3).toBe(1) }) - await it('should verify has()', () => { + await it('should check if property exists in object using has()', () => { expect(has('', 'test')).toBe(false) expect(has('test', '')).toBe(false) expect(has('test', 'test')).toBe(false) @@ -421,7 +421,7 @@ await describe('Utils test suite', async () => { expect(has(2, { 1: '1' })).toBe(false) }) - await it('should verify isEmpty()', () => { + await it('should detect empty strings, objects, arrays, maps and sets', () => { expect(isEmpty('')).toBe(true) expect(isEmpty(' ')).toBe(true) expect(isEmpty(' ')).toBe(true) @@ -439,7 +439,7 @@ await describe('Utils test suite', async () => { expect(isEmpty(new WeakSet())).toBe(false) }) - await it('should verify isNotEmptyString()', () => { + await it('should detect non-empty strings correctly', () => { expect(isNotEmptyString('')).toBe(false) expect(isNotEmptyString(' ')).toBe(false) expect(isNotEmptyString(' ')).toBe(false) @@ -457,7 +457,7 @@ await describe('Utils test suite', async () => { expect(isNotEmptyString(new WeakSet())).toBe(false) }) - await it('should verify isNotEmptyArray()', () => { + await it('should detect non-empty arrays correctly', () => { expect(isNotEmptyArray([])).toBe(false) expect(isNotEmptyArray([1, 2])).toBe(true) expect(isNotEmptyArray(['1', '2'])).toBe(true) @@ -473,13 +473,13 @@ await describe('Utils test suite', async () => { expect(isNotEmptyArray(new WeakSet())).toBe(false) }) - await it('should verify insertAt()', () => { + await it('should insert substring at specified index position', () => { expect(insertAt('test', 'ing', 'test'.length)).toBe('testing') // eslint-disable-next-line @cspell/spellchecker expect(insertAt('test', 'ing', 2)).toBe('teingst') }) - await it('should verify convertToIntOrNaN()', () => { + await it('should convert to integer or return NaN for invalid input', () => { expect(convertToIntOrNaN(undefined)).toBe(0) expect(convertToIntOrNaN(null)).toBe(0) expect(convertToIntOrNaN('0')).toBe(0) @@ -490,7 +490,7 @@ await describe('Utils test suite', async () => { expect(Number.isNaN(convertToIntOrNaN('abc'))).toBe(true) }) - await it('should verify isArraySorted()', () => { + await it('should check if array is sorted according to comparator', () => { expect(isArraySorted([], (a, b) => a - b)).toBe(true) expect(isArraySorted([1], (a, b) => a - b)).toBe(true) expect(isArraySorted([1, 2, 3, 4, 5], (a, b) => a - b)).toBe(true) @@ -498,7 +498,7 @@ await describe('Utils test suite', async () => { expect(isArraySorted([2, 1, 3, 4, 5], (a, b) => a - b)).toBe(false) }) - await it('should verify clampToSafeTimerValue()', () => { + await it('should clamp values to safe timer range (0 to MAX_SETINTERVAL_DELAY)', () => { expect(clampToSafeTimerValue(0)).toBe(0) expect(clampToSafeTimerValue(1000)).toBe(1000) expect(clampToSafeTimerValue(Constants.MAX_SETINTERVAL_DELAY)).toBe( @@ -516,7 +516,7 @@ await describe('Utils test suite', async () => { // Exponential Backoff Algorithm Tests (WebSocket Reconnection) // ------------------------------------------------------------------------- - await it('should verify exponentialDelay() with default parameters', () => { + await it('should calculate exponential delay with default parameters', () => { // Formula: delay = 2^retryNumber * delayFactor + (0-20% random jitter) // With default delayFactor = 100ms @@ -541,7 +541,7 @@ await describe('Utils test suite', async () => { expect(delay3).toBeLessThanOrEqual(960) // 800 + 20% max jitter }) - await it('should verify exponentialDelay() with custom delayFactor', () => { + await it('should calculate exponential delay with custom delay factor', () => { // Custom delayFactor = 50ms const delay0 = exponentialDelay(0, 50) expect(delay0).toBeGreaterThanOrEqual(50) @@ -557,7 +557,7 @@ await describe('Utils test suite', async () => { expect(delay2).toBeLessThanOrEqual(960) }) - await it('should verify exponentialDelay() exponential growth pattern', () => { + await it('should follow 2^n exponential growth pattern', () => { // Verify that delays follow 2^n exponential growth pattern const delayFactor = 100 @@ -577,7 +577,7 @@ await describe('Utils test suite', async () => { } }) - await it('should verify exponentialDelay() includes random jitter', () => { + await it('should include random jitter in exponential delay', () => { // Run multiple times to verify jitter produces different values const delays = new Set() const retryNumber = 3 @@ -594,7 +594,7 @@ await describe('Utils test suite', async () => { expect(delays.size).toBeGreaterThan(1) }) - await it('should verify exponentialDelay() jitter is within 0-20% range', () => { + await it('should keep jitter within 0-20% range of base delay', () => { // For a given retry, jitter should add 0-20% of base delay const retryNumber = 4 const delayFactor = 100 @@ -611,7 +611,7 @@ await describe('Utils test suite', async () => { } }) - await it('should verify exponentialDelay() handles edge cases', () => { + await it('should handle edge cases (default retry, large retry, small factor)', () => { // Default retryNumber (0) const defaultRetry = exponentialDelay() expect(defaultRetry).toBeGreaterThanOrEqual(100) // 2^0 * 100 @@ -629,7 +629,7 @@ await describe('Utils test suite', async () => { expect(smallFactor).toBeLessThan(5) // 4 + 20% }) - await it('should verify exponentialDelay() for WebSocket reconnection scenarios', () => { + await it('should calculate appropriate delays for WebSocket reconnection scenarios', () => { // Simulate typical WebSocket reconnection delay sequence const delayFactor = 100 // Default used in ChargingStation.reconnect() diff --git a/tests/worker/WorkerUtils.test.ts b/tests/worker/WorkerUtils.test.ts index 39e416d8..0730797f 100644 --- a/tests/worker/WorkerUtils.test.ts +++ b/tests/worker/WorkerUtils.test.ts @@ -3,7 +3,7 @@ * @description Unit tests for worker process utility functions */ import { expect } from '@std/expect' -import { describe, it } from 'node:test' +import { afterEach, describe, it } from 'node:test' import { WorkerProcessType } from '../../src/worker/WorkerTypes.js' import { @@ -13,9 +13,14 @@ import { randomizeDelay, sleep, } from '../../src/worker/WorkerUtils.js' +import { standardCleanup } from '../helpers/TestLifecycleHelpers.js' await describe('WorkerUtils test suite', async () => { - await it('should verify checkWorkerProcessType()', () => { + afterEach(() => { + standardCleanup() + }) + + await it('should validate worker process types correctly', () => { // Valid worker process types should not throw expect(() => { checkWorkerProcessType(WorkerProcessType.dynamicPool) @@ -33,7 +38,7 @@ await describe('WorkerUtils test suite', async () => { }).toThrow(SyntaxError) }) - await it('should verify sleep()', async t => { + await it('should return timeout object after specified delay', async t => { t.mock.timers.enable({ apis: ['setTimeout'] }) try { const delay = 10 // 10ms for fast test execution @@ -52,7 +57,7 @@ await describe('WorkerUtils test suite', async () => { } }) - await it('should verify defaultExitHandler()', t => { + await it('should log info for success/termination codes, error for other codes', t => { const mockConsoleInfo = t.mock.method(console, 'info') const mockConsoleError = t.mock.method(console, 'error') @@ -85,7 +90,7 @@ await describe('WorkerUtils test suite', async () => { expect(mockConsoleError.mock.calls.length).toBe(1) }) - await it('should verify defaultErrorHandler()', t => { + await it('should log error with error details', t => { const mockConsoleError = t.mock.method(console, 'error') const testError = new Error('Test error message') @@ -99,7 +104,7 @@ await describe('WorkerUtils test suite', async () => { expect(mockConsoleError.mock.calls.length).toBe(2) }) - await it('should verify randomizeDelay()', () => { + await it('should randomize delay within ±20% tolerance', () => { const baseDelay = 1000 const tolerance = baseDelay * 0.2 // 20% tolerance as per implementation