]> Piment Noir Git Repositories - e-mobility-charging-stations-simulator.git/commitdiff
refactor(tests): reduce eslint-disable comments with proper typing
authorJérôme Benoit <jerome.benoit@sap.com>
Fri, 27 Feb 2026 16:51:41 +0000 (17:51 +0100)
committerJérôme Benoit <jerome.benoit@sap.com>
Fri, 27 Feb 2026 16:51:41 +0000 (17:51 +0100)
- Add MockOCPPRequestService and MockOCPPIncomingRequestService interfaces
- Export TestChargingStation type for typed mock service access
- Remove 14 eslint-disable comments from ChargingStationFactory.test.ts
- Remove 4 eslint-disable comments from ConfigurationKeyUtils.test.ts
- Use Partial<ChargingStationOcppConfiguration> for missing config tests

Remaining 43 inline eslint-disable comments are all legitimate:
- no-empty-function: Testing empty callbacks
- require-await: Mock async implementations
- no-explicit-any: Testing validators with invalid inputs

tests/ChargingStationFactory.test.ts
tests/ChargingStationFactory.ts
tests/charging-station/ConfigurationKeyUtils.test.ts

index b3b380905f6931d9858aee588b1f544c448f60e2..a842c4e8035787c4bae92a7b61da6f9cd8bb6281 100644 (file)
@@ -14,10 +14,7 @@ await describe('ChargingStationFactory', async () => {
     await it('Should throw error when OCPPRequestService.requestHandler is not mocked', async () => {
       const station = createChargingStation({ connectorsCount: 1 })
 
-      await expect(
-        // eslint-disable-next-line @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-explicit-any
-        (station as any).ocppRequestService.requestHandler()
-      ).rejects.toThrow(
+      await expect(station.ocppRequestService.requestHandler()).rejects.toThrow(
         'ocppRequestService.requestHandler not mocked. Define in createChargingStation options.'
       )
     })
@@ -26,8 +23,7 @@ await describe('ChargingStationFactory', async () => {
       const station = createChargingStation({ connectorsCount: 1 })
 
       expect(() => {
-        // eslint-disable-next-line @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-explicit-any
-        ;(station as any).ocppIncomingRequestService.stop()
+        station.ocppIncomingRequestService.stop()
       }).toThrow(
         'ocppIncomingRequestService.stop not mocked. Define in createChargingStation options.'
       )
@@ -45,9 +41,7 @@ await describe('ChargingStationFactory', async () => {
         },
       })
 
-      // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-explicit-any
-      const result = await (station as any).ocppRequestService.requestHandler()
-      // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
+      const result = (await station.ocppRequestService.requestHandler()) as { success: boolean }
       expect(result.success).toBe(true)
     })
 
@@ -62,18 +56,14 @@ await describe('ChargingStationFactory', async () => {
         },
       })
 
-      // eslint-disable-next-line @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-explicit-any
-      ;(station as any).ocppIncomingRequestService.stop()
+      station.ocppIncomingRequestService.stop()
       expect(stopCalled).toBe(true)
     })
 
     await it('Should throw error when OCPPRequestService.sendError is not mocked', async () => {
       const station = createChargingStation({ connectorsCount: 1 })
 
-      await expect(
-        // eslint-disable-next-line @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-explicit-any
-        (station as any).ocppRequestService.sendError()
-      ).rejects.toThrow(
+      await expect(station.ocppRequestService.sendError()).rejects.toThrow(
         'ocppRequestService.sendError not mocked. Define in createChargingStation options.'
       )
     })
@@ -81,10 +71,7 @@ await describe('ChargingStationFactory', async () => {
     await it('Should throw error when OCPPRequestService.sendResponse is not mocked', async () => {
       const station = createChargingStation({ connectorsCount: 1 })
 
-      await expect(
-        // eslint-disable-next-line @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-explicit-any
-        (station as any).ocppRequestService.sendResponse()
-      ).rejects.toThrow(
+      await expect(station.ocppRequestService.sendResponse()).rejects.toThrow(
         'ocppRequestService.sendResponse not mocked. Define in createChargingStation options.'
       )
     })
@@ -101,9 +88,7 @@ await describe('ChargingStationFactory', async () => {
         },
       })
 
-      // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-explicit-any
-      const result = await (station as any).ocppRequestService.sendError()
-      // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
+      const result = (await station.ocppRequestService.sendError()) as { error: string }
       expect(result.error).toBe('test-error')
     })
 
@@ -119,19 +104,14 @@ await describe('ChargingStationFactory', async () => {
         },
       })
 
