The following utilities are available for reuse across test files:
-| Utility | Location | Purpose |
-| ----------------------------- | ------------------------------------ | ----------------------------------------- |
-| `createMockChargingStation()` | `ChargingStationTestUtils.ts` | Lightweight mock station stub |
-| `createChargingStation()` | `ChargingStationFactory.ts` | Full test station with OCPP services |
-| `createConnectorStatus()` | `helpers/StationHelpers.ts` | ConnectorStatus factory with defaults |
-| `MockWebSocket` | `mocks/MockWebSocket.ts` | WebSocket simulation with message capture |
-| `MockIdTagsCache` | `mocks/MockCaches.ts` | In-memory IdTags cache mock |
-| `MockSharedLRUCache` | `mocks/MockCaches.ts` | In-memory LRU cache mock |
-| `waitForCondition()` | `helpers/StationHelpers.ts` | Async condition waiting with timeout |
-| `cleanupChargingStation()` | `helpers/StationHelpers.ts` | Proper station cleanup for afterEach |
-| Auth factories | `ocpp/auth/helpers/MockFactories.ts` | Auth-specific mock creation |
+| Utility | Location | Purpose |
+| --------------------------------------- | ------------------------------------ | -------------------------------------------- |
+| `createMockChargingStation()` | `ChargingStationTestUtils.ts` | Lightweight mock station stub |
+| `createChargingStation()` | `ChargingStationFactory.ts` | Full test station with OCPP services |
+| `createConnectorStatus()` | `helpers/StationHelpers.ts` | ConnectorStatus factory with defaults |
+| `createStationWithCertificateManager()` | `ocpp/2.0/OCPP20TestUtils.ts` | Station with certificate manager (type-safe) |
+| `MockWebSocket` | `mocks/MockWebSocket.ts` | WebSocket simulation with message capture |
+| `MockIdTagsCache` | `mocks/MockCaches.ts` | In-memory IdTags cache mock |
+| `MockSharedLRUCache` | `mocks/MockCaches.ts` | In-memory LRU cache mock |
+| `waitForCondition()` | `helpers/StationHelpers.ts` | Async condition waiting with timeout |
+| `cleanupChargingStation()` | `helpers/StationHelpers.ts` | Proper station cleanup for afterEach |
+| Auth factories | `ocpp/auth/helpers/MockFactories.ts` | Auth-specific mock creation |
+| ----------------------------- | ------------------------------------ | ----------------------------------------- |
+| `createMockChargingStation()` | `ChargingStationTestUtils.ts` | Lightweight mock station stub |
+| `createChargingStation()` | `ChargingStationFactory.ts` | Full test station with OCPP services |
+| `createConnectorStatus()` | `helpers/StationHelpers.ts` | ConnectorStatus factory with defaults |
+| `MockWebSocket` | `mocks/MockWebSocket.ts` | WebSocket simulation with message capture |
+| `MockIdTagsCache` | `mocks/MockCaches.ts` | In-memory IdTags cache mock |
+| `MockSharedLRUCache` | `mocks/MockCaches.ts` | In-memory LRU cache mock |
+| `waitForCondition()` | `helpers/StationHelpers.ts` | Async condition waiting with timeout |
+| `cleanupChargingStation()` | `helpers/StationHelpers.ts` | Proper station cleanup for afterEach |
+| Auth factories | `ocpp/auth/helpers/MockFactories.ts` | Auth-specific mock creation |
**DO NOT duplicate these utilities.** Import and reuse them.
import { Constants } from '../../../../src/utils/index.js'
import { createChargingStation } from '../../../ChargingStationFactory.js'
import { TEST_CHARGING_STATION_BASE_NAME } from '../../ChargingStationTestConstants.js'
+import { createStationWithCertificateManager } from './OCPP20TestUtils.js'
const VALID_CERTIFICATE_HASH_DATA = {
hashAlgorithm: HashAlgorithmEnumType.SHA256,
websocketPingInterval: Constants.DEFAULT_WEBSOCKET_PING_INTERVAL,
})
- // Cast to allow setting certificateManager property
- stationWithCertManager = mockChargingStation as unknown as ChargingStationWithCertificateManager
- stationWithCertManager.certificateManager = createMockCertificateManager()
+ stationWithCertManager = createStationWithCertificateManager(
+ mockChargingStation,
+ createMockCertificateManager()
+ )
incomingRequestService = new OCPP20IncomingRequestService()
testableService = createTestableIncomingRequestService(incomingRequestService)
import { Constants } from '../../../../src/utils/index.js'
import { createChargingStation } from '../../../ChargingStationFactory.js'
import { TEST_CHARGING_STATION_BASE_NAME } from '../../ChargingStationTestConstants.js'
+import { createStationWithCertificateManager } from './OCPP20TestUtils.js'
const createMockCertificateHashData = (serialNumber = '123456789'): CertificateHashDataType => ({
hashAlgorithm: HashAlgorithmEnumType.SHA256,
websocketPingInterval: Constants.DEFAULT_WEBSOCKET_PING_INTERVAL,
})
- // Cast to allow setting certificateManager property
- stationWithCertManager = mockChargingStation as unknown as ChargingStationWithCertificateManager
- stationWithCertManager.certificateManager = createMockCertificateManager()
+ stationWithCertManager = createStationWithCertificateManager(
+ mockChargingStation,
+ createMockCertificateManager()
+ )
incomingRequestService = new OCPP20IncomingRequestService()
testableService = createTestableIncomingRequestService(incomingRequestService)
import { Constants } from '../../../../src/utils/index.js'
import { createChargingStation } from '../../../ChargingStationFactory.js'
import { TEST_CHARGING_STATION_BASE_NAME } from '../../ChargingStationTestConstants.js'
+import { createStationWithCertificateManager } from './OCPP20TestUtils.js'
const VALID_PEM_CERTIFICATE = `-----BEGIN CERTIFICATE-----
MIIBkTCB+wIJAKHBfpvPA0GXMA0GCSqGSIb3DQEBCwUAMBExDzANBgNVBAMMBnRl
websocketPingInterval: Constants.DEFAULT_WEBSOCKET_PING_INTERVAL,
})
- // Cast to allow setting certificateManager property
- stationWithCertManager = mockChargingStation as unknown as ChargingStationWithCertificateManager
- stationWithCertManager.certificateManager = createMockCertificateManager()
+ // Use factory function to create station with certificate manager
+ stationWithCertManager = createStationWithCertificateManager(
+ mockChargingStation,
+ createMockCertificateManager()
+ )
incomingRequestService = new OCPP20IncomingRequestService()
testableService = createTestableIncomingRequestService(incomingRequestService)
import { mock } from 'node:test'
import type { ChargingStation } from '../../../../src/charging-station/ChargingStation.js'
+import type { ChargingStationWithCertificateManager } from '../../../../src/charging-station/ocpp/2.0/OCPP20CertificateManager.js'
import type { OCPP20RequestService } from '../../../../src/charging-station/ocpp/2.0/OCPP20RequestService.js'
import type { ConfigurationKey } from '../../../../src/types/ChargingStationOcppConfiguration.js'
import type { EmptyObject } from '../../../../src/types/EmptyObject.js'
startContext: TransactionContextFixtures.remoteStart(),
},
] as const
+
+// ============================================================================
+// ChargingStationWithCertificateManager Factory
+// ============================================================================
+
+/**
+ * Create a mock ChargingStation with certificate manager for testing.
+ * This encapsulates the type casting pattern for ChargingStationWithCertificateManager.
+ * @param baseStation - Optional base station to extend (creates new if not provided)
+ * @param certificateManager - Certificate manager to attach
+ * @returns ChargingStation with certificateManager property properly typed
+ * @example
+ * ```typescript
+ * const station = createStationWithCertificateManager(
+ * createChargingStation({ ocppVersion: OCPPVersion.VERSION_201 }),
+ * createMockCertificateManager()
+ * )
+ * ```
+ */
+export function createStationWithCertificateManager (
+ baseStation: ChargingStation,
+ certificateManager: ChargingStationWithCertificateManager['certificateManager']
+): ChargingStationWithCertificateManager {
+ const station = baseStation as ChargingStationWithCertificateManager
+ station.certificateManager = certificateManager
+ return station
+}
* @description Unit tests for OCPP authentication integration with deterministic mocked responses
*/
import { expect } from '@std/expect'
-import { afterEach, beforeEach, describe, it } from 'node:test'
+import { afterEach, beforeEach, describe, it, mock } from 'node:test'
import type { ChargingStation } from '../../../../src/charging-station/ChargingStation.js'
})
afterEach(() => {
- mockChargingStation16 = undefined as unknown as ChargingStation
- mockChargingStation20 = undefined as unknown as ChargingStation
+ mock.reset()
})
await describe('Service Initialization', async () => {
* @description Unit tests for OCPP 1.6 authentication adapter
*/
import { expect } from '@std/expect'
-import { afterEach, beforeEach, describe, it } from 'node:test'
+import { afterEach, beforeEach, describe, it, mock } from 'node:test'
import type { ChargingStation } from '../../../../../src/charging-station/ChargingStation.js'
import type { OCPP16AuthorizeResponse } from '../../../../../src/types/ocpp/1.6/Responses.js'
})
afterEach(() => {
- adapter = undefined as unknown as OCPP16AuthAdapter
- mockChargingStation = undefined as unknown as ChargingStation
+ mock.reset()
})
await describe('constructor', async () => {
*/
import { expect } from '@std/expect'
-import { afterEach, beforeEach, describe, it } from 'node:test'
+import { afterEach, beforeEach, describe, it, mock } from 'node:test'
import type { ChargingStation } from '../../../../../src/charging-station/ChargingStation.js'
})
afterEach(() => {
- adapter = undefined as unknown as OCPP20AuthAdapter
- mockChargingStation = undefined as unknown as ChargingStation
+ mock.reset()
})
await describe('G03.FR.02.001 - Offline detection', async () => {
* @description Unit tests for OCPP 2.0 authentication adapter
*/
import { expect } from '@std/expect'
-import { afterEach, beforeEach, describe, it } from 'node:test'
+import { afterEach, beforeEach, describe, it, mock } from 'node:test'
import type { ChargingStation } from '../../../../../src/charging-station/ChargingStation.js'
})
afterEach(() => {
- adapter = undefined as unknown as OCPP20AuthAdapter
- mockChargingStation = undefined as unknown as ChargingStation
+ mock.reset()
})
await describe('constructor', async () => {
* @description Unit tests for in-memory authorization cache conformance (G03.FR.01)
*/
import { expect } from '@std/expect'
-import { afterEach, beforeEach, describe, it } from 'node:test'
+import { afterEach, beforeEach, describe, it, mock } from 'node:test'
import { InMemoryAuthCache } from '../../../../../src/charging-station/ocpp/auth/cache/InMemoryAuthCache.js'
import {
})
afterEach(() => {
- cache = undefined as unknown as InMemoryAuthCache
+ mock.reset()
})
await describe('G03.FR.01.001 - Cache Hit Behavior', async () => {
* @description Unit tests for certificate-based authentication strategy
*/
import { expect } from '@std/expect'
-import { afterEach, beforeEach, describe, it } from 'node:test'
+import { afterEach, beforeEach, describe, it, mock } from 'node:test'
import type { ChargingStation } from '../../../../../src/charging-station/ChargingStation.js'
import type { OCPPAuthAdapter } from '../../../../../src/charging-station/ocpp/auth/interfaces/OCPPAuthService.js'
})
afterEach(() => {
- mockChargingStation = undefined as unknown as typeof mockChargingStation
- mockOCPP20Adapter = undefined as unknown as typeof mockOCPP20Adapter
+ mock.reset()
})
await describe('constructor', async () => {
* @description Unit tests for local authorization strategy (cache and local list)
*/
import { expect } from '@std/expect'
-import { afterEach, beforeEach, describe, it } from 'node:test'
+import { afterEach, beforeEach, describe, it, mock } from 'node:test'
import type {
AuthCache,
})
afterEach(() => {
- mockAuthCache = undefined as unknown as typeof mockAuthCache
- mockLocalAuthListManager = undefined as unknown as typeof mockLocalAuthListManager
+ mock.reset()
})
await describe('constructor', async () => {
* @description Unit tests for remote (CSMS) authorization strategy
*/
import { expect } from '@std/expect'
-import { afterEach, beforeEach, describe, it } from 'node:test'
+import { afterEach, beforeEach, describe, it, mock } from 'node:test'
import type {
AuthCache,
})
afterEach(() => {
- mockAuthCache = undefined as unknown as typeof mockAuthCache
- mockOCPP16Adapter = undefined as unknown as typeof mockOCPP16Adapter
- mockOCPP20Adapter = undefined as unknown as typeof mockOCPP20Adapter
+ mock.reset()
})
await describe('constructor', async () => {
})
await it('should return generic message for unknown status', () => {
- // eslint-disable-next-line @typescript-eslint/no-unsafe-argument, @typescript-eslint/no-explicit-any
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-argument, @typescript-eslint/no-explicit-any -- testing invalid status value
expect(AuthHelpers.getStatusMessage('INVALID_STATUS' as any)).toBe('Authorization failed')
})
})
})
await it('should return false for non-string input', () => {
- // eslint-disable-next-line @typescript-eslint/no-unsafe-argument, @typescript-eslint/no-explicit-any
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-argument, @typescript-eslint/no-explicit-any -- testing invalid type input
expect(AuthValidators.isValidIdentifierValue(123 as any)).toBe(false)
})
})
})
await it('should return empty string for non-string input', () => {
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any -- testing invalid type input
expect(AuthValidators.sanitizeIdTag(123 as any)).toBe('')
})
})
await it('should return empty string for non-string input', () => {
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any -- testing invalid type input
expect(AuthValidators.sanitizeIdToken(123 as any)).toBe('')
})
})
await it('should return false for null configuration', () => {
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any -- testing null input
expect(AuthValidators.validateAuthConfiguration(null as any)).toBe(false)
})
await it('should return false for undefined configuration', () => {
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any -- testing undefined input
expect(AuthValidators.validateAuthConfiguration(undefined as any)).toBe(false)
})
localAuthListEnabled: true,
localPreAuthorize: true,
offlineAuthorizationEnabled: false,
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any -- testing invalid enum value
strategyPriorityOrder: ['InvalidMethod' as any],
}
await describe('validateIdentifier', async () => {
await it('should return false for undefined identifier', () => {
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any -- testing undefined input
expect(AuthValidators.validateIdentifier(undefined as any)).toBe(false)
})
await it('should return false for null identifier', () => {
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any -- testing null input
expect(AuthValidators.validateIdentifier(null as any)).toBe(false)
})