]> Piment Noir Git Repositories - e-mobility-charging-stations-simulator.git/commitdiff
fix(tests): address audit findings — assertion consistency, JSDoc, DRY, try/finally
authorJérôme Benoit <jerome.benoit@sap.com>
Tue, 3 Mar 2026 20:26:08 +0000 (21:26 +0100)
committerJérôme Benoit <jerome.benoit@sap.com>
Tue, 3 Mar 2026 20:29:29 +0000 (21:29 +0100)
- Replace expect(a === b).toBe(false) with expect(a).not.toBe(b) (IdTagsCache)
- Add explicit assertions to smoke tests (SimpleHandlers)
- Wrap state injection in try/finally (Configuration)
- Extract createStationWithRequestHandler helper, use mock.method() (connectorStatus)
- Fill empty JSDoc @param descriptions across 5 files
- Rename makeStationStub → makeStationMock, merge duplicate import (pure)
- Fix misleading test name 'is empty' → 'is null' (validation)
- Extract getConnectorStatus/getHandleStartTransactionResponse helpers (ATG)
- Fix perfectionist/sort-modules and sort-imports ordering

tests/charging-station/AutomaticTransactionGenerator.test.ts
tests/charging-station/IdTagsCache.test.ts
tests/charging-station/SharedLRUCache.test.ts
tests/charging-station/ocpp/2.0/OCPP20ResponseService-SimpleHandlers.test.ts
tests/charging-station/ocpp/OCPPServiceUtils-authorization.test.ts
tests/charging-station/ocpp/OCPPServiceUtils-connectorStatus.test.ts
tests/charging-station/ocpp/OCPPServiceUtils-pure.test.ts
tests/charging-station/ocpp/OCPPServiceUtils-validation.test.ts
tests/utils/Configuration.test.ts

index a8aaa0a9a1510a22ca1aa234a1188fabacbb8e82..b3bd6eacf2436baaf8f909d8a1b1b70770ca1aec 100644 (file)
@@ -24,9 +24,11 @@ import { BaseError } from '../../src/exception/index.js'
 import { AuthorizationStatus, type StartTransactionResponse } from '../../src/types/index.js'
 import { createMockChargingStation, standardCleanup } from './ChargingStationTestUtils.js'
 
