*/
import { expect } from '@std/expect'
-import { afterEach, describe, it, mock, type Mock } from 'node:test'
+import { afterEach, beforeEach, describe, it, mock, type Mock } from 'node:test'
import type { ChargingStation } from '../../../../src/charging-station/index.js'
import type {
})
await describe('I04 - CertificateSigned', async () => {
+ let mockChargingStation: TestableChargingStationWithCertificate
+ let incomingRequestService: OCPP20IncomingRequestService
+ let testableService: ReturnType<typeof createTestableIncomingRequestService>
+
+ beforeEach(() => {
+ mockChargingStation = createChargingStation({
+ baseName: TEST_CHARGING_STATION_BASE_NAME,
+ connectorsCount: 3,
+ evseConfiguration: { evsesCount: 3 },
+ heartbeatInterval: Constants.DEFAULT_HEARTBEAT_INTERVAL,
+ stationInfo: {
+ ocppStrictCompliance: false,
+ ocppVersion: OCPPVersion.VERSION_201,
+ },
+ websocketPingInterval: Constants.DEFAULT_WEBSOCKET_PING_INTERVAL,
+ }) as TestableChargingStationWithCertificate
+ mockChargingStation.certificateManager = createMockCertificateManager()
+ mockChargingStation.closeWSConnection = mock.fn()
+ incomingRequestService = new OCPP20IncomingRequestService()
+ testableService = createTestableIncomingRequestService(incomingRequestService)
+ })
+
afterEach(() => {
mock.restoreAll()
})
-
- const mockChargingStation = createChargingStation({
- baseName: TEST_CHARGING_STATION_BASE_NAME,
- connectorsCount: 3,
- evseConfiguration: { evsesCount: 3 },
- heartbeatInterval: Constants.DEFAULT_HEARTBEAT_INTERVAL,
- stationInfo: {
- ocppStrictCompliance: false,
- ocppVersion: OCPPVersion.VERSION_201,
- },
- websocketPingInterval: Constants.DEFAULT_WEBSOCKET_PING_INTERVAL,
- }) as TestableChargingStationWithCertificate
-
- mockChargingStation.certificateManager = createMockCertificateManager()
- // Mock closeWSConnection for reconnect tests
- mockChargingStation.closeWSConnection = mock.fn()
-
- const incomingRequestService = new OCPP20IncomingRequestService()
- const testableService = createTestableIncomingRequestService(incomingRequestService)
-
await describe('Valid Certificate Chain Installation', async () => {
await it('should accept valid certificate chain', async () => {
mockChargingStation.certificateManager = createMockCertificateManager({
*/
import { expect } from '@std/expect'
-import { afterEach, describe, it, mock } from 'node:test'
+import { afterEach, beforeEach, describe, it, mock } from 'node:test'
import { createTestableIncomingRequestService } from '../../../../src/charging-station/ocpp/2.0/__testable__/index.js'
import { OCPP20IncomingRequestService } from '../../../../src/charging-station/ocpp/2.0/OCPP20IncomingRequestService.js'
mock.restoreAll()
})
- const mockChargingStation = createChargingStation({
- baseName: TEST_CHARGING_STATION_BASE_NAME,
- connectorsCount: 3,
- evseConfiguration: { evsesCount: 3 },
- heartbeatInterval: Constants.DEFAULT_HEARTBEAT_INTERVAL,
- stationInfo: {
- ocppStrictCompliance: false,
- ocppVersion: OCPPVersion.VERSION_201,
- },
- websocketPingInterval: Constants.DEFAULT_WEBSOCKET_PING_INTERVAL,
+ let mockChargingStation: ReturnType<typeof createChargingStation>
+ let incomingRequestService: OCPP20IncomingRequestService
+ let testableService: ReturnType<typeof createTestableIncomingRequestService>
+
+ beforeEach(() => {
+ mockChargingStation = createChargingStation({
+ baseName: TEST_CHARGING_STATION_BASE_NAME,
+ connectorsCount: 3,
+ evseConfiguration: { evsesCount: 3 },
+ heartbeatInterval: Constants.DEFAULT_HEARTBEAT_INTERVAL,
+ stationInfo: {
+ ocppStrictCompliance: false,
+ ocppVersion: OCPPVersion.VERSION_201,
+ },
+ websocketPingInterval: Constants.DEFAULT_WEBSOCKET_PING_INTERVAL,
+ })
+ incomingRequestService = new OCPP20IncomingRequestService()
+ testableService = createTestableIncomingRequestService(incomingRequestService)
})
- const incomingRequestService = new OCPP20IncomingRequestService()
- const testableService = createTestableIncomingRequestService(incomingRequestService)
-
// FR: C11.FR.01 - CS SHALL attempt to clear its Authorization Cache
await it('should handle ClearCache request successfully', async () => {
const response = await testableService.handleRequestClearCache(mockChargingStation)
*/
import { expect } from '@std/expect'
-import { afterEach, describe, it, mock } from 'node:test'
+import { afterEach, beforeEach, describe, it, mock } from 'node:test'
import type { ChargingStationWithCertificateManager } from '../../../../src/charging-station/ocpp/2.0/OCPP20CertificateManager.js'
mock.restoreAll()
})
- const mockChargingStation = createChargingStation({
- baseName: TEST_CHARGING_STATION_BASE_NAME,
- connectorsCount: 3,
- evseConfiguration: { evsesCount: 3 },
- heartbeatInterval: Constants.DEFAULT_HEARTBEAT_INTERVAL,
- stationInfo: {
- ocppStrictCompliance: false,
- ocppVersion: OCPPVersion.VERSION_201,
- },
- websocketPingInterval: Constants.DEFAULT_WEBSOCKET_PING_INTERVAL,
- })
+ let mockChargingStation: ReturnType<typeof createChargingStation>
+ let stationWithCertManager: ChargingStationWithCertificateManager
+ let incomingRequestService: OCPP20IncomingRequestService
+ let testableService: ReturnType<typeof createTestableIncomingRequestService>
+
+ beforeEach(() => {
+ mockChargingStation = createChargingStation({
+ baseName: TEST_CHARGING_STATION_BASE_NAME,
+ connectorsCount: 3,
+ evseConfiguration: { evsesCount: 3 },
+ heartbeatInterval: Constants.DEFAULT_HEARTBEAT_INTERVAL,
+ stationInfo: {
+ ocppStrictCompliance: false,
+ ocppVersion: OCPPVersion.VERSION_201,
+ },
+ websocketPingInterval: Constants.DEFAULT_WEBSOCKET_PING_INTERVAL,
+ })
- // Cast to allow setting certificateManager property
- const stationWithCertManager =
- mockChargingStation as unknown as ChargingStationWithCertificateManager
- stationWithCertManager.certificateManager = createMockCertificateManager()
+ // Cast to allow setting certificateManager property
+ stationWithCertManager = mockChargingStation as unknown as ChargingStationWithCertificateManager
+ stationWithCertManager.certificateManager = createMockCertificateManager()
- const incomingRequestService = new OCPP20IncomingRequestService()
- const testableService = createTestableIncomingRequestService(incomingRequestService)
+ incomingRequestService = new OCPP20IncomingRequestService()
+ testableService = createTestableIncomingRequestService(incomingRequestService)
+ })
await describe('Valid Certificate Deletion', async () => {
await it('should accept deletion of existing certificate', async () => {
import { expect } from '@std/expect'
-import { afterEach, describe, it } from 'node:test'
+import { afterEach, beforeEach, describe, it } from 'node:test'
import {
addConfigurationKey,
} from '../../ChargingStationTestConstants.js'
await describe('B07 - Get Base Report', async () => {
- const mockChargingStation = createChargingStation({
- baseName: TEST_CHARGING_STATION_BASE_NAME,
- connectorsCount: 3,
- evseConfiguration: { evsesCount: 3 },
- heartbeatInterval: Constants.DEFAULT_HEARTBEAT_INTERVAL,
- stationInfo: {
- chargePointModel: TEST_CHARGE_POINT_MODEL,
- chargePointSerialNumber: TEST_CHARGE_POINT_SERIAL_NUMBER,
- chargePointVendor: TEST_CHARGE_POINT_VENDOR,
- firmwareVersion: TEST_FIRMWARE_VERSION,
- ocppStrictCompliance: false,
- ocppVersion: OCPPVersion.VERSION_201,
- },
- websocketPingInterval: Constants.DEFAULT_WEBSOCKET_PING_INTERVAL,
- })
+ let mockChargingStation: ReturnType<typeof createChargingStation>
+ let incomingRequestService: OCPP20IncomingRequestService
+ let testableService: ReturnType<typeof createTestableIncomingRequestService>
+
+ beforeEach(() => {
+ mockChargingStation = createChargingStation({
+ baseName: TEST_CHARGING_STATION_BASE_NAME,
+ connectorsCount: 3,
+ evseConfiguration: { evsesCount: 3 },
+ heartbeatInterval: Constants.DEFAULT_HEARTBEAT_INTERVAL,
+ stationInfo: {
+ chargePointModel: TEST_CHARGE_POINT_MODEL,
+ chargePointSerialNumber: TEST_CHARGE_POINT_SERIAL_NUMBER,
+ chargePointVendor: TEST_CHARGE_POINT_VENDOR,
+ firmwareVersion: TEST_FIRMWARE_VERSION,
+ ocppStrictCompliance: false,
+ ocppVersion: OCPPVersion.VERSION_201,
+ },
+ websocketPingInterval: Constants.DEFAULT_WEBSOCKET_PING_INTERVAL,
+ })
- const incomingRequestService = new OCPP20IncomingRequestService()
+ incomingRequestService = new OCPP20IncomingRequestService()
- const testableService = createTestableIncomingRequestService(incomingRequestService)
+ testableService = createTestableIncomingRequestService(incomingRequestService)
+ })
// Reset singleton state after each test to ensure test isolation
afterEach(() => {
*/
import { expect } from '@std/expect'
-import { afterEach, describe, it, mock } from 'node:test'
+import { afterEach, beforeEach, describe, it, mock } from 'node:test'
import type { ChargingStationWithCertificateManager } from '../../../../src/charging-station/ocpp/2.0/OCPP20CertificateManager.js'
})
await describe('I04 - GetInstalledCertificateIds', async () => {
- afterEach(() => {
- mock.restoreAll()
- })
+ let mockChargingStation: ReturnType<typeof createChargingStation>
+ let stationWithCertManager: ChargingStationWithCertificateManager
+ let incomingRequestService: OCPP20IncomingRequestService
+ let testableService: ReturnType<typeof createTestableIncomingRequestService>
+
+ beforeEach(() => {
+ mockChargingStation = createChargingStation({
+ baseName: TEST_CHARGING_STATION_BASE_NAME,
+ connectorsCount: 3,
+ evseConfiguration: { evsesCount: 3 },
+ heartbeatInterval: Constants.DEFAULT_HEARTBEAT_INTERVAL,
+ stationInfo: {
+ ocppStrictCompliance: false,
+ ocppVersion: OCPPVersion.VERSION_201,
+ },
+ websocketPingInterval: Constants.DEFAULT_WEBSOCKET_PING_INTERVAL,
+ })
- const mockChargingStation = createChargingStation({
- baseName: TEST_CHARGING_STATION_BASE_NAME,
- connectorsCount: 3,
- evseConfiguration: { evsesCount: 3 },
- heartbeatInterval: Constants.DEFAULT_HEARTBEAT_INTERVAL,
- stationInfo: {
- ocppStrictCompliance: false,
- ocppVersion: OCPPVersion.VERSION_201,
- },
- websocketPingInterval: Constants.DEFAULT_WEBSOCKET_PING_INTERVAL,
- })
+ // Cast to allow setting certificateManager property
+ stationWithCertManager =
+ mockChargingStation as unknown as ChargingStationWithCertificateManager
+ stationWithCertManager.certificateManager = createMockCertificateManager()
- // Cast to allow setting certificateManager property
- const stationWithCertManager =
- mockChargingStation as unknown as ChargingStationWithCertificateManager
- stationWithCertManager.certificateManager = createMockCertificateManager()
+ incomingRequestService = new OCPP20IncomingRequestService()
+ testableService = createTestableIncomingRequestService(incomingRequestService)
+ })
- const incomingRequestService = new OCPP20IncomingRequestService()
- const testableService = createTestableIncomingRequestService(incomingRequestService)
+ afterEach(() => {
+ mock.restoreAll()
+ })
await describe('Request All Certificate Types', async () => {
await it('should return all certificates when no filter is provided', async () => {
*/
import { expect } from '@std/expect'
import { millisecondsToSeconds } from 'date-fns'
-import { afterEach, describe, it } from 'node:test'
+import { afterEach, beforeEach, describe, it } from 'node:test'
import { OCPP20IncomingRequestService } from '../../../../src/charging-station/ocpp/2.0/OCPP20IncomingRequestService.js'
import { OCPP20VariableManager } from '../../../../src/charging-station/ocpp/2.0/OCPP20VariableManager.js'
} from './OCPP20TestUtils.js'
await describe('B06 - Get Variables', async () => {
- const mockChargingStation = createChargingStation({
- baseName: TEST_CHARGING_STATION_BASE_NAME,
- connectorsCount: 3,
- evseConfiguration: { evsesCount: 3 },
- heartbeatInterval: Constants.DEFAULT_HEARTBEAT_INTERVAL,
- stationInfo: {
- ocppStrictCompliance: false,
- ocppVersion: OCPPVersion.VERSION_201,
- },
- websocketPingInterval: Constants.DEFAULT_WEBSOCKET_PING_INTERVAL,
+ let mockChargingStation: ReturnType<typeof createChargingStation>
+ let incomingRequestService: OCPP20IncomingRequestService
+
+ beforeEach(() => {
+ mockChargingStation = createChargingStation({
+ baseName: TEST_CHARGING_STATION_BASE_NAME,
+ connectorsCount: 3,
+ evseConfiguration: { evsesCount: 3 },
+ heartbeatInterval: Constants.DEFAULT_HEARTBEAT_INTERVAL,
+ stationInfo: {
+ ocppStrictCompliance: false,
+ ocppVersion: OCPPVersion.VERSION_201,
+ },
+ websocketPingInterval: Constants.DEFAULT_WEBSOCKET_PING_INTERVAL,
+ })
+ incomingRequestService = new OCPP20IncomingRequestService()
})
- const incomingRequestService = new OCPP20IncomingRequestService()
-
// Reset singleton state after each test to ensure test isolation
afterEach(() => {
OCPP20VariableManager.getInstance().resetRuntimeOverrides()
*/
import { expect } from '@std/expect'
-import { afterEach, describe, it, mock } from 'node:test'
+import { afterEach, beforeEach, describe, it, mock } from 'node:test'
import type { ChargingStationWithCertificateManager } from '../../../../src/charging-station/ocpp/2.0/OCPP20CertificateManager.js'
mock.restoreAll()
})
- const mockChargingStation = createChargingStation({
- baseName: TEST_CHARGING_STATION_BASE_NAME,
- connectorsCount: 3,
- evseConfiguration: { evsesCount: 3 },
- heartbeatInterval: Constants.DEFAULT_HEARTBEAT_INTERVAL,
- stationInfo: {
- ocppStrictCompliance: false,
- ocppVersion: OCPPVersion.VERSION_201,
- },
- websocketPingInterval: Constants.DEFAULT_WEBSOCKET_PING_INTERVAL,
- })
+ let mockChargingStation: ReturnType<typeof createChargingStation>
+ let stationWithCertManager: ChargingStationWithCertificateManager
+ let incomingRequestService: OCPP20IncomingRequestService
+ let testableService: ReturnType<typeof createTestableIncomingRequestService>
+
+ beforeEach(() => {
+ mockChargingStation = createChargingStation({
+ baseName: TEST_CHARGING_STATION_BASE_NAME,
+ connectorsCount: 3,
+ evseConfiguration: { evsesCount: 3 },
+ heartbeatInterval: Constants.DEFAULT_HEARTBEAT_INTERVAL,
+ stationInfo: {
+ ocppStrictCompliance: false,
+ ocppVersion: OCPPVersion.VERSION_201,
+ },
+ websocketPingInterval: Constants.DEFAULT_WEBSOCKET_PING_INTERVAL,
+ })
- // Cast to allow setting certificateManager property
- const stationWithCertManager =
- mockChargingStation as unknown as ChargingStationWithCertificateManager
- stationWithCertManager.certificateManager = createMockCertificateManager()
+ // Cast to allow setting certificateManager property
+ stationWithCertManager =
+ mockChargingStation as unknown as ChargingStationWithCertificateManager
+ stationWithCertManager.certificateManager = createMockCertificateManager()
- const incomingRequestService = new OCPP20IncomingRequestService()
- const testableService = createTestableIncomingRequestService(incomingRequestService)
+ incomingRequestService = new OCPP20IncomingRequestService()
+ testableService = createTestableIncomingRequestService(incomingRequestService)
+ })
await describe('Valid Certificate Installation', async () => {
await it('should accept valid V2GRootCertificate', async () => {
} from './OCPP20TestUtils.js'
await describe('F01 & F02 - Remote Start Transaction', async () => {
- const mockChargingStation = createChargingStation({
- baseName: TEST_CHARGING_STATION_BASE_NAME,
- connectorsCount: 3,
- evseConfiguration: { evsesCount: 3 },
- heartbeatInterval: Constants.DEFAULT_HEARTBEAT_INTERVAL,
- ocppRequestService: {
- requestHandler: async () => Promise.resolve({}),
- },
- stationInfo: {
- ocppStrictCompliance: false,
- ocppVersion: OCPPVersion.VERSION_201,
- },
- websocketPingInterval: Constants.DEFAULT_WEBSOCKET_PING_INTERVAL,
- })
-
- const incomingRequestService = new OCPP20IncomingRequestService()
- const testableService = createTestableIncomingRequestService(incomingRequestService)
-
+ let mockChargingStation: ReturnType<typeof createChargingStation>
+ let incomingRequestService: OCPP20IncomingRequestService
+ let testableService: ReturnType<typeof createTestableIncomingRequestService>
beforeEach(() => {
+ mockChargingStation = createChargingStation({
+ baseName: TEST_CHARGING_STATION_BASE_NAME,
+ connectorsCount: 3,
+ evseConfiguration: { evsesCount: 3 },
+ heartbeatInterval: Constants.DEFAULT_HEARTBEAT_INTERVAL,
+ ocppRequestService: {
+ requestHandler: async () => Promise.resolve({}),
+ },
+ stationInfo: {
+ ocppStrictCompliance: false,
+ ocppVersion: OCPPVersion.VERSION_201,
+ },
+ websocketPingInterval: Constants.DEFAULT_WEBSOCKET_PING_INTERVAL,
+ })
+ incomingRequestService = new OCPP20IncomingRequestService()
+ testableService = createTestableIncomingRequestService(incomingRequestService)
const stationId = mockChargingStation.stationInfo?.chargingStationId ?? 'unknown'
OCPPAuthServiceFactory.setInstanceForTesting(stationId, createMockAuthService())
resetConnectorTransactionState(mockChargingStation)
await describe('F03 - Remote Stop Transaction', async () => {
let sentTransactionEvents: OCPP20TransactionEventRequest[] = []
+ let mockChargingStation: ReturnType<typeof createChargingStation>
+ let incomingRequestService: OCPP20IncomingRequestService
+ let testableService: ReturnType<typeof createTestableIncomingRequestService>
- const mockChargingStation = createChargingStation({
- baseName: TEST_CHARGING_STATION_BASE_NAME,
- connectorsCount: 3,
- evseConfiguration: { evsesCount: 3 },
- heartbeatInterval: Constants.DEFAULT_HEARTBEAT_INTERVAL,
- ocppRequestService: {
- requestHandler: async (
- _chargingStation: unknown,
- commandName: unknown,
- commandPayload: unknown
- ) => {
- if (commandName === OCPP20RequestCommand.TRANSACTION_EVENT) {
- sentTransactionEvents.push(commandPayload as OCPP20TransactionEventRequest)
+ beforeEach(() => {
+ sentTransactionEvents = []
+ mockChargingStation = createChargingStation({
+ baseName: TEST_CHARGING_STATION_BASE_NAME,
+ connectorsCount: 3,
+ evseConfiguration: { evsesCount: 3 },
+ heartbeatInterval: Constants.DEFAULT_HEARTBEAT_INTERVAL,
+ ocppRequestService: {
+ requestHandler: async (
+ _chargingStation: unknown,
+ commandName: unknown,
+ commandPayload: unknown
+ ) => {
+ if (commandName === OCPP20RequestCommand.TRANSACTION_EVENT) {
+ sentTransactionEvents.push(commandPayload as OCPP20TransactionEventRequest)
+ return Promise.resolve({})
+ }
return Promise.resolve({})
- }
- return Promise.resolve({})
+ },
},
- },
- stationInfo: {
- ocppStrictCompliance: false,
- ocppVersion: OCPPVersion.VERSION_201,
- },
- websocketPingInterval: Constants.DEFAULT_WEBSOCKET_PING_INTERVAL,
- })
-
- const incomingRequestService = new OCPP20IncomingRequestService()
- const testableService = createTestableIncomingRequestService(incomingRequestService)
-
- beforeEach(() => {
+ stationInfo: {
+ ocppStrictCompliance: false,
+ ocppVersion: OCPPVersion.VERSION_201,
+ },
+ websocketPingInterval: Constants.DEFAULT_WEBSOCKET_PING_INTERVAL,
+ })
+ incomingRequestService = new OCPP20IncomingRequestService()
+ testableService = createTestableIncomingRequestService(incomingRequestService)
const stationId = mockChargingStation.stationInfo?.chargingStationId ?? 'unknown'
OCPPAuthServiceFactory.setInstanceForTesting(stationId, createMockAuthService())
+ resetLimits(mockChargingStation)
+ resetReportingValueSize(mockChargingStation)
})
afterEach(() => {
OCPPAuthServiceFactory.clearAllInstances()
})
- resetLimits(mockChargingStation)
- resetReportingValueSize(mockChargingStation)
-
/**
* Helper function to reset all connector transaction states
*/
import { TEST_CHARGING_STATION_BASE_NAME } from '../../ChargingStationTestConstants.js'
await describe('B11 & B12 - Reset', async () => {
+ let mockChargingStation: ReturnType<typeof createChargingStation>
+ let mockStation: ReturnType<typeof createChargingStation> & {
+ getNumberOfRunningTransactions: () => number
+ reset: () => Promise<void>
+ }
+ let incomingRequestService: OCPP20IncomingRequestService
+ let testableService: ReturnType<typeof createTestableIncomingRequestService>
+
beforeEach(() => {
mock.timers.enable({ apis: ['setInterval', 'setTimeout', 'setImmediate'] })
+
+ mockChargingStation = createChargingStation({
+ baseName: TEST_CHARGING_STATION_BASE_NAME,
+ connectorsCount: 3,
+ evseConfiguration: { evsesCount: 3 },
+ heartbeatInterval: Constants.DEFAULT_HEARTBEAT_INTERVAL,
+ stationInfo: {
+ ocppStrictCompliance: false,
+ ocppVersion: OCPPVersion.VERSION_201,
+ resetTime: 5000,
+ },
+ websocketPingInterval: Constants.DEFAULT_WEBSOCKET_PING_INTERVAL,
+ })
+
+ // Add missing method to mock using interface extension pattern
+ interface MockChargingStation extends ChargingStation {
+ getNumberOfRunningTransactions: () => number
+ reset: () => Promise<void>
+ }
+ mockStation = mockChargingStation as MockChargingStation
+ mockStation.getNumberOfRunningTransactions = () => 0
+ mockStation.reset = () => Promise.resolve()
+
+ incomingRequestService = new OCPP20IncomingRequestService()
+ testableService = createTestableIncomingRequestService(incomingRequestService)
})
afterEach(() => {
mock.timers.reset()
})
- const mockChargingStation = createChargingStation({
- baseName: TEST_CHARGING_STATION_BASE_NAME,
- connectorsCount: 3,
- evseConfiguration: { evsesCount: 3 },
- heartbeatInterval: Constants.DEFAULT_HEARTBEAT_INTERVAL,
- stationInfo: {
- ocppStrictCompliance: false,
- ocppVersion: OCPPVersion.VERSION_201,
- resetTime: 5000,
- },
- websocketPingInterval: Constants.DEFAULT_WEBSOCKET_PING_INTERVAL,
- })
-
- // Add missing method to mock using interface extension pattern
- interface MockChargingStation extends ChargingStation {
- getNumberOfRunningTransactions: () => number
- reset: () => Promise<void>
- }
- const mockStation = mockChargingStation as MockChargingStation
- mockStation.getNumberOfRunningTransactions = () => 0
- mockStation.reset = () => Promise.resolve()
-
- const incomingRequestService = new OCPP20IncomingRequestService()
- const testableService = createTestableIncomingRequestService(incomingRequestService)
-
await describe('B11 - Reset - Without Ongoing Transaction', async () => {
// FR: B11.FR.01
await it('should handle Reset request with Immediate type when no transactions', async () => {
import { expect } from '@std/expect'
import { millisecondsToSeconds } from 'date-fns'
-import { afterEach, describe, it } from 'node:test'
+import { afterEach, beforeEach, describe, it } from 'node:test'
import { createTestableIncomingRequestService } from '../../../../src/charging-station/ocpp/2.0/__testable__/index.js'
import { OCPP20IncomingRequestService } from '../../../../src/charging-station/ocpp/2.0/OCPP20IncomingRequestService.js'
} from './OCPP20TestUtils.js'
await describe('B05 - Set Variables', async () => {
- const mockChargingStation = createChargingStation({
- baseName: TEST_CHARGING_STATION_BASE_NAME,
- connectorsCount: 3,
- evseConfiguration: { evsesCount: 3 },
- heartbeatInterval: Constants.DEFAULT_HEARTBEAT_INTERVAL,
- stationInfo: {
- ocppStrictCompliance: false,
- ocppVersion: OCPPVersion.VERSION_201,
- },
- websocketPingInterval: Constants.DEFAULT_WEBSOCKET_PING_INTERVAL,
+ let mockChargingStation: ReturnType<typeof createChargingStation>
+ let incomingRequestService: OCPP20IncomingRequestService
+ let testableService: ReturnType<typeof createTestableIncomingRequestService>
+
+ beforeEach(() => {
+ mockChargingStation = createChargingStation({
+ baseName: TEST_CHARGING_STATION_BASE_NAME,
+ connectorsCount: 3,
+ evseConfiguration: { evsesCount: 3 },
+ heartbeatInterval: Constants.DEFAULT_HEARTBEAT_INTERVAL,
+ stationInfo: {
+ ocppStrictCompliance: false,
+ ocppVersion: OCPPVersion.VERSION_201,
+ },
+ websocketPingInterval: Constants.DEFAULT_WEBSOCKET_PING_INTERVAL,
+ })
+ incomingRequestService = new OCPP20IncomingRequestService()
+ testableService = createTestableIncomingRequestService(incomingRequestService)
})
- const incomingRequestService = new OCPP20IncomingRequestService()
- const testableService = createTestableIncomingRequestService(incomingRequestService)
-
// Reset singleton state after each test to ensure test isolation
afterEach(() => {
OCPP20VariableManager.getInstance().resetRuntimeOverrides()
* @description Unit tests for OCPP 2.0 IdToken-first pre-authorization flow (E03)
*/
import { expect } from '@std/expect'
-import { afterEach, describe, it } from 'node:test'
+import { afterEach, beforeEach, describe, it } from 'node:test'
import { OCPP20ServiceUtils } from '../../../../src/charging-station/ocpp/2.0/OCPP20ServiceUtils.js'
import {
* - E02: Cable connection -> EV detection -> Authorization -> Charging
*/
await describe('E03 - IdToken-First Pre-Authorization Flow', async () => {
- const mockChargingStation = createMockOCPP20TransactionTestStation()
+ let mockChargingStation: ReturnType<typeof createMockOCPP20TransactionTestStation>
- // Reset limits and state before tests
- resetLimits(mockChargingStation)
+ beforeEach(() => {
+ mockChargingStation = createMockOCPP20TransactionTestStation()
+ resetLimits(mockChargingStation)
+ })
afterEach(() => {
resetConnectorTransactionState(mockChargingStation)
*/
export const IdTokenFixtures = {
/**
- * Central (server-side) token
- * @param idToken
+ * Central (server-side) token.
+ * @param idToken - The ID token string.
+ * @returns An OCPP20IdTokenType with Central type.
*/
central: (idToken = 'CENTRAL_TOKEN_001'): OCPP20IdTokenType => ({
idToken,
}),
/**
- * eMAID contract identifier token
- * @param idToken
+ * eMAID contract identifier token.
+ * @param idToken - The eMAID token string.
+ * @returns An OCPP20IdTokenType with eMAID type.
*/
emaid: (idToken = 'DE*ABC*E123456*1'): OCPP20IdTokenType => ({
idToken,
}),
/**
- * ISO14443 RFID token (most common type)
- * @param idToken
+ * ISO14443 RFID token (most common type).
+ * @param idToken - The RFID token string.
+ * @returns An OCPP20IdTokenType with ISO14443 type.
*/
iso14443: (idToken = 'TEST_RFID_TOKEN_001'): OCPP20IdTokenType => ({
idToken,
}),
/**
- * ISO15693 RFID token
- * @param idToken
+ * ISO15693 RFID token.
+ * @param idToken - The ISO15693 token string.
+ * @returns An OCPP20IdTokenType with ISO15693 type.
*/
iso15693: (idToken = 'TEST_ISO15693_001'): OCPP20IdTokenType => ({
idToken,
type: OCPP20IdTokenEnumType.ISO15693,
}),
- /** NoAuthorization token (free charging) */
+ /**
+ * NoAuthorization token (free charging).
+ * @returns An OCPP20IdTokenType with NoAuthorization type.
+ */
noAuth: (): OCPP20IdTokenType => ({
idToken: '',
type: OCPP20IdTokenEnumType.NoAuthorization,
// ===== Local Authorization Contexts =====
/**
- * Abnormal condition (with optional condition type)
- * @param condition
+ * Abnormal condition (with optional condition type).
+ * @param condition - The abnormal condition type.
+ * @returns An OCPP20TransactionContext for abnormal conditions.
*/
abnormalCondition: (condition = 'OverCurrent'): OCPP20TransactionContext => ({
abnormalCondition: condition,
source: 'abnormal_condition',
}),
- /** Cable plugged in (E02 cable-first start) */
+ /**
+ * Cable plugged in (E02 cable-first start).
+ * @returns An OCPP20TransactionContext for cable plugged in.
+ */
cablePluggedIn: (): OCPP20TransactionContext => ({
cableState: 'plugged_in',
source: 'cable_action',
}),
- /** Deauthorization (token revoked or invalid) */
+ /**
+ * Deauthorization (token revoked or invalid).
+ * @returns An OCPP20TransactionContext for deauthorization.
+ */
deauthorized: (): OCPP20TransactionContext => ({
authorizationMethod: 'idToken',
isDeauthorized: true,
// ===== Cable Action Contexts (E02 flow) =====
- /** Energy limit reached */
+ /**
+ * Energy limit reached.
+ * @returns An OCPP20TransactionContext for energy limit reached.
+ */
energyLimitReached: (): OCPP20TransactionContext => ({
source: 'energy_limit',
}),
- /** EV communication lost */
+ /**
+ * EV communication lost.
+ * @returns An OCPP20TransactionContext for EV communication lost.
+ */
evCommunicationLost: (): OCPP20TransactionContext => ({
source: 'system_event',
systemEvent: 'ev_communication_lost',
}),
- /** EV connect timeout */
+ /**
+ * EV connect timeout.
+ * @returns An OCPP20TransactionContext for EV connect timeout.
+ */
evConnectTimeout: (): OCPP20TransactionContext => ({
source: 'system_event',
systemEvent: 'ev_connect_timeout',
// ===== Remote Command Contexts =====
- /** Cable unplugged / EV departed */
+ /**
+ * Cable unplugged / EV departed.
+ * @returns An OCPP20TransactionContext for EV departure.
+ */
evDeparted: (): OCPP20TransactionContext => ({
cableState: 'unplugged',
source: 'cable_action',
}),
- /** EV detected after cable connection */
+ /**
+ * EV detected after cable connection.
+ * @returns An OCPP20TransactionContext for EV detection.
+ */
evDetected: (): OCPP20TransactionContext => ({
cableState: 'detected',
source: 'cable_action',
}),
/**
- * IdToken-first authorization (E03 flow start)
- * @param authorizationMethod
+ * IdToken-first authorization (E03 flow start).
+ * @param authorizationMethod - The authorization method used.
+ * @returns An OCPP20TransactionContext for IdToken authorization.
*/
idTokenAuthorized: (
authorizationMethod: 'groupIdToken' | 'idToken' = 'idToken'
source: 'local_authorization',
}),
- /** Clock-aligned meter value */
+ /**
+ * Clock-aligned meter value.
+ * @returns An OCPP20TransactionContext for clock-aligned meter values.
+ */
meterValueClock: (): OCPP20TransactionContext => ({
isPeriodicMeterValue: false,
source: 'meter_value',
}),
- /** Periodic meter value (sampled interval) */
+ /**
+ * Periodic meter value (sampled interval).
+ * @returns An OCPP20TransactionContext for periodic meter values.
+ */
meterValuePeriodic: (): OCPP20TransactionContext => ({
isPeriodicMeterValue: true,
source: 'meter_value',
// ===== Meter Value Contexts =====
- /** Remote start transaction request */
+ /**
+ * Remote start transaction request.
+ * @returns An OCPP20TransactionContext for remote start.
+ */
remoteStart: (): OCPP20TransactionContext => ({
command: 'RequestStartTransaction',
source: 'remote_command',
}),
- /** Remote stop transaction request */
+ /**
+ * Remote stop transaction request.
+ * @returns An OCPP20TransactionContext for remote stop.
+ */
remoteStop: (): OCPP20TransactionContext => ({
command: 'RequestStopTransaction',
source: 'remote_command',
}),
- /** Reset command */
+ /**
+ * Reset command.
+ * @returns An OCPP20TransactionContext for reset.
+ */
reset: (): OCPP20TransactionContext => ({
command: 'Reset',
source: 'remote_command',
// ===== System Event Contexts =====
- /** Signed data received */
+ /**
+ * Signed data received.
+ * @returns An OCPP20TransactionContext for signed data.
+ */
signedData: (): OCPP20TransactionContext => ({
isSignedDataReceived: true,
source: 'meter_value',
}),
- /** Stop authorized by local token presentation */
+ /**
+ * Stop authorized by local token presentation.
+ * @returns An OCPP20TransactionContext for stop authorization.
+ */
stopAuthorized: (): OCPP20TransactionContext => ({
authorizationMethod: 'stopAuthorized',
source: 'local_authorization',
// ===== Limit Contexts =====
- /** Time limit reached */
+ /**
+ * Time limit reached.
+ * @returns An OCPP20TransactionContext for time limit.
+ */
timeLimitReached: (): OCPP20TransactionContext => ({
source: 'time_limit',
}),
- /** Trigger message command */
+ /**
+ * Trigger message command.
+ * @returns An OCPP20TransactionContext for trigger message.
+ */
triggerMessage: (): OCPP20TransactionContext => ({
command: 'TriggerMessage',
source: 'remote_command',
// ===== Abnormal Condition Contexts =====
- /** Unlock connector command */
+ /**
+ * Unlock connector command.
+ * @returns An OCPP20TransactionContext for unlock connector.
+ */
unlockConnector: (): OCPP20TransactionContext => ({
command: 'UnlockConnector',
source: 'remote_command',
import { expect } from '@std/expect'
import { millisecondsToSeconds } from 'date-fns'
-import { afterEach, describe, it } from 'node:test'
+import { afterEach, beforeEach, describe, it } from 'node:test'
import {
deleteConfigurationKey,
}
await describe('B05/B06 - OCPP20VariableManager test suite', async () => {
- // Create mock ChargingStation with EVSEs for OCPP 2.0 testing
- const mockChargingStation = createChargingStation({
- baseName: TEST_CHARGING_STATION_BASE_NAME,
- connectorsCount: 3,
- evseConfiguration: { evsesCount: 3 },
- heartbeatInterval: Constants.DEFAULT_HEARTBEAT_INTERVAL,
- stationInfo: {
- ocppVersion: OCPPVersion.VERSION_201,
- },
- websocketPingInterval: Constants.DEFAULT_WEBSOCKET_PING_INTERVAL,
+ // Type declaration for mock ChargingStation
+ let mockChargingStation: ReturnType<typeof createChargingStation>
+
+ // Initialize mock ChargingStation before each test
+ beforeEach(() => {
+ mockChargingStation = createChargingStation({
+ baseName: TEST_CHARGING_STATION_BASE_NAME,
+ connectorsCount: 3,
+ evseConfiguration: { evsesCount: 3 },
+ heartbeatInterval: Constants.DEFAULT_HEARTBEAT_INTERVAL,
+ stationInfo: {
+ ocppVersion: OCPPVersion.VERSION_201,
+ },
+ websocketPingInterval: Constants.DEFAULT_WEBSOCKET_PING_INTERVAL,
+ })
})
// Reset singleton state after each test to ensure test isolation