-      // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-explicit-any
-      const result = await (station as any).ocppRequestService.sendResponse()
-      // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
+      const result = (await station.ocppRequestService.sendResponse()) as { response: string }
       expect(result.response).toBe('test-response')
     })
 
     await it('Should throw error when OCPPIncomingRequestService.incomingRequestHandler is not mocked', async () => {
       const station = createChargingStation({ connectorsCount: 1 })
 
-      await expect(
-        // eslint-disable-next-line @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-explicit-any
-        (station as any).ocppIncomingRequestService.incomingRequestHandler()
-      ).rejects.toThrow(
+      await expect(station.ocppIncomingRequestService.incomingRequestHandler()).rejects.toThrow(
         'ocppIncomingRequestService.incomingRequestHandler not mocked. Define in createChargingStation options.'
       )
     })
@@ -148,9 +128,9 @@ await describe('ChargingStationFactory', async () => {
         },
       })
 
-      // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-explicit-any
-      const result = await (station as any).ocppIncomingRequestService.incomingRequestHandler()
-      // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
+      const result = (await station.ocppIncomingRequestService.incomingRequestHandler()) as {
+        handled: boolean
+      }
       expect(result.handled).toBe(true)
     })
   })
index 5ade13e4c7c801de96b7e2e02e69505c6a2d9638..4b3f3038935311b7a15e7fde139625ff70304c79 100644 (file)
@@ -43,23 +43,51 @@ export interface ChargingStationOptions {
   heartbeatInterval?: number
   ocppConfiguration?: ChargingStationConfiguration
   /** Custom OCPP incoming request service for test mocking */
-  ocppIncomingRequestService?: unknown
+  ocppIncomingRequestService?: Partial<MockOCPPIncomingRequestService>
   /** Custom OCPP request service for test mocking */
-  ocppRequestService?: unknown
+  ocppRequestService?: Partial<MockOCPPRequestService>
   started?: boolean
   starting?: boolean
   stationInfo?: Partial<ChargingStationInfo>
   websocketPingInterval?: number
 }
 
+/**
+ * Mock OCPP incoming request service interface for testing
+ * Provides typed access to mock handlers without eslint-disable comments
+ */
+export interface MockOCPPIncomingRequestService {
+  incomingRequestHandler: () => Promise<unknown>
+  stop: () => void
+}
+
+/**
+ * Mock OCPP request service interface for testing
+ * Provides typed access to mock handlers without eslint-disable comments
+ */
+export interface MockOCPPRequestService {
+  requestHandler: () => Promise<unknown>
+  sendError: () => Promise<unknown>
+  sendResponse: () => Promise<unknown>
+}
+
+/**
+ * Test-specific ChargingStation interface exposing mock services
+ * Allows typed access to mock OCPP services in tests
+ */
+export interface TestChargingStation extends ChargingStation {
+  ocppIncomingRequestService: MockOCPPIncomingRequestService
+  ocppRequestService: MockOCPPRequestService
+}
+
 const CHARGING_STATION_BASE_NAME = 'CS-TEST'
 
 /**
  * Creates a ChargingStation instance for tests
  * @param options - Configuration options for the charging station
- * @returns ChargingStation instance configured for testing
+ * @returns TestChargingStation instance configured for testing
  */
-export function createChargingStation (options: ChargingStationOptions = {}): ChargingStation {
+export function createChargingStation (options: ChargingStationOptions = {}): TestChargingStation {
   const baseName = options.baseName ?? CHARGING_STATION_BASE_NAME
   const templateIndex = 1
   const connectionTimeout = options.connectionTimeout ?? Constants.DEFAULT_CONNECTION_TIMEOUT
@@ -198,7 +226,7 @@ export function createChargingStation (options: ChargingStationOptions = {}): Ch
       ],
       ...options.ocppConfiguration,
     },