+type ConnectorStatus = ReturnType<AutomaticTransactionGenerator['connectorsStatus']['get']>
+
 /**
- *
- * @param station
+ * Adds required ATG configuration methods to a mock station.
+ * @param station - The station to augment with ATG methods
  */
 function addATGMethodsToStation (station: ChargingStation): void {
   const stationExt = station as unknown as {
@@ -49,8 +51,9 @@ function addATGMethodsToStation (station: ChargingStation): void {
 }
 
 /**
- *
- * @param started
+ * Creates a mock station pre-configured for ATG tests.
+ * @param started - Whether the station should be in started state (default: true)
+ * @returns A mock ChargingStation with ATG methods configured
  */
 function createStationForATG (started = true): ChargingStation {
   const { station } = createMockChargingStation({ started })
@@ -59,8 +62,27 @@ function createStationForATG (started = true): ChargingStation {
 }
 
 /**
- *
- * @param station
+ * Retrieves connector status from the ATG, asserting it exists and narrowing the type.
+ * @param atg - The ATG instance to query
+ * @param connectorId - The connector ID to look up
+ * @returns The non-null connector status
+ */
+function getConnectorStatus (
+  atg: AutomaticTransactionGenerator,
+  connectorId: number
+): NonNullable<ConnectorStatus> {
+  const status = atg.connectorsStatus.get(connectorId)
+  expect(status).toBeDefined()
+  if (status == null) {
+    throw new BaseError(`Connector ${String(connectorId)} status unexpectedly undefined`)
+  }
+  return status
+}
+
+/**
+ * Gets the ATG instance for a station, asserting it exists and narrowing the type.
+ * @param station - The station to get the ATG instance for
+ * @returns The non-null ATG instance
  */
 function getDefinedATG (station: ChargingStation): AutomaticTransactionGenerator {
   const atg = AutomaticTransactionGenerator.getInstance(station)
@@ -72,8 +94,26 @@ function getDefinedATG (station: ChargingStation): AutomaticTransactionGenerator
 }
 
 /**
- *
- * @param atg
+ * Extracts the private handleStartTransactionResponse method from an ATG instance.
+ * @param atg - The ATG instance to extract the method from
+ * @returns The bound handleStartTransactionResponse method
+ */
+function getHandleStartTransactionResponse (
+  atg: AutomaticTransactionGenerator
+): (connectorId: number, response: StartTransactionResponse) => void {
+  return (
+    atg as unknown as {
+      handleStartTransactionResponse: (
+        connectorId: number,
+        response: StartTransactionResponse
+      ) => void
+    }
+  ).handleStartTransactionResponse.bind(atg)
+}
+
+/**
+ * Replaces the async internalStartConnector with a no-op to avoid real timer usage.
+ * @param atg - The ATG instance to mock
  */
 function mockInternalStartConnector (atg: AutomaticTransactionGenerator): void {
   const atgPrivate = atg as unknown as {
@@ -85,7 +125,7 @@ function mockInternalStartConnector (atg: AutomaticTransactionGenerator): void {
 }
 
 /**
- *
+ * Clears all ATG singleton instances to prevent test pollution.
  */
 function resetATGInstances (): void {
   const atgClass = AutomaticTransactionGenerator as unknown as {
@@ -188,12 +228,7 @@ await describe('AutomaticTransactionGenerator', async () => {
     await it('should stop a running connector', () => {
       const station = createStationForATG()
       const atg = getDefinedATG(station)
-
-      const connectorStatus = atg.connectorsStatus.get(1)
-      expect(connectorStatus).toBeDefined()
-      if (connectorStatus == null) {
-        throw new BaseError('Connector status unexpectedly undefined')
-      }
+      const connectorStatus = getConnectorStatus(atg, 1)
       connectorStatus.start = true
 
       atg.stopConnector(1)
@@ -215,20 +250,8 @@ await describe('AutomaticTransactionGenerator', async () => {
     await it('should increment accepted counters on accepted start response', () => {
       const station = createStationForATG()
       const atg = getDefinedATG(station)
-
-      const connectorStatus = atg.connectorsStatus.get(1)
-      expect(connectorStatus).toBeDefined()
-      if (connectorStatus == null) {
-        throw new BaseError('Connector status unexpectedly undefined')
-      }
-      const handleResponse = (
-        atg as unknown as {
-          handleStartTransactionResponse: (
-            connectorId: number,
-            response: StartTransactionResponse
-          ) => void
-        }
-      ).handleStartTransactionResponse.bind(atg)
+      const connectorStatus = getConnectorStatus(atg, 1)
+      const handleResponse = getHandleStartTransactionResponse(atg)
 
       handleResponse(1, {
         idTagInfo: { status: AuthorizationStatus.ACCEPTED },
@@ -243,20 +266,8 @@ await describe('AutomaticTransactionGenerator', async () => {
     await it('should increment rejected counters on rejected start response', () => {
       const station = createStationForATG()
       const atg = getDefinedATG(station)
-
-      const connectorStatus = atg.connectorsStatus.get(1)
-      expect(connectorStatus).toBeDefined()
-      if (connectorStatus == null) {
-        throw new BaseError('Connector status unexpectedly undefined')
-      }
-      const handleResponse = (
-        atg as unknown as {
-          handleStartTransactionResponse: (
-            connectorId: number,
-            response: StartTransactionResponse
-          ) => void
-        }
-      ).handleStartTransactionResponse.bind(atg)
+      const connectorStatus = getConnectorStatus(atg, 1)
+      const handleResponse = getHandleStartTransactionResponse(atg)
 
       handleResponse(1, {
         idTagInfo: { status: AuthorizationStatus.INVALID },
index c35687e4b38a6c14902452392ec7e2ffad12482e..316a283445bf689b7a58ab83c4f04d0f1f402922 100644 (file)
@@ -32,10 +32,10 @@ interface IdTagsCacheInternal {
 }
 
 /**
- *
- * @param cache
- * @param file
- * @param idTags
+ * Injects id tags directly into the cache's internal Map, bypassing file I/O.
+ * @param cache - The IdTagsCache instance
+ * @param file - The file path key to use
+ * @param idTags - Array of id tags to cache
  */
 function populateCache (cache: IdTagsCache, file: string, idTags: string[]): void {
   const internal = cache as unknown as IdTagsCacheInternal
@@ -43,15 +43,16 @@ function populateCache (cache: IdTagsCache, file: string, idTags: string[]): voi
 }
 
 /**
- *
+ * Resets the IdTagsCache singleton so subsequent getInstance() creates a fresh cache.
  */
 function resetIdTagsCache (): void {
   ;(IdTagsCache as unknown as { instance: null }).instance = null
 }
 
 /**
- *
- * @param station
+ * Resolves the idTags file path for a mock station, throwing if unresolvable.
+ * @param station - The station whose stationInfo is used
+ * @returns The resolved file path string
  */
 function resolveIdTagsFile (station: ChargingStation): string {
   const stationInfo = station.stationInfo
@@ -84,7 +85,7 @@ await describe('IdTagsCache', async () => {
       resetIdTagsCache()
       const instance2 = IdTagsCache.getInstance()
 
-      expect(instance1 === instance2).toBe(false)
+      expect(instance1).not.toBe(instance2)
     })
   })
 
index 5e12cabeb907d5b2d0dff873b1b9c621492458a5..66c1517ba82580fecce527caf621e87a77f50182 100644 (file)
@@ -26,8 +26,9 @@ interface BootstrapStatic {
 }
 
 /**
- *
- * @param hash
+ * Creates a cacheable ChargingStationConfiguration fixture with the given hash.
+ * @param hash - The configurationHash to assign
+ * @returns A ChargingStationConfiguration fixture
  */
 function createCacheableConfiguration (hash: string): ChargingStationConfiguration {
   return {
@@ -39,8 +40,9 @@ function createCacheableConfiguration (hash: string): ChargingStationConfigurati
 }
 
 /**
- *
- * @param hash
+ * Creates a ChargingStationTemplate fixture with the given hash.
+ * @param hash - The templateHash to assign
+ * @returns A ChargingStationTemplate fixture
  */
 function createTemplate (hash: string): ChargingStationTemplate {
   return {
@@ -51,10 +53,9 @@ function createTemplate (hash: string): ChargingStationTemplate {
   } as ChargingStationTemplate
 }
 
-// Inject a mock Bootstrap singleton so that SharedLRUCache constructor reads numeric getters
-// instead of triggering a real Bootstrap construction.
 /**
- *
+ * Injects a mock Bootstrap singleton so SharedLRUCache reads numeric getters
+ * instead of triggering real Bootstrap construction.
  */
 function installMockBootstrap (): void {
   ;(Bootstrap as unknown as BootstrapStatic).instance = {
@@ -65,7 +66,7 @@ function installMockBootstrap (): void {
 }
 
 /**
- *
+ * Resets the SharedLRUCache singleton so subsequent getInstance() creates a fresh cache.
  */
 function resetSharedLRUCache (): void {
   ;(SharedLRUCache as unknown as { instance: null }).instance = null
@@ -102,10 +103,10 @@ await describe('SharedLRUCache', async () => {
   await describe('template operations', async () => {
     await it('should store and retrieve a charging station template', () => {
       const cache = SharedLRUCache.getInstance()
-      const template = createTemplate('tmpl-hash-1')
+      const template = createTemplate('template-hash-1')
 
       cache.setChargingStationTemplate(template)
-      const retrieved = cache.getChargingStationTemplate('tmpl-hash-1')
+      const retrieved = cache.getChargingStationTemplate('template-hash-1')
 
       expect(retrieved).toStrictEqual(template)
     })
@@ -120,22 +121,22 @@ await describe('SharedLRUCache', async () => {
 
     await it('should report has correctly for templates', () => {
       const cache = SharedLRUCache.getInstance()
-      const template = createTemplate('tmpl-hash-2')
+      const template = createTemplate('template-hash-2')
 
       cache.setChargingStationTemplate(template)
 
-      expect(cache.hasChargingStationTemplate('tmpl-hash-2')).toBe(true)
+      expect(cache.hasChargingStationTemplate('template-hash-2')).toBe(true)
       expect(cache.hasChargingStationTemplate('unknown-hash')).toBe(false)
     })
 
     await it('should delete a charging station template', () => {
       const cache = SharedLRUCache.getInstance()
-      const template = createTemplate('tmpl-hash-3')
+      const template = createTemplate('template-hash-3')
 
       cache.setChargingStationTemplate(template)
-      cache.deleteChargingStationTemplate('tmpl-hash-3')
+      cache.deleteChargingStationTemplate('template-hash-3')
 
-      expect(cache.hasChargingStationTemplate('tmpl-hash-3')).toBe(false)
+      expect(cache.hasChargingStationTemplate('template-hash-3')).toBe(false)
     })
   })
 
@@ -193,14 +194,14 @@ await describe('SharedLRUCache', async () => {
   await describe('clear', async () => {
     await it('should clear all cached entries', () => {
       const cache = SharedLRUCache.getInstance()
-      const template = createTemplate('tmpl-clear')
+      const template = createTemplate('template-clear')
       const config = createCacheableConfiguration('config-clear')
 
       cache.setChargingStationTemplate(template)
       cache.setChargingStationConfiguration(config)
       cache.clear()
 
-      expect(cache.hasChargingStationTemplate('tmpl-clear')).toBe(false)
+      expect(cache.hasChargingStationTemplate('template-clear')).toBe(false)
       expect(cache.hasChargingStationConfiguration('config-clear')).toBe(false)
     })
   })
index e352f9c9385c987de36a2942c9710ef3a3aebdf2..4c24b86b10fcceedd6016047e8622dbd7b655845 100644 (file)
@@ -3,6 +3,7 @@
  * @description Verifies Heartbeat, NotifyReport, and StatusNotification response handling
  */
 
+import { expect } from '@std/expect'
 import { afterEach, beforeEach, describe, it, mock } from 'node:test'
 
 import type { MockChargingStation } from '../../ChargingStationTestUtils.js'
@@ -56,36 +57,42 @@ await describe('Simple response handlers', async () => {
   await describe('G02 - HeartbeatResponse handler', async () => {
     await it('should handle Heartbeat response without throwing', async () => {
       const payload: OCPP20HeartbeatResponse = { currentTime: new Date() }
-      await responseService.responseHandler(
-        mockStation,
-        OCPP20RequestCommand.HEARTBEAT,
-        payload as unknown as Parameters<typeof responseService.responseHandler>[2],
-        {} as Parameters<typeof responseService.responseHandler>[3]
-      )
+      await expect(
+        responseService.responseHandler(
+          mockStation,
+          OCPP20RequestCommand.HEARTBEAT,
+          payload as unknown as Parameters<typeof responseService.responseHandler>[2],
+          {} as Parameters<typeof responseService.responseHandler>[3]
+        )
+      ).resolves.toBeUndefined()
     })
   })
 
   await describe('B07 - NotifyReportResponse handler', async () => {
     await it('should handle NotifyReport response without throwing', async () => {
       const payload: OCPP20NotifyReportResponse = {}
-      await responseService.responseHandler(
-        mockStation,
-        OCPP20RequestCommand.NOTIFY_REPORT,
-        payload as unknown as Parameters<typeof responseService.responseHandler>[2],
-        {} as Parameters<typeof responseService.responseHandler>[3]
-      )
+      await expect(
+        responseService.responseHandler(
+          mockStation,
+          OCPP20RequestCommand.NOTIFY_REPORT,
+          payload as unknown as Parameters<typeof responseService.responseHandler>[2],
+          {} as Parameters<typeof responseService.responseHandler>[3]
+        )
+      ).resolves.toBeUndefined()
     })
   })
 
   await describe('G01 - StatusNotificationResponse handler', async () => {
     await it('should handle StatusNotification response without throwing', async () => {
       const payload: OCPP20StatusNotificationResponse = {}
-      await responseService.responseHandler(
-        mockStation,
-        OCPP20RequestCommand.STATUS_NOTIFICATION,
-        payload as unknown as Parameters<typeof responseService.responseHandler>[2],
-        {} as Parameters<typeof responseService.responseHandler>[3]
-      )
+      await expect(
+        responseService.responseHandler(
+          mockStation,
+          OCPP20RequestCommand.STATUS_NOTIFICATION,
+          payload as unknown as Parameters<typeof responseService.responseHandler>[2],
+          {} as Parameters<typeof responseService.responseHandler>[3]
+        )
+      ).resolves.toBeUndefined()
     })
   })
 })
index 7c9e9edacacdb55450be39b116abc3cdd3fcd202..bcf7c1ce6268b54d26a8adc95ea98d4d64af0ea9 100644 (file)
@@ -29,10 +29,10 @@ interface StationLocalAuthOverrides {
 }
 
 /**
- *
- * @param station
- * @param mocks
- * @param tags
+ * Configures local authorization on a mock station with the given id tags.
+ * @param station - The mock station to configure
+ * @param mocks - The mock infrastructure (for idTagsCache injection)
+ * @param tags - Array of id tags to register in the local auth list
  */
 function setupLocalAuth (
   station: ReturnType<typeof createMockChargingStation>['station'],
index 7b1f840b21d3726cb94e4dc85cd231c408bfac75..6862da013ea43c952674b89476957686e95f34ae 100644 (file)
@@ -10,7 +10,9 @@
 import { expect } from '@std/expect'
 import { afterEach, describe, it, mock } from 'node:test'
 
+import type { ChargingStation } from '../../../src/charging-station/ChargingStation.js'
 import type { Reservation } from '../../../src/types/index.js'
+import type { MockChargingStationOptions } from '../helpers/StationHelpers.js'
 
 import {
   restoreConnectorStatus,
@@ -20,6 +22,23 @@ import { ConnectorStatusEnum, OCPPVersion } from '../../../src/types/index.js'
 import { standardCleanup } from '../../helpers/TestLifecycleHelpers.js'
 import { createMockChargingStation } from '../ChargingStationTestUtils.js'
 
+/**
+ * Creates a mock station with a spied requestHandler for verifying OCPP requests.
+ * @param opts - Additional mock station options to merge
+ * @returns The station and its requestHandler spy
+ */
+function createStationWithRequestHandler (opts?: Partial<MockChargingStationOptions>): {
+  requestHandler: ReturnType<typeof mock.fn>
+  station: ChargingStation
+} {
+  const requestHandler = mock.fn(() => Promise.resolve({}))
+  const { station } = createMockChargingStation({
+    ocppRequestService: { requestHandler },
+    ...opts,
+  })
+  return { requestHandler, station }
+}
+
 await describe('OCPPServiceUtils — connector status management', async () => {
   afterEach(() => {
     standardCleanup()
@@ -27,10 +46,7 @@ await describe('OCPPServiceUtils — connector status management', async () => {
 
   await describe('sendAndSetConnectorStatus', async () => {
     await it('should send StatusNotification and update connector status', async () => {
-      const requestHandler = mock.fn(() => Promise.resolve({}))
-      const { station } = createMockChargingStation({
-        ocppRequestService: { requestHandler },
-      })
+      const { requestHandler, station } = createStationWithRequestHandler()
 
       await sendAndSetConnectorStatus(station, 1, ConnectorStatusEnum.Occupied)
 
@@ -39,10 +55,7 @@ await describe('OCPPServiceUtils — connector status management', async () => {
     })
 
     await it('should return early when connector does not exist', async () => {
-      const requestHandler = mock.fn(() => Promise.resolve({}))
-      const { station } = createMockChargingStation({
-        ocppRequestService: { requestHandler },
-      })
+      const { requestHandler, station } = createStationWithRequestHandler()
 
       await sendAndSetConnectorStatus(station, 99, ConnectorStatusEnum.Occupied)
 
@@ -50,10 +63,7 @@ await describe('OCPPServiceUtils — connector status management', async () => {
     })
 
     await it('should skip sending when options.send is false', async () => {
-      const requestHandler = mock.fn(() => Promise.resolve({}))
-      const { station } = createMockChargingStation({
-        ocppRequestService: { requestHandler },
-      })
+      const { requestHandler, station } = createStationWithRequestHandler()
 
       await sendAndSetConnectorStatus(station, 1, ConnectorStatusEnum.Occupied, undefined, {
         send: false,
@@ -64,10 +74,7 @@ await describe('OCPPServiceUtils — connector status management', async () => {
     })
 
     await it('should update connector status even when send is true', async () => {
-      const requestHandler = mock.fn(() => Promise.resolve({}))
-      const { station } = createMockChargingStation({
-        ocppRequestService: { requestHandler },
-      })
+      const { station } = createStationWithRequestHandler()
 
       expect(station.getConnectorStatus(1)?.status).toBe(ConnectorStatusEnum.Available)
 
@@ -77,26 +84,17 @@ await describe('OCPPServiceUtils — connector status management', async () => {
     })
 
     await it('should call emitChargingStationEvent with connectorStatusChanged', async () => {
-      const requestHandler = mock.fn(() => Promise.resolve({}))
-      const emitMock = mock.fn()
-      const { station } = createMockChargingStation({
-        ocppRequestService: { requestHandler },
-      })
-
-      const stationWithEmit = station as unknown as {
-        emitChargingStationEvent: (...args: unknown[]) => void
-      }
-      stationWithEmit.emitChargingStationEvent = emitMock
+      const { station } = createStationWithRequestHandler()
+      const stationObj = station as unknown as { emitChargingStationEvent: () => void }
+      const emitSpy = mock.method(stationObj, 'emitChargingStationEvent')
 
       await sendAndSetConnectorStatus(station, 1, ConnectorStatusEnum.Occupied)
 
-      expect(emitMock.mock.calls.length).toBe(1)
+      expect(emitSpy.mock.calls.length).toBe(1)
     })
 
     await it('should pass evseId to buildStatusNotificationRequest for OCPP 2.0', async () => {
-      const requestHandler = mock.fn(() => Promise.resolve({}))
-      const { station } = createMockChargingStation({
-        ocppRequestService: { requestHandler },
+      const { requestHandler, station } = createStationWithRequestHandler({
         ocppVersion: OCPPVersion.VERSION_20,
       })
 
@@ -107,10 +105,7 @@ await describe('OCPPServiceUtils — connector status management', async () => {
     })
 
     await it('should default options.send to true when options not provided', async () => {
-      const requestHandler = mock.fn(() => Promise.resolve({}))
-      const { station } = createMockChargingStation({
-        ocppRequestService: { requestHandler },
-      })
+      const { requestHandler, station } = createStationWithRequestHandler()
 
       await sendAndSetConnectorStatus(station, 1, ConnectorStatusEnum.Occupied)
 
@@ -120,10 +115,7 @@ await describe('OCPPServiceUtils — connector status management', async () => {
 
   await describe('restoreConnectorStatus', async () => {
     await it('should restore to Reserved when connector has reservation and is not Reserved', async () => {
-      const requestHandler = mock.fn(() => Promise.resolve({}))
-      const { station } = createMockChargingStation({
-        ocppRequestService: { requestHandler },
-      })
+      const { station } = createStationWithRequestHandler()
 
       const connector = station.getConnectorStatus(1)
       if (connector != null) {
@@ -142,10 +134,7 @@ await describe('OCPPServiceUtils — connector status management', async () => {
     })
 
     await it('should restore to Available when connector has no reservation and is not Available', async () => {
-      const requestHandler = mock.fn(() => Promise.resolve({}))
-      const { station } = createMockChargingStation({
-        ocppRequestService: { requestHandler },
-      })
+      const { station } = createStationWithRequestHandler()
 
       const connector = station.getConnectorStatus(1)
       if (connector != null) {
@@ -158,10 +147,7 @@ await describe('OCPPServiceUtils — connector status management', async () => {
     })
 
     await it('should not change status when connector is already Available with no reservation', async () => {
-      const requestHandler = mock.fn(() => Promise.resolve({}))
-      const { station } = createMockChargingStation({
-        ocppRequestService: { requestHandler },
-      })
+      const { requestHandler, station } = createStationWithRequestHandler()
 
       const connector = station.getConnectorStatus(1)
       if (connector != null) {
index 6c954c0c43cd9d8d12bc99d943df8632cbbb67be..79308523ff94a8a0931b660396e9f84ef5da7909 100644 (file)
@@ -20,8 +20,8 @@ import {
   ajvErrorsToErrorType,
   convertDateToISOString,
   getMessageTypeString,
+  OCPPServiceUtils,
 } from '../../../src/charging-station/ocpp/OCPPServiceUtils.js'
-import { OCPPServiceUtils } from '../../../src/charging-station/ocpp/OCPPServiceUtils.js'
 import {
   ErrorType,
   IncomingRequestCommand,
@@ -31,8 +31,9 @@ import {
 import { standardCleanup } from '../../helpers/TestLifecycleHelpers.js'
 
 /**
- *
- * @param keyword
+ * Creates a minimal AJV error fixture for testing keyword-based error mapping.
+ * @param keyword - The AJV validation keyword (e.g. 'type', 'required', 'format')
+ * @returns An ErrorObject fixture with the given keyword
  */
 function makeAjvError (keyword: string): ErrorObject {
   return {
@@ -44,9 +45,10 @@ function makeAjvError (keyword: string): ErrorObject {
 }
 
 /**
- *
+ * Creates a minimal ChargingStation stub with a logPrefix method.
+ * @returns A mock ChargingStation
  */
-function makeStationStub (): ChargingStation {
+function makeStationMock (): ChargingStation {
   return { logPrefix: () => '[test-station]' } as unknown as ChargingStation
 }
 
@@ -152,7 +154,7 @@ await describe('OCPPServiceUtils — pure functions', async () => {
   await describe('OCPPServiceUtils.isConnectorIdValid', async () => {
     await it('should return true for connector ID greater than zero', () => {
       const result = OCPPServiceUtils.isConnectorIdValid(
-        makeStationStub(),
+        makeStationMock(),
         IncomingRequestCommand.REMOTE_START_TRANSACTION,
         1
       )
@@ -161,7 +163,7 @@ await describe('OCPPServiceUtils — pure functions', async () => {
 
     await it('should return true for connector ID zero', () => {
       const result = OCPPServiceUtils.isConnectorIdValid(
-        makeStationStub(),
+        makeStationMock(),
         IncomingRequestCommand.REMOTE_START_TRANSACTION,
         0
       )
@@ -170,7 +172,7 @@ await describe('OCPPServiceUtils — pure functions', async () => {
 
     await it('should return false for negative connector ID', () => {
       const result = OCPPServiceUtils.isConnectorIdValid(
-        makeStationStub(),
+        makeStationMock(),
         IncomingRequestCommand.REMOTE_START_TRANSACTION,
         -1
       )
index baefaf11eef90a97fc3a6aabee3b4bc9e945d244..9b959a59caed93819bb21ee04d8c3fdab1e51544 100644 (file)
@@ -28,6 +28,7 @@ import { standardCleanup } from '../../helpers/TestLifecycleHelpers.js'
 /**
  * Creates a minimal ChargingStation mock with the given stationInfo.
  * @param stationInfo - partial stationInfo to set on the mock
+ * @returns A mock ChargingStation
  */
 function makeStationMock (stationInfo?: Record<string, unknown>): ChargingStation {
   return {
@@ -203,7 +204,7 @@ await describe('OCPPServiceUtils — command/trigger validation', async () => {
       expect(result).toBe(true)
     })
 
-    await it('should return true when messageTriggerSupport is empty', () => {
+    await it('should return true when messageTriggerSupport is null', () => {
       const station = makeStationMock({
         messageTriggerSupport: null,
       })
index 2e739b106e996577924c2f3aef56ff6363a88efd..9f071f5ed3ec10c8234345a8cefeda4132dedd19 100644 (file)
@@ -28,6 +28,7 @@ import { standardCleanup } from '../helpers/TestLifecycleHelpers.js'
 
 /**
  * Get a reference to the private configurationData for injection.
+ * @returns The internal configurationData holder
  */
 function getConfigurationInternals (): {
   configurationData: ConfigurationData | undefined
@@ -136,21 +137,19 @@ await describe('Configuration', async () => {
   })
 
   await it('should default to ROUND_ROBIN when not configured', () => {
-    // Arrange
     const internals = getConfigurationInternals()
     const originalData = internals.configurationData
     internals.configurationData = {
       stationTemplateUrls: [],
     } as ConfigurationData
 
-    // Act
-    const distribution = Configuration.getSupervisionUrlDistribution()
-
-    // Assert
-    expect(distribution).toBe(SupervisionUrlDistribution.ROUND_ROBIN)
-
-    internals.configurationData = originalData
-    resetSectionCache()
+    try {
+      const distribution = Configuration.getSupervisionUrlDistribution()
+      expect(distribution).toBe(SupervisionUrlDistribution.ROUND_ROBIN)
+    } finally {
+      internals.configurationData = originalData
+      resetSectionCache()
+    }
   })
 
   await it('should return false for workerPoolInUse with default workerSet config', () => {