*/
export const TEST_TRANSACTION_ID = 1
export const TEST_TRANSACTION_ID_STRING = 'tx-ocpp20-1'
+export const TEST_TRANSACTION_UUID = '00000000-0000-0000-0000-000000000001'
export const TEST_TRANSACTION_ENERGY_WH = 5000
/**
await it('should contain 56 connector-level transitions', () => {
const transitions = OCPP16Constants.ChargePointStatusConnectorTransitions
- assert.ok(transitions.length >= 56)
+ assert.ok(transitions.length >= 56, 'should contain at least 56 connector-level transitions')
})
await it('should have transitions with correct structure', () => {
// Assert
assert.notStrictEqual(response.configurationKey, undefined)
assert.notStrictEqual(response.unknownKey, undefined)
- assert.ok(response.configurationKey.length >= 2)
+ assert.ok(response.configurationKey.length >= 2, 'should return at least 2 configuration keys')
const heartbeatKey = response.configurationKey.find(
k => k.key === (OCPP16StandardParametersKey.HeartbeatInterval as string)
)
const getResponse = testableService.handleRequestGetConfiguration(station, {})
// Assert — All visible keys returned with correct values
- assert.ok(getResponse.configurationKey.length >= 3)
+ assert.ok(
+ getResponse.configurationKey.length >= 3,
+ 'should return at least 3 configuration keys'
+ )
assert.strictEqual(getResponse.unknownKey.length, 0)
const heartbeat = getResponse.configurationKey.find(
OCPPVersion,
} from '../../../../src/types/index.js'
import { standardCleanup } from '../../../helpers/TestLifecycleHelpers.js'
+import { TEST_CHARGING_STATION_BASE_NAME, TEST_ID_TAG } from '../../ChargingStationTestConstants.js'
import { createMockChargingStation } from '../../ChargingStationTestUtils.js'
import { getTestAuthCache } from '../auth/helpers/MockFactories.js'
import { createCommandsSupport, createMeterValuesTemplate } from './OCPP16TestUtils.js'
assert.strictEqual(result.chargingSchedulePeriod.length, 2)
// Should be sorted by startPeriod
const periods = result.chargingSchedulePeriod
- assert.ok(periods[0].startPeriod <= periods[1].startPeriod)
+ assert.ok(
+ periods[0].startPeriod <= periods[1].startPeriod,
+ 'periods should be sorted by startPeriod'
+ )
})
})
// ─── updateAuthorizationCache ──────────────────────────────────────────
await describe('updateAuthorizationCache', async () => {
- const TEST_ID_TAG = 'TEST_RFID_001'
-
afterEach(() => {
OCPPAuthServiceFactory.clearAllInstances()
})
const { station } = createMockChargingStation({
ocppVersion: OCPPVersion.VERSION_16,
stationInfo: {
- chargingStationId: 'CS_CACHE_TEST_01',
+ chargingStationId: TEST_CHARGING_STATION_BASE_NAME,
ocppVersion: OCPPVersion.VERSION_16,
},
})
const { station } = createMockChargingStation({
ocppVersion: OCPPVersion.VERSION_16,
stationInfo: {
- chargingStationId: 'CS_CACHE_TEST_02',
+ chargingStationId: TEST_CHARGING_STATION_BASE_NAME,
ocppVersion: OCPPVersion.VERSION_16,
},
})
const { station } = createMockChargingStation({
ocppVersion: OCPPVersion.VERSION_16,
stationInfo: {
- chargingStationId: 'CS_CACHE_TEST_03',
+ chargingStationId: TEST_CHARGING_STATION_BASE_NAME,
ocppVersion: OCPPVersion.VERSION_16,
},
})
const { station } = createMockChargingStation({
ocppVersion: OCPPVersion.VERSION_16,
stationInfo: {
- chargingStationId: 'CS_CACHE_TEST_04',
+ chargingStationId: TEST_CHARGING_STATION_BASE_NAME,
ocppVersion: OCPPVersion.VERSION_16,
},
})
const { station } = createMockChargingStation({
ocppVersion: OCPPVersion.VERSION_16,
stationInfo: {
- chargingStationId: 'CS_CACHE_TEST_05',
+ chargingStationId: TEST_CHARGING_STATION_BASE_NAME,
ocppVersion: OCPPVersion.VERSION_16,
},
})
for (const line of contentLines.slice(0, -1)) {
assert.strictEqual(line.length, 64)
}
- assert.ok(contentLines[contentLines.length - 1].length <= 64)
+ assert.ok(
+ contentLines[contentLines.length - 1].length <= 64,
+ 'last line length should be at most 64 characters'
+ )
})
})
})
InstallCertificateUseEnumType,
} from '../../../../src/types/index.js'
import { standardCleanup } from '../../../helpers/TestLifecycleHelpers.js'
+import { TEST_CHARGING_STATION_HASH_ID } from '../../ChargingStationTestConstants.js'
import {
EMPTY_PEM_CERTIFICATE,
EXPIRED_X509_PEM_CERTIFICATE,
VALID_X509_PEM_CERTIFICATE,
} from './OCPP20CertificateTestData.js'
-const TEST_STATION_HASH_ID = 'test-station-hash-12345'
const TEST_CERT_TYPE = InstallCertificateUseEnumType.CSMSRootCertificate
await describe('I02-I04 - ISO15118 Certificate Management', async () => {
afterEach(async () => {
- await rm(`dist/assets/configurations/${TEST_STATION_HASH_ID}`, {
+ await rm(`dist/assets/configurations/${TEST_CHARGING_STATION_HASH_ID}`, {
force: true,
recursive: true,
})
await it('should store a valid PEM certificate to the correct path', async () => {
const result = await manager.storeCertificate(
- TEST_STATION_HASH_ID,
+ TEST_CHARGING_STATION_HASH_ID,
TEST_CERT_TYPE,
VALID_PEM_CERTIFICATE_EXTENDED
)
if (result.filePath == null) {
assert.fail('Expected filePath to be defined')
}
- assert.ok(result.filePath.includes(TEST_STATION_HASH_ID))
+ assert.ok(result.filePath.includes(TEST_CHARGING_STATION_HASH_ID))
assert.ok(result.filePath.includes('certs'))
assert.match(result.filePath, /\.pem$/)
})
await it('should reject invalid PEM certificate without BEGIN/END markers', async () => {
const result = await manager.storeCertificate(
- TEST_STATION_HASH_ID,
+ TEST_CHARGING_STATION_HASH_ID,
TEST_CERT_TYPE,
INVALID_PEM_CERTIFICATE_MISSING_MARKERS
)
await it('should reject empty certificate data', async () => {
const result = await manager.storeCertificate(
- TEST_STATION_HASH_ID,
+ TEST_CHARGING_STATION_HASH_ID,
TEST_CERT_TYPE,
EMPTY_PEM_CERTIFICATE
)
await it('should create certificate directory structure if not exists', async () => {
const result = await manager.storeCertificate(
- TEST_STATION_HASH_ID,
+ TEST_CHARGING_STATION_HASH_ID,
InstallCertificateUseEnumType.V2GRootCertificate,
VALID_PEM_CERTIFICATE_EXTENDED
)
serialNumber: 'SN-12345',
}
- const result = await manager.deleteCertificate(TEST_STATION_HASH_ID, hashData)
+ const result = await manager.deleteCertificate(TEST_CHARGING_STATION_HASH_ID, hashData)
assert.notStrictEqual(result, undefined)
assert.notStrictEqual(result.status, undefined)
serialNumber: 'NON-EXISTENT-SN',
}
- const result = await manager.deleteCertificate(TEST_STATION_HASH_ID, hashData)
+ const result = await manager.deleteCertificate(TEST_CHARGING_STATION_HASH_ID, hashData)
assert.notStrictEqual(result, undefined)
assert.strictEqual(result.status, DeleteCertificateStatusEnumType.NotFound)
manager = new OCPP20CertificateManager()
})
await it('should return list of installed certificates for station', async () => {
- const result = await manager.getInstalledCertificates(TEST_STATION_HASH_ID)
+ const result = await manager.getInstalledCertificates(TEST_CHARGING_STATION_HASH_ID)
assert.notStrictEqual(result, undefined)
assert.ok(Array.isArray(result.certificateHashDataChain))
await it('should filter certificates by type when filter provided', async () => {
const filterTypes = [InstallCertificateUseEnumType.CSMSRootCertificate]
- const result = await manager.getInstalledCertificates(TEST_STATION_HASH_ID, filterTypes)
+ const result = await manager.getInstalledCertificates(
+ TEST_CHARGING_STATION_HASH_ID,
+ filterTypes
+ )
assert.notStrictEqual(result, undefined)
assert.ok(Array.isArray(result.certificateHashDataChain))
InstallCertificateUseEnumType.V2GRootCertificate,
InstallCertificateUseEnumType.ManufacturerRootCertificate,
]
- const result = await manager.getInstalledCertificates(TEST_STATION_HASH_ID, filterTypes)
+ const result = await manager.getInstalledCertificates(
+ TEST_CHARGING_STATION_HASH_ID,
+ filterTypes
+ )
assert.notStrictEqual(result, undefined)
assert.ok(Array.isArray(result.certificateHashDataChain))
manager = new OCPP20CertificateManager()
})
await it('should return correct file path for certificate', () => {
- const path = manager.getCertificatePath(TEST_STATION_HASH_ID, TEST_CERT_TYPE, 'SERIAL-12345')
+ const path = manager.getCertificatePath(
+ TEST_CHARGING_STATION_HASH_ID,
+ TEST_CERT_TYPE,
+ 'SERIAL-12345'
+ )
assert.notStrictEqual(path, undefined)
- assert.ok(path.includes(TEST_STATION_HASH_ID))
+ assert.ok(path.includes(TEST_CHARGING_STATION_HASH_ID))
assert.ok(path.includes('certs'))
assert.ok(path.includes('CSMSRootCertificate'))
assert.ok(path.includes('SERIAL-12345'))
await it('should handle special characters in serial number', () => {
const path = manager.getCertificatePath(
- TEST_STATION_HASH_ID,
+ TEST_CHARGING_STATION_HASH_ID,
TEST_CERT_TYPE,
'SERIAL:ABC/123'
)
await it('should return different paths for different certificate types', () => {
const csmsPath = manager.getCertificatePath(
- TEST_STATION_HASH_ID,
+ TEST_CHARGING_STATION_HASH_ID,
InstallCertificateUseEnumType.CSMSRootCertificate,
'SERIAL-001'
)
const v2gPath = manager.getCertificatePath(
- TEST_STATION_HASH_ID,
+ TEST_CHARGING_STATION_HASH_ID,
InstallCertificateUseEnumType.V2GRootCertificate,
'SERIAL-001'
)
})
await it('should return path following project convention', () => {
- const path = manager.getCertificatePath(TEST_STATION_HASH_ID, TEST_CERT_TYPE, 'SERIAL-12345')
+ const path = manager.getCertificatePath(
+ TEST_CHARGING_STATION_HASH_ID,
+ TEST_CERT_TYPE,
+ 'SERIAL-12345'
+ )
assert.match(path, /configurations/)
assert.match(path, /certs/)
await it('should handle concurrent certificate operations', async () => {
const results = await Promise.all([
manager.storeCertificate(
- TEST_STATION_HASH_ID,
+ TEST_CHARGING_STATION_HASH_ID,
InstallCertificateUseEnumType.CSMSRootCertificate,
VALID_PEM_CERTIFICATE_EXTENDED
),
manager.storeCertificate(
- TEST_STATION_HASH_ID,
+ TEST_CHARGING_STATION_HASH_ID,
InstallCertificateUseEnumType.V2GRootCertificate,
VALID_PEM_CERTIFICATE_EXTENDED
),
- manager.getInstalledCertificates(TEST_STATION_HASH_ID),
+ manager.getInstalledCertificates(TEST_CHARGING_STATION_HASH_ID),
])
assert.strictEqual(results.length, 3)
await it('should handle very long certificate chains', async () => {
const longChain = Array(5).fill(VALID_PEM_CERTIFICATE_EXTENDED).join('\n')
- const result = await manager.storeCertificate(TEST_STATION_HASH_ID, TEST_CERT_TYPE, longChain)
+ const result = await manager.storeCertificate(
+ TEST_CHARGING_STATION_HASH_ID,
+ TEST_CERT_TYPE,
+ longChain
+ )
assert.notStrictEqual(result, undefined)
})
assert.fail('Expected statusInfo to be defined')
}
assert.strictEqual(typeof response.statusInfo.reasonCode, 'string')
- assert.ok(response.statusInfo.reasonCode.length > 0)
- assert.ok(response.statusInfo.reasonCode.length <= 20)
+ assert.ok(response.statusInfo.reasonCode.length > 0, 'reasonCode should not be empty')
+ assert.ok(
+ response.statusInfo.reasonCode.length <= 20,
+ 'reasonCode length should be at most 20 characters'
+ )
})
})
const evseStatus = station.getEvseStatus(1)
assert.strictEqual(evseStatus?.availability, OCPP20OperationalStatusEnumType.Inoperative)
await flushMicrotasks()
- assert.ok(requestHandlerMock.mock.callCount() >= 1)
+ assert.ok(
+ requestHandlerMock.mock.callCount() >= 1,
+ 'request handler should have been called at least once'
+ )
const args = requestHandlerMock.mock.calls[0].arguments as [unknown, string]
assert.strictEqual(args[1], OCPP20RequestCommand.STATUS_NOTIFICATION)
})
assert.fail('Expected statusInfo to be defined')
}
assert.strictEqual(typeof response.statusInfo.reasonCode, 'string')
- assert.ok(response.statusInfo.reasonCode.length > 0)
- assert.ok(response.statusInfo.reasonCode.length <= 20)
+ assert.ok(response.statusInfo.reasonCode.length > 0, 'reasonCode should not be empty')
+ assert.ok(
+ response.statusInfo.reasonCode.length <= 20,
+ 'reasonCode length should be at most 20 characters'
+ )
})
})
)
assert.ok(Array.isArray(reportData))
- assert.ok(reportData.length > 0)
+ assert.ok(reportData.length > 0, 'report data should not be empty')
// Check that each report data item has the expected structure
for (const item of reportData) {
const reportData = testableService.buildReportData(station, ReportBaseEnumType.FullInventory)
assert.ok(Array.isArray(reportData))
- assert.ok(reportData.length > 0)
+ assert.ok(reportData.length > 0, 'report data should not be empty')
// Check for station info variables
const modelVariable = reportData.find(
const reportData = testableService.buildReportData(station, ReportBaseEnumType.SummaryInventory)
assert.ok(Array.isArray(reportData))
- assert.ok(reportData.length > 0)
+ assert.ok(reportData.length > 0, 'report data should not be empty')
// Check for availability state variable
const availabilityVariable = reportData.find(
await it('should handle GetBaseReport with EVSE structure', () => {
// Create a station with EVSEs
const { station: stationWithEvses } = createMockChargingStation({
- baseName: 'CS-EVSE-001',
+ baseName: TEST_CHARGING_STATION_BASE_NAME,
connectorsCount: 3,
evseConfiguration: { evsesCount: 3 },
stationInfo: {
)
assert.ok(Array.isArray(reportData))
- assert.ok(reportData.length > 0)
+ assert.ok(reportData.length > 0, 'report data should not be empty')
// Check if EVSE components are included when EVSEs exist
const evseComponents = reportData.filter(
(item: ReportDataType) => item.component.name === (OCPP20ComponentName.EVSE as string)
)
if (stationWithEvses.hasEvses) {
- assert.ok(evseComponents.length > 0)
+ assert.ok(evseComponents.length > 0, 'should include EVSE components')
}
})
setStrictLimits(station, 100, limit)
const response = incomingRequestService.handleRequestGetVariables(station, request)
const actualSize = Buffer.byteLength(JSON.stringify(response.getVariableResult), 'utf8')
- assert.ok(actualSize > limit)
+ assert.ok(actualSize > limit, 'response size should exceed limit')
assert.strictEqual(response.getVariableResult.length, request.getVariableData.length)
response.getVariableResult.forEach(r => {
assert.strictEqual(r.attributeStatus, GetVariableStatusEnumType.Rejected)
if (result.attributeValue == null) {
assert.fail('Expected attributeValue to be defined')
}
- assert.ok(result.attributeValue.length <= 3)
+ assert.ok(
+ result.attributeValue.length <= 3,
+ 'attributeValue should be truncated to at most 3 characters'
+ )
resetReportingValueSize(station)
})
})
assert.fail('Expected statusInfo to be defined')
}
assert.strictEqual(typeof response.statusInfo.reasonCode, 'string')
- assert.ok(response.statusInfo.reasonCode.length > 0)
- assert.ok(response.statusInfo.reasonCode.length <= 20)
+ assert.ok(response.statusInfo.reasonCode.length > 0, 'reasonCode should not be empty')
+ assert.ok(
+ response.statusInfo.reasonCode.length <= 20,
+ 'reasonCode length should be at most 20 characters'
+ )
})
})
})
// Then: Charging station should have required configuration
assert.notStrictEqual(mockStation, undefined)
assert.notStrictEqual(mockStation.getNumberOfEvses(), 0)
- assert.ok(mockStation.getNumberOfEvses() > 0)
+ assert.ok(mockStation.getNumberOfEvses() > 0, 'should have at least one EVSE')
assert.strictEqual(mockStation.stationInfo?.ocppVersion, OCPPVersion.VERSION_201)
})
})
if (response.transactionId == null) {
assert.fail('Expected transactionId to be defined')
}
- assert.ok(response.transactionId.length > 0)
+ assert.ok(response.transactionId.length > 0, 'transactionId should not be empty')
})
await describe('REQUEST_START_TRANSACTION event listener', async () => {
postCalcLimit.toString(),
false
)
- assert.ok(preEstimate < postCalcLimit)
+ assert.ok(preEstimate < postCalcLimit, 'pre-estimate should be less than post-calc limit')
const response: { setVariableResult: OCPP20SetVariableResultType[] } =
testableService.handleRequestSetVariables(mockStation, request)
const actualSize = Buffer.byteLength(JSON.stringify(response.setVariableResult), 'utf8')
- assert.ok(actualSize > postCalcLimit)
+ assert.ok(actualSize > postCalcLimit, 'actual response size should exceed post-calc limit')
assert.strictEqual(response.setVariableResult.length, request.setVariableData.length)
response.setVariableResult.forEach(r => {
assert.strictEqual(r.attributeStatus, SetVariableStatusEnumType.Rejected)
assert.strictEqual(sendMessageMock.mock.calls.length, 1)
const sentPayload = sendMessageMock.mock.calls[0]
.arguments[2] as OCPP20TransactionEventRequest
- assert.ok(sentPayload.transactionInfo.transactionId.length > 0)
+ assert.ok(
+ sentPayload.transactionInfo.transactionId.length > 0,
+ 'transactionId should not be empty'
+ )
})
await it('should default triggerReason to Authorized for Started when not provided', async () => {
assert.strictEqual(sendMessageMock.mock.calls.length, 1)
const sentPayload = sendMessageMock.mock.calls[0]
.arguments[2] as OCPP20TransactionEventRequest
- assert.ok(sentPayload.transactionInfo.transactionId.length > 0)
+ assert.ok(
+ sentPayload.transactionInfo.transactionId.length > 0,
+ 'transactionId should not be empty'
+ )
assert.strictEqual(sentPayload.eventType, OCPP20TransactionEventEnumType.Started)
})
})
TEST_CHARGE_POINT_MODEL,
TEST_CHARGE_POINT_SERIAL_NUMBER,
TEST_CHARGE_POINT_VENDOR,
+ TEST_CHARGING_STATION_BASE_NAME,
TEST_FIRMWARE_VERSION,
} from '../../ChargingStationTestConstants.js'
import { createMockChargingStation } from '../../ChargingStationTestUtils.js'
// FR: G02.FR.05
await it('should handle HeartBeat request with different charging station configurations', () => {
const { station: alternativeChargingStation } = createMockChargingStation({
- baseName: 'CS-ALTERNATIVE-002',
+ baseName: TEST_CHARGING_STATION_BASE_NAME,
connectorsCount: 3,
evseConfiguration: { evsesCount: 3 },
heartbeatInterval: 120,
assert.notStrictEqual(response, undefined)
assert.strictEqual(response.status, GenericStatus.Accepted)
- assert.ok(sendMessageMock.mock.calls.length > 0)
+ assert.ok(
+ sendMessageMock.mock.calls.length > 0,
+ 'sendMessage should have been called at least once'
+ )
const sentPayload = sendMessageMock.mock.calls[0].arguments[2] as OCPP20SignCertificateRequest
assert.notStrictEqual(sentPayload.csr, undefined)
assert.strictEqual(typeof sentPayload, 'object')
assert.notStrictEqual(sentPayload.csr, undefined)
assert.strictEqual(typeof sentPayload.csr, 'string')
- assert.ok(sentPayload.csr.length > 0)
- assert.ok(sentPayload.csr.length <= 5500)
+ assert.ok(sentPayload.csr.length > 0, 'CSR should not be empty')
+ assert.ok(sentPayload.csr.length <= 5500, 'CSR length should be at most 5500 characters')
})
await it('should send SIGN_CERTIFICATE command name', async () => {
assert.notStrictEqual(payload, undefined)
assert.ok(payload.timestamp instanceof Date)
- assert.ok(payload.timestamp.getTime() >= beforeBuild.getTime())
+ assert.ok(
+ payload.timestamp.getTime() >= beforeBuild.getTime(),
+ 'timestamp should be at or after build start time'
+ )
})
})
})
} from '../../../../src/charging-station/ocpp/auth/index.js'
import { OCPPVersion } from '../../../../src/types/index.js'
import { standardCleanup } from '../../../helpers/TestLifecycleHelpers.js'
+import {
+ TEST_CHARGING_STATION_BASE_NAME,
+ TEST_TOKEN_ISO14443,
+} from '../../ChargingStationTestConstants.js'
import { createMockChargingStation } from '../../ChargingStationTestUtils.js'
import { getTestAuthCache } from '../auth/helpers/MockFactories.js'
-const TEST_IDENTIFIER = 'TEST_RFID_TOKEN_001'
-const TEST_STATION_ID = 'CS_CACHE_UPDATE_TEST'
-
await describe('C10 - TransactionEventResponse Cache Update', async () => {
let station: ChargingStation
let authService: OCPPAuthServiceImpl
beforeEach(() => {
const { station: mockStation } = createMockChargingStation({
- baseName: TEST_STATION_ID,
+ baseName: TEST_CHARGING_STATION_BASE_NAME,
connectorsCount: 1,
stationInfo: {
- chargingStationId: TEST_STATION_ID,
+ chargingStationId: TEST_CHARGING_STATION_BASE_NAME,
ocppVersion: OCPPVersion.VERSION_201,
},
})
await it('C10.FR.05 - should update cache on TransactionEventResponse with Accepted idTokenInfo', () => {
// Act
authService.updateCacheEntry(
- TEST_IDENTIFIER,
+ TEST_TOKEN_ISO14443,
AuthorizationStatus.ACCEPTED,
undefined,
IdentifierType.ISO14443
)
// Assert
- const cached = authCache.get(TEST_IDENTIFIER)
+ const cached = authCache.get(TEST_TOKEN_ISO14443)
assert.ok(cached != null, 'Cache entry should exist')
assert.strictEqual(cached.status, AuthorizationStatus.ACCEPTED)
})
// Act
authService.updateCacheEntry(
- TEST_IDENTIFIER,
+ TEST_TOKEN_ISO14443,
AuthorizationStatus.ACCEPTED,
futureDate,
IdentifierType.ISO14443
)
// Assert
- const cached = authCache.get(TEST_IDENTIFIER)
+ const cached = authCache.get(TEST_TOKEN_ISO14443)
assert.ok(cached != null, 'Cache entry should exist with explicit TTL')
assert.strictEqual(cached.status, AuthorizationStatus.ACCEPTED)
})
await it('C10.FR.08 - should use AuthCacheLifeTime as TTL when cacheExpiryDateTime absent', () => {
// Act — no expiryDate, uses config.authorizationCacheLifetime
authService.updateCacheEntry(
- TEST_IDENTIFIER,
+ TEST_TOKEN_ISO14443,
AuthorizationStatus.ACCEPTED,
undefined,
IdentifierType.ISO14443
)
// Assert
- const cached = authCache.get(TEST_IDENTIFIER)
+ const cached = authCache.get(TEST_TOKEN_ISO14443)
assert.ok(cached != null, 'Cache entry should exist with default TTL')
assert.strictEqual(cached.status, AuthorizationStatus.ACCEPTED)
})
// Act
authService.updateCacheEntry(
- TEST_IDENTIFIER,
+ TEST_TOKEN_ISO14443,
AuthorizationStatus.ACCEPTED,
pastDate,
IdentifierType.ISO14443
)
// Assert
- const cached = authCache.get(TEST_IDENTIFIER)
+ const cached = authCache.get(TEST_TOKEN_ISO14443)
assert.strictEqual(cached, undefined, 'Expired entry must not be cached')
})
await it('should not update cache when authorizationCacheEnabled is false', () => {
// Arrange — create service with cache disabled
const { station: disabledStation } = createMockChargingStation({
- baseName: 'CS_CACHE_DISABLED',
+ baseName: TEST_CHARGING_STATION_BASE_NAME,
connectorsCount: 1,
stationInfo: {
- chargingStationId: 'CS_CACHE_DISABLED',
+ chargingStationId: TEST_CHARGING_STATION_BASE_NAME,
ocppVersion: OCPPVersion.VERSION_201,
},
})
// Act
disabledService.updateCacheEntry(
- TEST_IDENTIFIER,
+ TEST_TOKEN_ISO14443,
AuthorizationStatus.ACCEPTED,
undefined,
IdentifierType.ISO14443
// Assert
const disabledCache = getTestAuthCache(disabledService)
- const cached = disabledCache.get(TEST_IDENTIFIER)
+ const cached = disabledCache.get(TEST_TOKEN_ISO14443)
assert.strictEqual(cached, undefined, 'Cache entry should not exist when cache is disabled')
})
})
setupConnectorWithTransaction,
standardCleanup,
} from '../../../helpers/TestLifecycleHelpers.js'
-import { TEST_CHARGING_STATION_BASE_NAME } from '../../ChargingStationTestConstants.js'
+import {
+ TEST_CHARGING_STATION_BASE_NAME,
+ TEST_TRANSACTION_UUID,
+} from '../../ChargingStationTestConstants.js'
import { createMockChargingStation } from '../../ChargingStationTestUtils.js'
-/** UUID used as transactionId in all tests — must match connector.transactionId */
-const TEST_TRANSACTION_ID: UUIDv4 = '00000000-0000-0000-0000-000000000001'
-
interface TestableOCPP20ResponseService {
handleResponseTransactionEvent: (
chargingStation: ChargingStation,
// Override with UUID string so getConnectorIdByTransactionId can find it
const connectorStatus = station.getConnectorStatus(1)
if (connectorStatus != null) {
- connectorStatus.transactionId = TEST_TRANSACTION_ID
+ connectorStatus.transactionId = TEST_TRANSACTION_UUID
}
const responseService = new OCPP20ResponseService()
testable = createTestableResponseService(responseService)
status: OCPP20AuthorizationStatusEnumType.Accepted,
},
}
- const requestPayload = buildTransactionEventRequest(TEST_TRANSACTION_ID)
+ const requestPayload = buildTransactionEventRequest(TEST_TRANSACTION_UUID)
// Act
testable.handleResponseTransactionEvent(station, payload, requestPayload)
status: OCPP20AuthorizationStatusEnumType.Invalid,
},
}
- const requestPayload = buildTransactionEventRequest(TEST_TRANSACTION_ID)
+ const requestPayload = buildTransactionEventRequest(TEST_TRANSACTION_UUID)
// Act
testable.handleResponseTransactionEvent(station, payload, requestPayload)
status: OCPP20AuthorizationStatusEnumType.Blocked,
},
}
- const requestPayload = buildTransactionEventRequest(TEST_TRANSACTION_ID)
+ const requestPayload = buildTransactionEventRequest(TEST_TRANSACTION_UUID)
// Act
testable.handleResponseTransactionEvent(station, payload, requestPayload)
const payload: OCPP20TransactionEventResponse = {
chargingPriority: 5,
}
- const requestPayload = buildTransactionEventRequest(TEST_TRANSACTION_ID)
+ const requestPayload = buildTransactionEventRequest(TEST_TRANSACTION_UUID)
// Act
testable.handleResponseTransactionEvent(station, payload, requestPayload)
() => Promise.resolve({} as OCPP20TransactionEventResponse)
)
const payload: OCPP20TransactionEventResponse = {}
- const requestPayload = buildTransactionEventRequest(TEST_TRANSACTION_ID)
+ const requestPayload = buildTransactionEventRequest(TEST_TRANSACTION_UUID)
// Act
testable.handleResponseTransactionEvent(station, payload, requestPayload)
status: OCPP20AuthorizationStatusEnumType.Expired,
},
}
- const requestPayload = buildTransactionEventRequest(TEST_TRANSACTION_ID)
+ const requestPayload = buildTransactionEventRequest(TEST_TRANSACTION_UUID)
// Act
testable.handleResponseTransactionEvent(station, payload, requestPayload)
status: OCPP20AuthorizationStatusEnumType.NoCredit,
},
}
- const requestPayload = buildTransactionEventRequest(TEST_TRANSACTION_ID)
+ const requestPayload = buildTransactionEventRequest(TEST_TRANSACTION_UUID)
// Act
testable.handleResponseTransactionEvent(station, payload, requestPayload)
format: OCPP20MessageFormatEnumType.UTF8,
},
}
- const requestPayload = buildTransactionEventRequest(TEST_TRANSACTION_ID)
+ const requestPayload = buildTransactionEventRequest(TEST_TRANSACTION_UUID)
// Act
testable.handleResponseTransactionEvent(station, payload, requestPayload)
OCPPVersion,
} from '../../../../src/types/index.js'
import { standardCleanup } from '../../../helpers/TestLifecycleHelpers.js'
+import {
+ TEST_CHARGING_STATION_BASE_NAME,
+ TEST_TOKEN_ISO14443,
+} from '../../ChargingStationTestConstants.js'
import { createMockChargingStation } from '../../ChargingStationTestUtils.js'
import { getTestAuthCache } from '../auth/helpers/MockFactories.js'
-const TEST_STATION_ID = 'CS_AUTH_CACHE_UTILS_TEST'
-const TEST_TOKEN_VALUE = 'RFID_AUTH_CACHE_001'
-
await describe('OCPP20ServiceUtils.updateAuthorizationCache', async () => {
let station: ChargingStation
let authService: OCPPAuthServiceImpl
beforeEach(() => {
const { station: mockStation } = createMockChargingStation({
- baseName: TEST_STATION_ID,
+ baseName: TEST_CHARGING_STATION_BASE_NAME,
connectorsCount: 1,
stationInfo: {
- chargingStationId: TEST_STATION_ID,
+ chargingStationId: TEST_CHARGING_STATION_BASE_NAME,
ocppVersion: OCPPVersion.VERSION_201,
},
})
authService = new OCPPAuthServiceImpl(station)
authService.initialize()
- OCPPAuthServiceFactory.setInstanceForTesting(TEST_STATION_ID, authService)
+ OCPPAuthServiceFactory.setInstanceForTesting(TEST_CHARGING_STATION_BASE_NAME, authService)
authCache = getTestAuthCache(authService)
})
await it('C10.FR.04 - should update cache on AuthorizeResponse via updateAuthorizationCache', () => {
// Arrange
const idToken: OCPP20IdTokenType = {
- idToken: TEST_TOKEN_VALUE,
+ idToken: TEST_TOKEN_ISO14443,
type: OCPP20IdTokenEnumType.ISO14443,
}
const idTokenInfo = {
OCPP20ServiceUtils.updateAuthorizationCache(station, idToken, idTokenInfo)
// Assert
- const cached = authCache.get(TEST_TOKEN_VALUE)
+ const cached = authCache.get(TEST_TOKEN_ISO14443)
assert.ok(cached != null, 'AuthorizeResponse should update the cache')
assert.strictEqual(cached.status, AuthorizationStatus.ACCEPTED)
})
await it('should handle auth service initialization failure gracefully', () => {
// Arrange
const { station: isolatedStation } = createMockChargingStation({
- baseName: 'CS_NO_AUTH_SERVICE',
+ baseName: TEST_CHARGING_STATION_BASE_NAME,
connectorsCount: 1,
stationInfo: {
- chargingStationId: 'CS_NO_AUTH_SERVICE',
+ chargingStationId: TEST_CHARGING_STATION_BASE_NAME,
ocppVersion: OCPPVersion.VERSION_201,
},
})
OCPPAuthServiceFactory.clearAllInstances()
const idToken: OCPP20IdTokenType = {
- idToken: TEST_TOKEN_VALUE,
+ idToken: TEST_TOKEN_ISO14443,
type: OCPP20IdTokenEnumType.ISO14443,
}
const idTokenInfo = {
} from '../../../../src/types/index.js'
import { Constants } from '../../../../src/utils/index.js'
import { standardCleanup } from '../../../helpers/TestLifecycleHelpers.js'
+import { TEST_CHARGING_STATION_BASE_NAME } from '../../ChargingStationTestConstants.js'
import { createMockChargingStation } from '../../ChargingStationTestUtils.js'
import { upsertConfigurationKey } from './OCPP20TestUtils.js'
-const TEST_STATION_ID = 'CS_RECONNECT_DELAY_TEST'
-
const DEFAULT_WAIT_MINIMUM_S = 30
const DEFAULT_RANDOM_RANGE_S = 10
const DEFAULT_REPEAT_TIMES = 5
beforeEach(() => {
const { station: mockStation } = createMockChargingStation({
- baseName: TEST_STATION_ID,
+ baseName: TEST_CHARGING_STATION_BASE_NAME,
connectorsCount: 1,
heartbeatInterval: Constants.DEFAULT_HEARTBEAT_INTERVAL,
stationInfo: {
- chargingStationId: TEST_STATION_ID,
+ chargingStationId: TEST_CHARGING_STATION_BASE_NAME,
ocppVersion: OCPPVersion.VERSION_201,
},
})
assert.fail('Expected evse to be defined')
}
assert.strictEqual(typeof transactionEvent.evse.id, 'number')
- assert.ok(transactionEvent.evse.id > 0)
+ assert.ok(transactionEvent.evse.id > 0, 'EVSE ID should be positive')
// Validate transactionInfo structure
assert.strictEqual(typeof transactionEvent.transactionInfo.transactionId, 'string')
assert.strictEqual(capturedReasons.length, 1)
assert.strictEqual(capturedReasons[0].reasonCode, ReasonCodeEnumType.TooLargeElement)
assert.strictEqual(typeof capturedReasons[0].additionalInfo, 'string')
- assert.ok(capturedReasons[0].additionalInfo.length > 0)
+ assert.ok(capturedReasons[0].additionalInfo.length > 0, 'additionalInfo should not be empty')
})
})
})
const result = await stopTransactionOnConnector(station, 1)
assert.strictEqual(result.accepted, true)
- assert.ok(requestHandler.mock.calls.length >= 1)
+ assert.ok(
+ requestHandler.mock.calls.length >= 1,
+ 'request handler should have been called at least once'
+ )
assert.strictEqual(requestHandler.mock.calls[0].arguments[1] as string, 'StopTransaction')
})
const result = await stopTransactionOnConnector(station, 1)
assert.strictEqual(result.accepted, true)
- assert.ok(requestHandler.mock.calls.length >= 1)
+ assert.ok(
+ requestHandler.mock.calls.length >= 1,
+ 'request handler should have been called at least once'
+ )
assert.strictEqual(requestHandler.mock.calls[0].arguments[1] as string, 'TransactionEvent')
})
const result = await startTransactionOnConnector(station, 1, 'TAG001')
assert.strictEqual(result.accepted, true)
- assert.ok(requestHandler.mock.calls.length >= 1)
+ assert.ok(
+ requestHandler.mock.calls.length >= 1,
+ 'request handler should have been called at least once'
+ )
assert.strictEqual(requestHandler.mock.calls[0].arguments[1] as string, 'StartTransaction')
})
const result = await startTransactionOnConnector(station, 1, 'TAG002')
assert.strictEqual(result.accepted, true)
- assert.ok(requestHandler.mock.calls.length >= 1)
+ assert.ok(
+ requestHandler.mock.calls.length >= 1,
+ 'request handler should have been called at least once'
+ )
assert.strictEqual(requestHandler.mock.calls[0].arguments[1] as string, 'TransactionEvent')
})
cache.get('token-2')
const stats = cache.getStats()
- assert.ok(stats.expiredEntries >= 2)
+ assert.ok(stats.expiredEntries >= 2, 'should track at least 2 expired entries')
})
})
cache.get('miss')
const statsBefore = cache.getStats()
- assert.ok(statsBefore.hits > 0)
- assert.ok(statsBefore.misses > 0)
+ assert.ok(statsBefore.hits > 0, 'should have cache hits before clear')
+ assert.ok(statsBefore.misses > 0, 'should have cache misses before clear')
cache.clear()
assert.strictEqual(result, undefined)
const stats = cache.getStats()
- assert.ok(stats.rateLimit.blockedRequests > 0)
+ assert.ok(
+ stats.rateLimit.blockedRequests > 0,
+ 'should have blocked requests in rate limit stats'
+ )
})
await it('should track rate limit statistics', () => {
cache.set(identifier, mockResult) // Should be blocked
const stats = cache.getStats()
- assert.ok(stats.rateLimit.totalChecks > 0)
- assert.ok(stats.rateLimit.blockedRequests > 0)
+ assert.ok(stats.rateLimit.totalChecks > 0, 'should have total rate limit checks')
+ assert.ok(stats.rateLimit.blockedRequests > 0, 'should have blocked requests')
})
await it('should reset rate limit after window expires', async t => {
assert.strictEqual(stats.hits, 1)
assert.strictEqual(stats.misses, 1)
assert.strictEqual(stats.hitRate, 50)
- assert.ok(stats.memoryUsage > 0)
+ assert.ok(stats.memoryUsage > 0, 'should have positive memory usage')
})
await it('should track memory usage estimate', () => {
const statsAfter = cache.getStats()
const memoryAfter = statsAfter.memoryUsage
- assert.ok(memoryAfter > memoryBefore)
+ assert.ok(memoryAfter > memoryBefore, 'memory usage should increase with more entries')
})
await it('should provide rate limit statistics', () => {
const stats = cache.getStats()
assert.notStrictEqual(stats.rateLimit, undefined)
- assert.ok(stats.rateLimit.totalChecks > 0)
- assert.ok(stats.rateLimit.blockedRequests > 0)
- assert.ok(stats.rateLimit.rateLimitedIdentifiers > 0)
+ assert.ok(stats.rateLimit.totalChecks > 0, 'should have total rate limit checks')
+ assert.ok(stats.rateLimit.blockedRequests > 0, 'should have blocked requests')
+ assert.ok(stats.rateLimit.rateLimitedIdentifiers > 0, 'should have rate limited identifiers')
})
})
}
const rateLimitsSize = boundedCache.getStats().rateLimit.rateLimitedIdentifiers
- assert.ok(rateLimitsSize <= 4)
+ assert.ok(rateLimitsSize <= 4, 'rate limits size should be at most 4')
boundedCache.dispose()
})
})
statsCache.get('id-miss') // miss
const before = statsCache.getStats()
- assert.ok(before.evictions > 0)
- assert.ok(before.hits > 0)
- assert.ok(before.misses > 0)
+ assert.ok(before.evictions > 0, 'should have evictions')
+ assert.ok(before.hits > 0, 'should have cache hits')
+ assert.ok(before.misses > 0, 'should have cache misses')
statsCache.clear()
statsCache.get('id-miss') // miss
const before = statsCache.getStats()
- assert.ok(before.hits > 0)
- assert.ok(before.misses > 0)
+ assert.ok(before.hits > 0, 'should have cache hits before reset')
+ assert.ok(before.misses > 0, 'should have cache misses before reset')
statsCache.resetStats()
statsCache.clear() // clears entries but preserves stats
const afterClear = statsCache.getStats()
- assert.ok(afterClear.hits > 0) // stats preserved
+ assert.ok(afterClear.hits > 0, 'stats preserved after clear') // stats preserved
assert.strictEqual(afterClear.totalEntries, 0) // entries gone
statsCache.resetStats() // now zero out
const result = AuthHelpers.calculateTTL(futureDate)
assert.notStrictEqual(result, undefined)
if (result !== undefined) {
- assert.ok(result >= 4)
- assert.ok(result <= 5)
+ assert.ok(result >= 4, 'TTL should be at least 4 seconds')
+ assert.ok(result <= 5, 'TTL should be at most 5 seconds')
}
})