-    ocppIncomingRequestService: options.ocppIncomingRequestService ?? {
+    ocppIncomingRequestService: {
       incomingRequestHandler: async () => {
         return await Promise.reject(
           new Error(
@@ -211,8 +239,9 @@ export function createChargingStation (options: ChargingStationOptions = {}): Ch
           'ocppIncomingRequestService.stop not mocked. Define in createChargingStation options.'
         )
       },
+      ...options.ocppIncomingRequestService,
     },
-    ocppRequestService: options.ocppRequestService ?? {
+    ocppRequestService: {
       requestHandler: async () => {
         return await Promise.reject(
           new Error(
@@ -234,6 +263,7 @@ export function createChargingStation (options: ChargingStationOptions = {}): Ch
           )
         )
       },
+      ...options.ocppRequestService,
     },
     restartHeartbeat: (): void => {
       /* no-op for tests */
@@ -270,7 +300,7 @@ export function createChargingStation (options: ChargingStationOptions = {}): Ch
     stopTxUpdatedInterval: (_connectorId: number): void => {
       /* no-op for tests */
     },
-  } as unknown as ChargingStation
+  } as unknown as TestChargingStation
 
   return chargingStation
 }
index 7c9474d86730bb25d25beb4e01cef1b15114ab30..031f92a694fc5c94ac6f375ab6aa39070d6b6ab1 100644 (file)
@@ -5,6 +5,8 @@
 import { expect } from '@std/expect'
 import { describe, it } from 'node:test'
 
+import type { ChargingStationOcppConfiguration } from '../../src/types/index.js'
+
 import {
   addConfigurationKey,
   deleteConfigurationKey,
@@ -23,9 +25,8 @@ await describe('ConfigurationKeyUtils test suite', async () => {
   await describe('getConfigurationKey()', async () => {
     await it('should return undefined when configurationKey array is missing', () => {
       const cs = createChargingStation()
-      // remove array
-      // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-assignment
-      cs.ocppConfiguration = {} as any
+      // Simulate missing configurationKey array
+      cs.ocppConfiguration = {} as Partial<ChargingStationOcppConfiguration>
       expect(getConfigurationKey(cs, TEST_KEY_1)).toBeUndefined()
     })
 
@@ -54,8 +55,8 @@ await describe('ConfigurationKeyUtils test suite', async () => {
   await describe('addConfigurationKey()', async () => {
     await it('should no-op when configurationKey array missing', () => {
       const cs = createChargingStation()
-      // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-assignment
-      cs.ocppConfiguration = {} as any
+      // Simulate missing configurationKey array
+      cs.ocppConfiguration = {} as Partial<ChargingStationOcppConfiguration>
       addConfigurationKey(cs, TEST_KEY_1, VALUE_A)
       expect(getConfigurationKey(cs, TEST_KEY_1)).toBeUndefined()
     })
@@ -214,8 +215,8 @@ await describe('ConfigurationKeyUtils test suite', async () => {
 
     await it('should return undefined without logging when configurationKey array missing', t => {
       const cs = createChargingStation()
-      // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-assignment
-      cs.ocppConfiguration = {} as any
+      // Simulate missing configurationKey array
+      cs.ocppConfiguration = {} as Partial<ChargingStationOcppConfiguration>
       const errorMock = t.mock.method(logger, 'error')
       const res = setConfigurationKeyValue(cs, TEST_KEY_1, VALUE_A)
       expect(res).toBeUndefined()
@@ -242,8 +243,8 @@ await describe('ConfigurationKeyUtils test suite', async () => {
   await describe('deleteConfigurationKey()', async () => {
     await it('should return undefined when configurationKey array missing', () => {
       const cs = createChargingStation()
-      // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-assignment
-      cs.ocppConfiguration = {} as any
+      // Simulate missing configurationKey array
+      cs.ocppConfiguration = {} as Partial<ChargingStationOcppConfiguration>
       const res = deleteConfigurationKey(cs, TEST_KEY_1)
       expect(res).toBeUndefined()
     })