} from './OCPP20TestUtils.js'
await describe('B05 - Set Variables', async () => {
- let mockChargingStation: ChargingStation
+ let mockStation: ChargingStation
let incomingRequestService: OCPP20IncomingRequestService
let testableService: ReturnType<typeof createTestableIncomingRequestService>
},
websocketPingInterval: Constants.DEFAULT_WEBSOCKET_PING_INTERVAL,
})
- mockChargingStation = station
+ mockStation = station
incomingRequestService = new OCPP20IncomingRequestService()
testableService = createTestableIncomingRequestService(incomingRequestService)
})
}
const response: { setVariableResult: OCPP20SetVariableResultType[] } =
- testableService.handleRequestSetVariables(mockChargingStation, request)
+ testableService.handleRequestSetVariables(mockStation, request)
expect(response).toBeDefined()
expect(response.setVariableResult).toBeDefined()
}
const response: { setVariableResult: OCPP20SetVariableResultType[] } =
- testableService.handleRequestSetVariables(mockChargingStation, request)
+ testableService.handleRequestSetVariables(mockStation, request)
expect(response.setVariableResult).toHaveLength(2)
const firstResult = response.setVariableResult[0]
}
const response: { setVariableResult: OCPP20SetVariableResultType[] } =
- testableService.handleRequestSetVariables(mockChargingStation, request)
+ testableService.handleRequestSetVariables(mockStation, request)
expect(response.setVariableResult).toHaveLength(1)
const result = response.setVariableResult[0]
],
}
const response: { setVariableResult: OCPP20SetVariableResultType[] } =
- testableService.handleRequestSetVariables(mockChargingStation, request)
+ testableService.handleRequestSetVariables(mockStation, request)
expect(response.setVariableResult).toHaveLength(1)
const result = response.setVariableResult[0]
expect(result.attributeStatus).toBe(SetVariableStatusEnumType.UnknownComponent)
}
const response: { setVariableResult: OCPP20SetVariableResultType[] } =
- testableService.handleRequestSetVariables(mockChargingStation, request)
+ testableService.handleRequestSetVariables(mockStation, request)
expect(response.setVariableResult).toHaveLength(1)
const result = response.setVariableResult[0]
}
const response: { setVariableResult: OCPP20SetVariableResultType[] } =
- testableService.handleRequestSetVariables(mockChargingStation, request)
+ testableService.handleRequestSetVariables(mockStation, request)
expect(response.setVariableResult).toHaveLength(5)
const [accepted, unknownVariable, unsupportedAttrHeartbeat, unsupportedAttrWs, oversize] =
],
}
const response: { setVariableResult: OCPP20SetVariableResultType[] } =
- testableService.handleRequestSetVariables(mockChargingStation, request)
+ testableService.handleRequestSetVariables(mockStation, request)
expect(response.setVariableResult).toHaveLength(1)
const result = response.setVariableResult[0]
expect(result.attributeStatus).toBe(SetVariableStatusEnumType.NotSupportedAttributeType)
],
}
const response: { setVariableResult: OCPP20SetVariableResultType[] } =
- testableService.handleRequestSetVariables(mockChargingStation, request)
+ testableService.handleRequestSetVariables(mockStation, request)
expect(response.setVariableResult).toHaveLength(1)
const result = response.setVariableResult[0]
expect(result.attributeStatus).toBe(SetVariableStatusEnumType.Rejected)
},
],
}
- testableService.handleRequestSetVariables(mockChargingStation, setRequest)
+ testableService.handleRequestSetVariables(mockStation, setRequest)
const getResponse: { getVariableResult: OCPP20GetVariableResultType[] } =
- testableService.handleRequestGetVariables(mockChargingStation, {
+ testableService.handleRequestGetVariables(mockStation, {
getVariableData: [
{
attributeType: AttributeEnumType.Actual,
},
],
}
- testableService.handleRequestSetVariables(mockChargingStation, setRequest)
+ testableService.handleRequestSetVariables(mockStation, setRequest)
const getBefore: { getVariableResult: OCPP20GetVariableResultType[] } =
- testableService.handleRequestGetVariables(mockChargingStation, {
+ testableService.handleRequestGetVariables(mockStation, {
getVariableData: [
{
attributeType: AttributeEnumType.Actual,
OCPP20VariableManager.getInstance().resetRuntimeOverrides()
const getAfter: { getVariableResult: OCPP20GetVariableResultType[] } =
- testableService.handleRequestGetVariables(mockChargingStation, {
+ testableService.handleRequestGetVariables(mockStation, {
getVariableData: [
{
component: { name: OCPP20ComponentName.SampledDataCtrlr },
// FR: B07.FR.12
await it('should reject all SetVariables when ItemsPerMessage limit exceeded', () => {
- setStrictLimits(mockChargingStation, 1, 10000)
+ setStrictLimits(mockStation, 1, 10000)
const request: OCPP20SetVariablesRequest = {
setVariableData: [
{
],
}
const response: { setVariableResult: OCPP20SetVariableResultType[] } =
- testableService.handleRequestSetVariables(mockChargingStation, request)
+ testableService.handleRequestSetVariables(mockStation, request)
expect(response.setVariableResult).toHaveLength(2)
response.setVariableResult.forEach(r => {
expect(r.attributeStatus).toBe(SetVariableStatusEnumType.Rejected)
expect(r.attributeStatusInfo?.reasonCode).toBe(ReasonCodeEnumType.TooManyElements)
expect(r.attributeStatusInfo?.additionalInfo).toMatch(/ItemsPerMessage limit 1 exceeded/)
})
- resetLimits(mockChargingStation)
+ resetLimits(mockStation)
})
await it('should reject all SetVariables when BytesPerMessage limit exceeded (pre-calculation)', () => {
// Set strict bytes limit low enough for request pre-estimate to exceed
- setStrictLimits(mockChargingStation, 100, 10)
+ setStrictLimits(mockStation, 100, 10)
const request: OCPP20SetVariablesRequest = {
setVariableData: [
{
],
}
const response: { setVariableResult: OCPP20SetVariableResultType[] } =
- testableService.handleRequestSetVariables(mockChargingStation, request)
+ testableService.handleRequestSetVariables(mockStation, request)
expect(response.setVariableResult).toHaveLength(2)
response.setVariableResult.forEach(r => {
expect(r.attributeStatus).toBe(SetVariableStatusEnumType.Rejected)
expect(r.attributeStatusInfo?.reasonCode).toBe(ReasonCodeEnumType.TooLargeElement)
expect(r.attributeStatusInfo?.additionalInfo).toMatch(/BytesPerMessage limit 10 exceeded/)
})
- resetLimits(mockChargingStation)
+ resetLimits(mockStation)
})
await it('should reject all SetVariables when BytesPerMessage limit exceeded (post-calculation)', () => {
const preEstimate = Buffer.byteLength(JSON.stringify(request.setVariableData), 'utf8')
const postCalcLimit = preEstimate + 10
upsertConfigurationKey(
- mockChargingStation,
+ mockStation,
OCPP20RequiredVariableName.BytesPerMessage,
postCalcLimit.toString(),
false
)
expect(preEstimate).toBeLessThan(postCalcLimit)
const response: { setVariableResult: OCPP20SetVariableResultType[] } =
- testableService.handleRequestSetVariables(mockChargingStation, request)
+ testableService.handleRequestSetVariables(mockStation, request)
const actualSize = Buffer.byteLength(JSON.stringify(response.setVariableResult), 'utf8')
expect(actualSize).toBeGreaterThan(postCalcLimit)
expect(response.setVariableResult).toHaveLength(request.setVariableData.length)
new RegExp(`BytesPerMessage limit ${postCalcLimit.toString()} exceeded`)
)
})
- resetLimits(mockChargingStation)
+ resetLimits(mockStation)
})
// Effective ConfigurationValueSize / ValueSize propagation tests
await it('should enforce ConfigurationValueSize when ValueSize unset (service propagation)', () => {
- resetValueSizeLimits(mockChargingStation)
- setConfigurationValueSize(mockChargingStation, 100)
- upsertConfigurationKey(mockChargingStation, OCPP20RequiredVariableName.ValueSize, '')
+ resetValueSizeLimits(mockStation)
+ setConfigurationValueSize(mockStation, 100)
+ upsertConfigurationKey(mockStation, OCPP20RequiredVariableName.ValueSize, '')
const prefix = 'wss://example.com/'
const withinLimit = prefix + 'a'.repeat(100 - prefix.length)
const overLimit = prefix + 'a'.repeat(100 - prefix.length + 1)
- let response = testableService.handleRequestSetVariables(mockChargingStation, {
+ let response = testableService.handleRequestSetVariables(mockStation, {
setVariableData: [
{
attributeValue: withinLimit,
],
})
expect(response.setVariableResult[0].attributeStatus).toBe(SetVariableStatusEnumType.Accepted)
- response = testableService.handleRequestSetVariables(mockChargingStation, {
+ response = testableService.handleRequestSetVariables(mockStation, {
setVariableData: [
{
attributeValue: overLimit,
const res = response.setVariableResult[0]
expect(res.attributeStatus).toBe(SetVariableStatusEnumType.Rejected)
expect(res.attributeStatusInfo?.reasonCode).toBe(ReasonCodeEnumType.TooLargeElement)
- resetValueSizeLimits(mockChargingStation)
+ resetValueSizeLimits(mockStation)
})
await it('should enforce ValueSize when ConfigurationValueSize unset (service propagation)', () => {
- resetValueSizeLimits(mockChargingStation)
- upsertConfigurationKey(
- mockChargingStation,
- OCPP20RequiredVariableName.ConfigurationValueSize,
- ''
- )
- setValueSize(mockChargingStation, 120)
+ resetValueSizeLimits(mockStation)
+ upsertConfigurationKey(mockStation, OCPP20RequiredVariableName.ConfigurationValueSize, '')
+ setValueSize(mockStation, 120)
const prefix = 'wss://example.com/'
const withinLimit = prefix + 'b'.repeat(120 - prefix.length)
const overLimit = prefix + 'b'.repeat(120 - prefix.length + 1)
- let response = testableService.handleRequestSetVariables(mockChargingStation, {
+ let response = testableService.handleRequestSetVariables(mockStation, {
setVariableData: [
{
attributeValue: withinLimit,
],
})
expect(response.setVariableResult[0].attributeStatus).toBe(SetVariableStatusEnumType.Accepted)
- response = testableService.handleRequestSetVariables(mockChargingStation, {
+ response = testableService.handleRequestSetVariables(mockStation, {
setVariableData: [
{
attributeValue: overLimit,
const res = response.setVariableResult[0]
expect(res.attributeStatus).toBe(SetVariableStatusEnumType.Rejected)
expect(res.attributeStatusInfo?.reasonCode).toBe(ReasonCodeEnumType.TooLargeElement)
- resetValueSizeLimits(mockChargingStation)
+ resetValueSizeLimits(mockStation)
})
await it('should use smaller ValueSize when ValueSize < ConfigurationValueSize (service propagation)', () => {
- resetValueSizeLimits(mockChargingStation)
- setConfigurationValueSize(mockChargingStation, 400)
- setValueSize(mockChargingStation, 350)
+ resetValueSizeLimits(mockStation)
+ setConfigurationValueSize(mockStation, 400)
+ setValueSize(mockStation, 350)
const prefix = 'wss://example.com/'
const withinLimit = prefix + 'c'.repeat(350 - prefix.length)
const overLimit = prefix + 'c'.repeat(350 - prefix.length + 1)
- let response = testableService.handleRequestSetVariables(mockChargingStation, {
+ let response = testableService.handleRequestSetVariables(mockStation, {
setVariableData: [
{
attributeValue: withinLimit,
],
})
expect(response.setVariableResult[0].attributeStatus).toBe(SetVariableStatusEnumType.Accepted)
- response = testableService.handleRequestSetVariables(mockChargingStation, {
+ response = testableService.handleRequestSetVariables(mockStation, {
setVariableData: [
{
attributeValue: overLimit,
const res = response.setVariableResult[0]
expect(res.attributeStatus).toBe(SetVariableStatusEnumType.Rejected)
expect(res.attributeStatusInfo?.reasonCode).toBe(ReasonCodeEnumType.TooLargeElement)
- resetValueSizeLimits(mockChargingStation)
+ resetValueSizeLimits(mockStation)
})
await it('should use smaller ConfigurationValueSize when ConfigurationValueSize < ValueSize (service propagation)', () => {
- resetValueSizeLimits(mockChargingStation)
- setConfigurationValueSize(mockChargingStation, 260)
- setValueSize(mockChargingStation, 500)
+ resetValueSizeLimits(mockStation)
+ setConfigurationValueSize(mockStation, 260)
+ setValueSize(mockStation, 500)
const prefix = 'wss://example.com/'
const withinLimit = prefix + 'd'.repeat(260 - prefix.length)
const overLimit = prefix + 'd'.repeat(260 - prefix.length + 1)
- let response = testableService.handleRequestSetVariables(mockChargingStation, {
+ let response = testableService.handleRequestSetVariables(mockStation, {
setVariableData: [
{
attributeValue: withinLimit,
],
})
expect(response.setVariableResult[0].attributeStatus).toBe(SetVariableStatusEnumType.Accepted)
- response = testableService.handleRequestSetVariables(mockChargingStation, {
+ response = testableService.handleRequestSetVariables(mockStation, {
setVariableData: [
{
attributeValue: overLimit,
const res = response.setVariableResult[0]
expect(res.attributeStatus).toBe(SetVariableStatusEnumType.Rejected)
expect(res.attributeStatusInfo?.reasonCode).toBe(ReasonCodeEnumType.TooLargeElement)
- resetValueSizeLimits(mockChargingStation)
+ resetValueSizeLimits(mockStation)
})
await it('should fallback to default absolute max length when both limits invalid/non-positive', () => {
- resetValueSizeLimits(mockChargingStation)
- setConfigurationValueSize(mockChargingStation, 0)
- setValueSize(mockChargingStation, -5)
+ resetValueSizeLimits(mockStation)
+ setConfigurationValueSize(mockStation, 0)
+ setValueSize(mockStation, -5)
const prefix = 'wss://example.com/'
const validValue = prefix + 'e'.repeat(300 - prefix.length) // 300 < default absolute max length and < ConnectionUrl maxLength
- const response = testableService.handleRequestSetVariables(mockChargingStation, {
+ const response = testableService.handleRequestSetVariables(mockStation, {
setVariableData: [
{
attributeValue: validValue,
const res = response.setVariableResult[0]
expect(res.attributeStatus).toBe(SetVariableStatusEnumType.Accepted)
expect(res.attributeStatusInfo).toBeUndefined()
- resetValueSizeLimits(mockChargingStation)
+ resetValueSizeLimits(mockStation)
})
// FR: B07.FR.12 (updated behavior: ConnectionUrl now readable after set)
await it('should allow ConnectionUrl read-back after setting', () => {
- resetLimits(mockChargingStation)
+ resetLimits(mockStation)
const url = 'wss://central.example.com/ocpp'
const setRequest: OCPP20SetVariablesRequest = {
setVariableData: [
},
],
}
- testableService.handleRequestSetVariables(mockChargingStation, setRequest)
+ testableService.handleRequestSetVariables(mockStation, setRequest)
const getResponse: { getVariableResult: OCPP20GetVariableResultType[] } =
- testableService.handleRequestGetVariables(mockChargingStation, {
+ testableService.handleRequestGetVariables(mockStation, {
getVariableData: [
{
attributeType: AttributeEnumType.Actual,
expect(result.attributeStatus).toBe(GetVariableStatusEnumType.Accepted)
expect(result.attributeValue).toBe(url)
expect(result.attributeStatusInfo).toBeUndefined()
- resetLimits(mockChargingStation)
+ resetLimits(mockStation)
})
await it('should accept ConnectionUrl with custom mqtt scheme (no scheme restriction)', () => {
- resetLimits(mockChargingStation)
+ resetLimits(mockStation)
const url = 'mqtt://broker.internal:1883/ocpp'
const setRequest: OCPP20SetVariablesRequest = {
setVariableData: [
],
}
const response: { setVariableResult: OCPP20SetVariableResultType[] } =
- testableService.handleRequestSetVariables(mockChargingStation, setRequest)
+ testableService.handleRequestSetVariables(mockStation, setRequest)
expect(response.setVariableResult).toHaveLength(1)
const setResult = response.setVariableResult[0]
expect(setResult.attributeStatus).toBe(SetVariableStatusEnumType.Accepted)
expect(setResult.attributeStatusInfo).toBeUndefined()
const getResponse: { getVariableResult: OCPP20GetVariableResultType[] } =
- testableService.handleRequestGetVariables(mockChargingStation, {
+ testableService.handleRequestGetVariables(mockStation, {
getVariableData: [
{
attributeType: AttributeEnumType.Actual,
expect(getResult.attributeStatus).toBe(GetVariableStatusEnumType.Accepted)
expect(getResult.attributeValue).toBe(url)
expect(getResult.attributeStatusInfo).toBeUndefined()
- resetLimits(mockChargingStation)
+ resetLimits(mockStation)
})
})
await describe('OCPP20 TransactionEvent ServiceUtils', async () => {
await describe('E01-E04 - OCPP 2.0.1 TransactionEvent Implementation', async () => {
- let mockChargingStation: ChargingStation
+ let mockStation: ChargingStation
beforeEach(() => {
const { station } = createMockChargingStation({
},
websocketPingInterval: Constants.DEFAULT_WEBSOCKET_PING_INTERVAL,
})
- mockChargingStation = station
- resetLimits(mockChargingStation)
+ mockStation = station
+ resetLimits(mockStation)
})
// Reset singleton state and timers after each test to ensure test isolation
const triggerReason = OCPP20TriggerReasonEnumType.Authorized
// Reset sequence number to simulate new transaction
- OCPP20ServiceUtils.resetTransactionSequenceNumber(mockChargingStation, connectorId)
+ OCPP20ServiceUtils.resetTransactionSequenceNumber(mockStation, connectorId)
const transactionEvent = OCPP20ServiceUtils.buildTransactionEvent(
- mockChargingStation,
+ mockStation,
OCPP20TransactionEventEnumType.Started,
triggerReason,
connectorId,
const transactionId = generateUUID()
// Reset for new transaction
- OCPP20ServiceUtils.resetTransactionSequenceNumber(mockChargingStation, connectorId)
+ OCPP20ServiceUtils.resetTransactionSequenceNumber(mockStation, connectorId)
// Build first event (Started)
const startEvent = OCPP20ServiceUtils.buildTransactionEvent(
- mockChargingStation,
+ mockStation,
OCPP20TransactionEventEnumType.Started,
OCPP20TriggerReasonEnumType.Authorized,
connectorId,
// Build second event (Updated)
const updateEvent = OCPP20ServiceUtils.buildTransactionEvent(
- mockChargingStation,
+ mockStation,
OCPP20TransactionEventEnumType.Updated,
OCPP20TriggerReasonEnumType.MeterValuePeriodic,
connectorId,
// Build third event (Ended)
const endEvent = OCPP20ServiceUtils.buildTransactionEvent(
- mockChargingStation,
+ mockStation,
OCPP20TransactionEventEnumType.Ended,
OCPP20TriggerReasonEnumType.StopAuthorized,
connectorId,
}
const transactionEvent = OCPP20ServiceUtils.buildTransactionEvent(
- mockChargingStation,
+ mockStation,
OCPP20TransactionEventEnumType.Updated,
OCPP20TriggerReasonEnumType.ChargingStateChanged,
connectorId,
try {
OCPP20ServiceUtils.buildTransactionEvent(
- mockChargingStation,
+ mockStation,
OCPP20TransactionEventEnumType.Started,
OCPP20TriggerReasonEnumType.Authorized,
connectorId,
]
// Reset sequence number
- OCPP20ServiceUtils.resetTransactionSequenceNumber(mockChargingStation, connectorId)
+ OCPP20ServiceUtils.resetTransactionSequenceNumber(mockStation, connectorId)
for (const triggerReason of triggerReasons) {
const transactionEvent = OCPP20ServiceUtils.buildTransactionEvent(
- mockChargingStation,
+ mockStation,
OCPP20TransactionEventEnumType.Updated,
triggerReason,
connectorId,
const transactionId = generateUUID()
const response = await OCPP20ServiceUtils.sendTransactionEvent(
- mockChargingStation,
+ mockStation,
OCPP20TransactionEventEnumType.Started,
OCPP20TriggerReasonEnumType.Authorized,
connectorId,
// First, build a transaction event to set sequence number
OCPP20ServiceUtils.buildTransactionEvent(
- mockChargingStation,
+ mockStation,
OCPP20TransactionEventEnumType.Started,
OCPP20TriggerReasonEnumType.Authorized,
connectorId,
)
// Verify sequence number is set
- const connectorStatus = mockChargingStation.getConnectorStatus(connectorId)
+ const connectorStatus = mockStation.getConnectorStatus(connectorId)
expect(connectorStatus?.transactionSeqNo).toBeDefined()
// Reset sequence number
- OCPP20ServiceUtils.resetTransactionSequenceNumber(mockChargingStation, connectorId)
+ OCPP20ServiceUtils.resetTransactionSequenceNumber(mockStation, connectorId)
// Verify sequence number is reset
expect(connectorStatus?.transactionSeqNo).toBeUndefined()
// Should not throw error for non-existent connector
expect(() => {
- OCPP20ServiceUtils.resetTransactionSequenceNumber(
- mockChargingStation,
- nonExistentConnectorId
- )
+ OCPP20ServiceUtils.resetTransactionSequenceNumber(mockStation, nonExistentConnectorId)
}).not.toThrow()
})
})
const connectorId = 1
const transactionId = generateUUID()
- OCPP20ServiceUtils.resetTransactionSequenceNumber(mockChargingStation, connectorId)
+ OCPP20ServiceUtils.resetTransactionSequenceNumber(mockStation, connectorId)
const transactionEvent = OCPP20ServiceUtils.buildTransactionEvent(
- mockChargingStation,
+ mockStation,
OCPP20TransactionEventEnumType.Started,
OCPP20TriggerReasonEnumType.Authorized,
connectorId,
const connectorId = 2
const transactionId = generateUUID()
- OCPP20ServiceUtils.resetTransactionSequenceNumber(mockChargingStation, connectorId)
+ OCPP20ServiceUtils.resetTransactionSequenceNumber(mockStation, connectorId)
const transactionEvent = OCPP20ServiceUtils.buildTransactionEvent(
- mockChargingStation,
+ mockStation,
OCPP20TransactionEventEnumType.Started,
OCPP20TriggerReasonEnumType.Authorized,
connectorId,
source: 'remote_command',
}
- OCPP20ServiceUtils.resetTransactionSequenceNumber(mockChargingStation, connectorId)
+ OCPP20ServiceUtils.resetTransactionSequenceNumber(mockStation, connectorId)
const transactionEvent = OCPP20ServiceUtils.buildTransactionEvent(
- mockChargingStation,
+ mockStation,
OCPP20TransactionEventEnumType.Started,
context,
connectorId,
}
const transactionEvent = OCPP20ServiceUtils.buildTransactionEvent(
- mockChargingStation,
+ mockStation,
OCPP20TransactionEventEnumType.Updated,
context,
connectorId,
}
const response = await OCPP20ServiceUtils.sendTransactionEvent(
- mockChargingStation,
+ mockStation,
OCPP20TransactionEventEnumType.Started,
context,
connectorId,
const connectorId = 1
const transactionId = generateUUID()
- OCPP20ServiceUtils.resetTransactionSequenceNumber(mockChargingStation, connectorId)
+ OCPP20ServiceUtils.resetTransactionSequenceNumber(mockStation, connectorId)
// Old method call should still work
const oldEvent = OCPP20ServiceUtils.buildTransactionEvent(
- mockChargingStation,
+ mockStation,
OCPP20TransactionEventEnumType.Started,
OCPP20TriggerReasonEnumType.Authorized,
connectorId,
// Old method call should still work
const response = await OCPP20ServiceUtils.sendTransactionEvent(
- mockChargingStation,
+ mockStation,
OCPP20TransactionEventEnumType.Started,
OCPP20TriggerReasonEnumType.Authorized,
connectorId,
? { idToken: `${id.toUpperCase()}_TOKEN_001`, type: OCPP20IdTokenEnumType.ISO14443 }
: undefined
- OCPP20ServiceUtils.resetTransactionSequenceNumber(mockChargingStation, connectorId)
+ OCPP20ServiceUtils.resetTransactionSequenceNumber(mockStation, connectorId)
const startedEvent = OCPP20ServiceUtils.buildTransactionEvent(
- mockChargingStation,
+ mockStation,
OCPP20TransactionEventEnumType.Started,
expectedStartTrigger,
connectorId,
}
: undefined
- OCPP20ServiceUtils.resetTransactionSequenceNumber(mockChargingStation, connectorId)
+ OCPP20ServiceUtils.resetTransactionSequenceNumber(mockStation, connectorId)
// Step 1: Started event
const startedEvent = OCPP20ServiceUtils.buildTransactionEvent(
- mockChargingStation,
+ mockStation,
OCPP20TransactionEventEnumType.Started,
expectedStartTrigger,
connectorId,
// Step 2: Charging state change
const chargingEvent = OCPP20ServiceUtils.buildTransactionEvent(
- mockChargingStation,
+ mockStation,
OCPP20TransactionEventEnumType.Updated,
OCPP20TriggerReasonEnumType.ChargingStateChanged,
connectorId,
// Step 3: Ended event
const endedEvent = OCPP20ServiceUtils.buildTransactionEvent(
- mockChargingStation,
+ mockStation,
OCPP20TransactionEventEnumType.Ended,
OCPP20TriggerReasonEnumType.StopAuthorized,
connectorId,
const transaction1Id = generateUUID()
const transaction2Id = generateUUID()
- OCPP20ServiceUtils.resetTransactionSequenceNumber(mockChargingStation, connector1)
- OCPP20ServiceUtils.resetTransactionSequenceNumber(mockChargingStation, connector2)
+ OCPP20ServiceUtils.resetTransactionSequenceNumber(mockStation, connector1)
+ OCPP20ServiceUtils.resetTransactionSequenceNumber(mockStation, connector2)
// Start transaction on connector 1
const conn1Event1 = OCPP20ServiceUtils.buildTransactionEvent(
- mockChargingStation,
+ mockStation,
OCPP20TransactionEventEnumType.Started,
expectedStartTrigger,
connector1,
// Start transaction on connector 2
const conn2Event1 = OCPP20ServiceUtils.buildTransactionEvent(
- mockChargingStation,
+ mockStation,
OCPP20TransactionEventEnumType.Started,
expectedStartTrigger,
connector2,
// Update connector 1
const conn1Event2 = OCPP20ServiceUtils.buildTransactionEvent(
- mockChargingStation,
+ mockStation,
OCPP20TransactionEventEnumType.Updated,
OCPP20TriggerReasonEnumType.ChargingStateChanged,
connector1,
// Update connector 2
const conn2Event2 = OCPP20ServiceUtils.buildTransactionEvent(
- mockChargingStation,
+ mockStation,
OCPP20TransactionEventEnumType.Updated,
OCPP20TriggerReasonEnumType.ChargingStateChanged,
connector2,
// ==========================================================================
await describe('E02 - Cable-First Transaction', async () => {
beforeEach(() => {
- resetConnectorTransactionState(mockChargingStation)
+ resetConnectorTransactionState(mockStation)
})
await describe('Cable Plug Event Sequencing', async () => {
const connectorId = 1
const transactionId = generateUUID()
- OCPP20ServiceUtils.resetTransactionSequenceNumber(mockChargingStation, connectorId)
+ OCPP20ServiceUtils.resetTransactionSequenceNumber(mockStation, connectorId)
// Step 1: Cable plugged in (Started)
const cablePluggedEvent = OCPP20ServiceUtils.buildTransactionEvent(
- mockChargingStation,
+ mockStation,
OCPP20TransactionEventEnumType.Started,
OCPP20TriggerReasonEnumType.CablePluggedIn,
connectorId,
// Step 2: EV detected (Updated)
const evDetectedEvent = OCPP20ServiceUtils.buildTransactionEvent(
- mockChargingStation,
+ mockStation,
OCPP20TransactionEventEnumType.Updated,
OCPP20TriggerReasonEnumType.EVDetected,
connectorId,
// Step 3: Charging starts (Updated with ChargingStateChanged)
const chargingStartedEvent = OCPP20ServiceUtils.buildTransactionEvent(
- mockChargingStation,
+ mockStation,
OCPP20TransactionEventEnumType.Updated,
OCPP20TriggerReasonEnumType.ChargingStateChanged,
connectorId,
const connectorId = 2
const transactionId = generateUUID()
- OCPP20ServiceUtils.resetTransactionSequenceNumber(mockChargingStation, connectorId)
+ OCPP20ServiceUtils.resetTransactionSequenceNumber(mockStation, connectorId)
// Start transaction with cable plug
const startEvent = OCPP20ServiceUtils.buildTransactionEvent(
- mockChargingStation,
+ mockStation,
OCPP20TransactionEventEnumType.Started,
OCPP20TriggerReasonEnumType.CablePluggedIn,
connectorId,
// End transaction with EV departure (cable removal)
const endEvent = OCPP20ServiceUtils.buildTransactionEvent(
- mockChargingStation,
+ mockStation,
OCPP20TransactionEventEnumType.Ended,
OCPP20TriggerReasonEnumType.EVDeparted,
connectorId,
const connectorId = 1
const transactionId = generateUUID()
- OCPP20ServiceUtils.resetTransactionSequenceNumber(mockChargingStation, connectorId)
+ OCPP20ServiceUtils.resetTransactionSequenceNumber(mockStation, connectorId)
// Build full cable-first flow
const events = [
OCPP20ServiceUtils.buildTransactionEvent(
- mockChargingStation,
+ mockStation,
OCPP20TransactionEventEnumType.Started,
OCPP20TriggerReasonEnumType.CablePluggedIn,
connectorId,
transactionId
),
OCPP20ServiceUtils.buildTransactionEvent(
- mockChargingStation,
+ mockStation,
OCPP20TransactionEventEnumType.Updated,
OCPP20TriggerReasonEnumType.EVDetected,
connectorId,
transactionId
),
OCPP20ServiceUtils.buildTransactionEvent(
- mockChargingStation,
+ mockStation,
OCPP20TransactionEventEnumType.Updated,
OCPP20TriggerReasonEnumType.Authorized,
connectorId,
transactionId
),
OCPP20ServiceUtils.buildTransactionEvent(
- mockChargingStation,
+ mockStation,
OCPP20TransactionEventEnumType.Updated,
OCPP20TriggerReasonEnumType.ChargingStateChanged,
connectorId,
const connectorId = 1
// Get connector status object
- const connectorStatus = mockChargingStation.getConnectorStatus(connectorId)
+ const connectorStatus = mockStation.getConnectorStatus(connectorId)
expect(connectorStatus).toBeDefined()
if (connectorStatus == null) {
throw new Error('Connector status should be defined')
const connectorId = 2
const transactionId = generateUUID()
- const connectorStatus = mockChargingStation.getConnectorStatus(connectorId)
+ const connectorStatus = mockStation.getConnectorStatus(connectorId)
expect(connectorStatus).toBeDefined()
if (connectorStatus == null) {
throw new Error('Connector status should be defined')
const connectorId = 3
const transactionId = generateUUID()
- OCPP20ServiceUtils.resetTransactionSequenceNumber(mockChargingStation, connectorId)
+ OCPP20ServiceUtils.resetTransactionSequenceNumber(mockStation, connectorId)
// Cable-first flow with suspended state
const events = [
// 1. Cable plugged
OCPP20ServiceUtils.buildTransactionEvent(
- mockChargingStation,
+ mockStation,
OCPP20TransactionEventEnumType.Started,
OCPP20TriggerReasonEnumType.CablePluggedIn,
connectorId,
),
// 2. Start charging
OCPP20ServiceUtils.buildTransactionEvent(
- mockChargingStation,
+ mockStation,
OCPP20TransactionEventEnumType.Updated,
OCPP20TriggerReasonEnumType.ChargingStateChanged,
connectorId,
),
// 3. Suspended by EV
OCPP20ServiceUtils.buildTransactionEvent(
- mockChargingStation,
+ mockStation,
OCPP20TransactionEventEnumType.Updated,
OCPP20TriggerReasonEnumType.ChargingStateChanged,
connectorId,
),
// 4. Resume charging
OCPP20ServiceUtils.buildTransactionEvent(
- mockChargingStation,
+ mockStation,
OCPP20TransactionEventEnumType.Updated,
OCPP20TriggerReasonEnumType.ChargingStateChanged,
connectorId,
),
// 5. EV departed
OCPP20ServiceUtils.buildTransactionEvent(
- mockChargingStation,
+ mockStation,
OCPP20TransactionEventEnumType.Ended,
OCPP20TriggerReasonEnumType.EVDeparted,
connectorId,
// ==========================================================================
await describe('E03 - IdToken-First Pre-Authorization', async () => {
beforeEach(() => {
- resetConnectorTransactionState(mockChargingStation)
+ resetConnectorTransactionState(mockStation)
})
await describe('E03.FR.13 - Trigger Reason Selection', async () => {
type: OCPP20IdTokenEnumType.ISO14443,
}
- OCPP20ServiceUtils.resetTransactionSequenceNumber(mockChargingStation, connectorId)
+ OCPP20ServiceUtils.resetTransactionSequenceNumber(mockStation, connectorId)
// Build Started event with idToken (E03.FR.01: IdToken must be in first event)
const startedEvent = OCPP20ServiceUtils.buildTransactionEvent(
- mockChargingStation,
+ mockStation,
OCPP20TransactionEventEnumType.Started,
OCPP20TriggerReasonEnumType.Authorized,
connectorId,
type: OCPP20IdTokenEnumType.ISO14443,
}
- OCPP20ServiceUtils.resetTransactionSequenceNumber(mockChargingStation, connectorId)
+ OCPP20ServiceUtils.resetTransactionSequenceNumber(mockStation, connectorId)
// First event includes idToken
const startedEvent = OCPP20ServiceUtils.buildTransactionEvent(
- mockChargingStation,
+ mockStation,
OCPP20TransactionEventEnumType.Started,
OCPP20TriggerReasonEnumType.Authorized,
connectorId,
// Second event should NOT include idToken (flag is set after first inclusion)
const updatedEvent = OCPP20ServiceUtils.buildTransactionEvent(
- mockChargingStation,
+ mockStation,
OCPP20TransactionEventEnumType.Updated,
OCPP20TriggerReasonEnumType.ChargingStateChanged,
connectorId,
const connectorId = 1
const transactionId = generateUUID()
- OCPP20ServiceUtils.resetTransactionSequenceNumber(mockChargingStation, connectorId)
+ OCPP20ServiceUtils.resetTransactionSequenceNumber(mockStation, connectorId)
// Test ISO14443 (RFID)
const rfidToken: OCPP20IdTokenType = {
}
const rfidEvent = OCPP20ServiceUtils.buildTransactionEvent(
- mockChargingStation,
+ mockStation,
OCPP20TransactionEventEnumType.Started,
OCPP20TriggerReasonEnumType.Authorized,
connectorId,
expect(rfidEvent.idToken?.type).toBe(OCPP20IdTokenEnumType.ISO14443)
// Reset for eMAID test
- OCPP20ServiceUtils.resetTransactionSequenceNumber(mockChargingStation, connectorId)
- const connectorStatus = mockChargingStation.getConnectorStatus(connectorId)
+ OCPP20ServiceUtils.resetTransactionSequenceNumber(mockStation, connectorId)
+ const connectorStatus = mockStation.getConnectorStatus(connectorId)
if (connectorStatus != null) {
connectorStatus.transactionIdTokenSent = undefined
}
}
const emaidEvent = OCPP20ServiceUtils.buildTransactionEvent(
- mockChargingStation,
+ mockStation,
OCPP20TransactionEventEnumType.Started,
OCPP20TriggerReasonEnumType.Authorized,
connectorId,
type: OCPP20IdTokenEnumType.ISO14443,
}
- OCPP20ServiceUtils.resetTransactionSequenceNumber(mockChargingStation, connectorId)
+ OCPP20ServiceUtils.resetTransactionSequenceNumber(mockStation, connectorId)
// E03 Step 1: IdToken presented and authorized (Started with Authorized trigger)
const authorizedEvent = OCPP20ServiceUtils.buildTransactionEvent(
- mockChargingStation,
+ mockStation,
OCPP20TransactionEventEnumType.Started,
OCPP20TriggerReasonEnumType.Authorized,
connectorId,
// E03 Step 2: Cable connected (Updated event)
const cableConnectedEvent = OCPP20ServiceUtils.buildTransactionEvent(
- mockChargingStation,
+ mockStation,
OCPP20TransactionEventEnumType.Updated,
OCPP20TriggerReasonEnumType.CablePluggedIn,
connectorId,
// E03 Step 3: Charging starts
const chargingEvent = OCPP20ServiceUtils.buildTransactionEvent(
- mockChargingStation,
+ mockStation,
OCPP20TransactionEventEnumType.Updated,
OCPP20TriggerReasonEnumType.ChargingStateChanged,
connectorId,
// E03 Step 4: Transaction ends
const endedEvent = OCPP20ServiceUtils.buildTransactionEvent(
- mockChargingStation,
+ mockStation,
OCPP20TransactionEventEnumType.Ended,
OCPP20TriggerReasonEnumType.StopAuthorized,
connectorId,
}
// E03 IdToken-First: Starts with Authorized trigger
- OCPP20ServiceUtils.resetTransactionSequenceNumber(mockChargingStation, connectorId)
- const connectorStatus = mockChargingStation.getConnectorStatus(connectorId)
+ OCPP20ServiceUtils.resetTransactionSequenceNumber(mockStation, connectorId)
+ const connectorStatus = mockStation.getConnectorStatus(connectorId)
if (connectorStatus != null) {
connectorStatus.transactionIdTokenSent = undefined
}
const e03Start = OCPP20ServiceUtils.buildTransactionEvent(
- mockChargingStation,
+ mockStation,
OCPP20TransactionEventEnumType.Started,
OCPP20TriggerReasonEnumType.Authorized,
connectorId,
)
// E02 Cable-First: Starts with CablePluggedIn trigger
- OCPP20ServiceUtils.resetTransactionSequenceNumber(mockChargingStation, connectorId)
+ OCPP20ServiceUtils.resetTransactionSequenceNumber(mockStation, connectorId)
if (connectorStatus != null) {
connectorStatus.transactionIdTokenSent = undefined
}
const e02Start = OCPP20ServiceUtils.buildTransactionEvent(
- mockChargingStation,
+ mockStation,
OCPP20TransactionEventEnumType.Started,
OCPP20TriggerReasonEnumType.CablePluggedIn,
connectorId,
type: OCPP20IdTokenEnumType.ISO14443,
}
- OCPP20ServiceUtils.resetTransactionSequenceNumber(mockChargingStation, connectorId)
+ OCPP20ServiceUtils.resetTransactionSequenceNumber(mockStation, connectorId)
// E03.FR.05: User authorizes with IdToken
const authorizedEvent = OCPP20ServiceUtils.buildTransactionEvent(
- mockChargingStation,
+ mockStation,
OCPP20TransactionEventEnumType.Started,
OCPP20TriggerReasonEnumType.Authorized,
connectorId,
// E03.FR.06: Cable not connected within timeout - transaction ends with Timeout
const timeoutEvent = OCPP20ServiceUtils.buildTransactionEvent(
- mockChargingStation,
+ mockStation,
OCPP20TransactionEventEnumType.Ended,
OCPP20TriggerReasonEnumType.EVConnectTimeout,
connectorId,
type: OCPP20IdTokenEnumType.ISO14443,
}
- OCPP20ServiceUtils.resetTransactionSequenceNumber(mockChargingStation, connectorId)
+ OCPP20ServiceUtils.resetTransactionSequenceNumber(mockStation, connectorId)
// Transaction started with authorization
const startEvent = OCPP20ServiceUtils.buildTransactionEvent(
- mockChargingStation,
+ mockStation,
OCPP20TransactionEventEnumType.Started,
OCPP20TriggerReasonEnumType.Authorized,
connectorId,
// Transaction ended due to deauthorization (e.g., token revoked mid-session)
const revokedEvent = OCPP20ServiceUtils.buildTransactionEvent(
- mockChargingStation,
+ mockStation,
OCPP20TransactionEventEnumType.Ended,
OCPP20TriggerReasonEnumType.Deauthorized,
connectorId,
type: OCPP20IdTokenEnumType.ISO14443,
}
- OCPP20ServiceUtils.resetTransactionSequenceNumber(mockChargingStation, connectorId)
+ OCPP20ServiceUtils.resetTransactionSequenceNumber(mockStation, connectorId)
const events = [
OCPP20ServiceUtils.buildTransactionEvent(
- mockChargingStation,
+ mockStation,
OCPP20TransactionEventEnumType.Started,
OCPP20TriggerReasonEnumType.Authorized,
connectorId,
{ idToken }
),
OCPP20ServiceUtils.buildTransactionEvent(
- mockChargingStation,
+ mockStation,
OCPP20TransactionEventEnumType.Updated,
OCPP20TriggerReasonEnumType.CablePluggedIn,
connectorId,
transactionId
),
OCPP20ServiceUtils.buildTransactionEvent(
- mockChargingStation,
+ mockStation,
OCPP20TransactionEventEnumType.Updated,
OCPP20TriggerReasonEnumType.ChargingStateChanged,
connectorId,
transactionId
),
OCPP20ServiceUtils.buildTransactionEvent(
- mockChargingStation,
+ mockStation,
OCPP20TransactionEventEnumType.Updated,
OCPP20TriggerReasonEnumType.MeterValuePeriodic,
connectorId,
transactionId
),
OCPP20ServiceUtils.buildTransactionEvent(
- mockChargingStation,
+ mockStation,
OCPP20TransactionEventEnumType.Ended,
OCPP20TriggerReasonEnumType.StopAuthorized,
connectorId,
await it('should use unique transaction ID (E03.FR.08)', () => {
const connectorId = 1
- OCPP20ServiceUtils.resetTransactionSequenceNumber(mockChargingStation, connectorId)
+ OCPP20ServiceUtils.resetTransactionSequenceNumber(mockStation, connectorId)
const transaction1Id = generateUUID()
const transaction2Id = generateUUID()
expect(transaction1Id).not.toBe(transaction2Id)
const event1 = OCPP20ServiceUtils.buildTransactionEvent(
- mockChargingStation,
+ mockStation,
OCPP20TransactionEventEnumType.Started,
OCPP20TriggerReasonEnumType.Authorized,
connectorId,
transaction1Id
)
- OCPP20ServiceUtils.resetTransactionSequenceNumber(mockChargingStation, connectorId)
+ OCPP20ServiceUtils.resetTransactionSequenceNumber(mockStation, connectorId)
const event2 = OCPP20ServiceUtils.buildTransactionEvent(
- mockChargingStation,
+ mockStation,
OCPP20TransactionEventEnumType.Started,
OCPP20TriggerReasonEnumType.Authorized,
connectorId,
await describe('E02 - OCPP 2.0.1 Offline TransactionEvent Queueing', async () => {
let mockTracking: MockStationWithTracking
- let mockChargingStation: ChargingStation
+ let mockStation: ChargingStation
let sentRequests: CapturedOCPPRequest[]
let setOnline: (online: boolean) => void
beforeEach(() => {
mockTracking = createMockStationWithRequestTracking()
- mockChargingStation = mockTracking.station
+ mockStation = mockTracking.station
sentRequests = mockTracking.sentRequests
setOnline = mockTracking.setOnline
})
afterEach(() => {
for (let connectorId = 1; connectorId <= 3; connectorId++) {
- const connector = mockChargingStation.getConnectorStatus(connectorId)
+ const connector = mockStation.getConnectorStatus(connectorId)
if (connector != null) {
connector.transactionEventQueue = undefined
}
setOnline(false)
- OCPP20ServiceUtils.resetTransactionSequenceNumber(mockChargingStation, connectorId)
+ OCPP20ServiceUtils.resetTransactionSequenceNumber(mockStation, connectorId)
const response = await OCPP20ServiceUtils.sendTransactionEvent(
- mockChargingStation,
+ mockStation,
OCPP20TransactionEventEnumType.Started,
OCPP20TriggerReasonEnumType.Authorized,
connectorId,
expect(response.idTokenInfo).toBeUndefined()
- const connector = mockChargingStation.getConnectorStatus(connectorId)
+ const connector = mockStation.getConnectorStatus(connectorId)
expect(connector?.transactionEventQueue).toBeDefined()
expect(connector.transactionEventQueue.length).toBe(1)
expect(connector.transactionEventQueue[0].seqNo).toBe(0)
setOnline(false)
- OCPP20ServiceUtils.resetTransactionSequenceNumber(mockChargingStation, connectorId)
+ OCPP20ServiceUtils.resetTransactionSequenceNumber(mockStation, connectorId)
await OCPP20ServiceUtils.sendTransactionEvent(
- mockChargingStation,
+ mockStation,
OCPP20TransactionEventEnumType.Started,
OCPP20TriggerReasonEnumType.Authorized,
connectorId,
)
await OCPP20ServiceUtils.sendTransactionEvent(
- mockChargingStation,
+ mockStation,
OCPP20TransactionEventEnumType.Updated,
OCPP20TriggerReasonEnumType.MeterValuePeriodic,
connectorId,
)
await OCPP20ServiceUtils.sendTransactionEvent(
- mockChargingStation,
+ mockStation,
OCPP20TransactionEventEnumType.Ended,
OCPP20TriggerReasonEnumType.StopAuthorized,
connectorId,
transactionId
)
- const connector = mockChargingStation.getConnectorStatus(connectorId)
+ const connector = mockStation.getConnectorStatus(connectorId)
expect(connector?.transactionEventQueue?.length).toBe(3)
expect(connector.transactionEventQueue[0].seqNo).toBe(0)
const transactionId = generateUUID()
setOnline(true)
- OCPP20ServiceUtils.resetTransactionSequenceNumber(mockChargingStation, connectorId)
+ OCPP20ServiceUtils.resetTransactionSequenceNumber(mockStation, connectorId)
await OCPP20ServiceUtils.sendTransactionEvent(
- mockChargingStation,
+ mockStation,
OCPP20TransactionEventEnumType.Started,
OCPP20TriggerReasonEnumType.Authorized,
connectorId,
setOnline(false)
await OCPP20ServiceUtils.sendTransactionEvent(
- mockChargingStation,
+ mockStation,
OCPP20TransactionEventEnumType.Updated,
OCPP20TriggerReasonEnumType.MeterValuePeriodic,
connectorId,
)
await OCPP20ServiceUtils.sendTransactionEvent(
- mockChargingStation,
+ mockStation,
OCPP20TransactionEventEnumType.Updated,
OCPP20TriggerReasonEnumType.MeterValuePeriodic,
connectorId,
transactionId
)
- const connector = mockChargingStation.getConnectorStatus(connectorId)
+ const connector = mockStation.getConnectorStatus(connectorId)
expect(connector?.transactionEventQueue?.length).toBe(2)
expect(connector.transactionEventQueue[0].seqNo).toBe(1)
expect(connector.transactionEventQueue[1].seqNo).toBe(2)
const transactionId = generateUUID()
setOnline(false)
- OCPP20ServiceUtils.resetTransactionSequenceNumber(mockChargingStation, connectorId)
+ OCPP20ServiceUtils.resetTransactionSequenceNumber(mockStation, connectorId)
const beforeQueue = new Date()
await OCPP20ServiceUtils.sendTransactionEvent(
- mockChargingStation,
+ mockStation,
OCPP20TransactionEventEnumType.Started,
OCPP20TriggerReasonEnumType.Authorized,
connectorId,
)
const afterQueue = new Date()
- const connector = mockChargingStation.getConnectorStatus(connectorId)
+ const connector = mockStation.getConnectorStatus(connectorId)
expect(connector?.transactionEventQueue?.[0]?.timestamp).toBeInstanceOf(Date)
expect(connector.transactionEventQueue[0].timestamp.getTime()).toBeGreaterThanOrEqual(
beforeQueue.getTime()
const transactionId = generateUUID()
setOnline(false)
- OCPP20ServiceUtils.resetTransactionSequenceNumber(mockChargingStation, connectorId)
+ OCPP20ServiceUtils.resetTransactionSequenceNumber(mockStation, connectorId)
await OCPP20ServiceUtils.sendTransactionEvent(
- mockChargingStation,
+ mockStation,
OCPP20TransactionEventEnumType.Started,
OCPP20TriggerReasonEnumType.Authorized,
connectorId,
)
await OCPP20ServiceUtils.sendTransactionEvent(
- mockChargingStation,
+ mockStation,
OCPP20TransactionEventEnumType.Updated,
OCPP20TriggerReasonEnumType.MeterValuePeriodic,
connectorId,
setOnline(true)
- await OCPP20ServiceUtils.sendQueuedTransactionEvents(mockChargingStation, connectorId)
+ await OCPP20ServiceUtils.sendQueuedTransactionEvents(mockStation, connectorId)
expect(sentRequests.length).toBe(2)
expect(sentRequests[0].payload.seqNo).toBe(0)
const transactionId = generateUUID()
setOnline(false)
- OCPP20ServiceUtils.resetTransactionSequenceNumber(mockChargingStation, connectorId)
+ OCPP20ServiceUtils.resetTransactionSequenceNumber(mockStation, connectorId)
await OCPP20ServiceUtils.sendTransactionEvent(
- mockChargingStation,
+ mockStation,
OCPP20TransactionEventEnumType.Started,
OCPP20TriggerReasonEnumType.Authorized,
connectorId,
transactionId
)
- const connector = mockChargingStation.getConnectorStatus(connectorId)
+ const connector = mockStation.getConnectorStatus(connectorId)
expect(connector?.transactionEventQueue?.length).toBe(1)
setOnline(true)
- await OCPP20ServiceUtils.sendQueuedTransactionEvents(mockChargingStation, connectorId)
+ await OCPP20ServiceUtils.sendQueuedTransactionEvents(mockStation, connectorId)
expect(connector.transactionEventQueue.length).toBe(0)
})
const transactionId = generateUUID()
setOnline(false)
- OCPP20ServiceUtils.resetTransactionSequenceNumber(mockChargingStation, connectorId)
+ OCPP20ServiceUtils.resetTransactionSequenceNumber(mockStation, connectorId)
await OCPP20ServiceUtils.sendTransactionEvent(
- mockChargingStation,
+ mockStation,
OCPP20TransactionEventEnumType.Started,
OCPP20TriggerReasonEnumType.Authorized,
connectorId,
)
await OCPP20ServiceUtils.sendTransactionEvent(
- mockChargingStation,
+ mockStation,
OCPP20TransactionEventEnumType.Updated,
OCPP20TriggerReasonEnumType.ChargingStateChanged,
connectorId,
)
await OCPP20ServiceUtils.sendTransactionEvent(
- mockChargingStation,
+ mockStation,
OCPP20TransactionEventEnumType.Ended,
OCPP20TriggerReasonEnumType.StopAuthorized,
connectorId,
)
setOnline(true)
- await OCPP20ServiceUtils.sendQueuedTransactionEvents(mockChargingStation, connectorId)
+ await OCPP20ServiceUtils.sendQueuedTransactionEvents(mockStation, connectorId)
expect(sentRequests[0].payload.eventType).toBe(OCPP20TransactionEventEnumType.Started)
expect(sentRequests[1].payload.eventType).toBe(OCPP20TransactionEventEnumType.Updated)
const connectorId = 1
await expect(
- OCPP20ServiceUtils.sendQueuedTransactionEvents(mockChargingStation, connectorId)
+ OCPP20ServiceUtils.sendQueuedTransactionEvents(mockStation, connectorId)
).resolves.toBeUndefined()
expect(sentRequests.length).toBe(0)
await it('should handle null queue gracefully', async () => {
const connectorId = 1
- const connector = mockChargingStation.getConnectorStatus(connectorId)
+ const connector = mockStation.getConnectorStatus(connectorId)
connector.transactionEventQueue = undefined
await expect(
- OCPP20ServiceUtils.sendQueuedTransactionEvents(mockChargingStation, connectorId)
+ OCPP20ServiceUtils.sendQueuedTransactionEvents(mockStation, connectorId)
).resolves.toBeUndefined()
expect(sentRequests.length).toBe(0)
const transactionId = generateUUID()
setOnline(true)
- OCPP20ServiceUtils.resetTransactionSequenceNumber(mockChargingStation, connectorId)
+ OCPP20ServiceUtils.resetTransactionSequenceNumber(mockStation, connectorId)
await OCPP20ServiceUtils.sendTransactionEvent(
- mockChargingStation,
+ mockStation,
OCPP20TransactionEventEnumType.Started,
OCPP20TriggerReasonEnumType.Authorized,
connectorId,
setOnline(false)
await OCPP20ServiceUtils.sendTransactionEvent(
- mockChargingStation,
+ mockStation,
OCPP20TransactionEventEnumType.Updated,
OCPP20TriggerReasonEnumType.MeterValuePeriodic,
connectorId,
)
await OCPP20ServiceUtils.sendTransactionEvent(
- mockChargingStation,
+ mockStation,
OCPP20TransactionEventEnumType.Updated,
OCPP20TriggerReasonEnumType.MeterValuePeriodic,
connectorId,
setOnline(true)
- await OCPP20ServiceUtils.sendQueuedTransactionEvents(mockChargingStation, connectorId)
+ await OCPP20ServiceUtils.sendQueuedTransactionEvents(mockStation, connectorId)
expect(sentRequests[1].payload.seqNo).toBe(1)
expect(sentRequests[2].payload.seqNo).toBe(2)
await OCPP20ServiceUtils.sendTransactionEvent(
- mockChargingStation,
+ mockStation,
OCPP20TransactionEventEnumType.Ended,
OCPP20TriggerReasonEnumType.StopAuthorized,
connectorId,
const transactionId2 = generateUUID()
setOnline(false)
- OCPP20ServiceUtils.resetTransactionSequenceNumber(mockChargingStation, 1)
- OCPP20ServiceUtils.resetTransactionSequenceNumber(mockChargingStation, 2)
+ OCPP20ServiceUtils.resetTransactionSequenceNumber(mockStation, 1)
+ OCPP20ServiceUtils.resetTransactionSequenceNumber(mockStation, 2)
await OCPP20ServiceUtils.sendTransactionEvent(
- mockChargingStation,
+ mockStation,
OCPP20TransactionEventEnumType.Started,
OCPP20TriggerReasonEnumType.Authorized,
1,
)
await OCPP20ServiceUtils.sendTransactionEvent(
- mockChargingStation,
+ mockStation,
OCPP20TransactionEventEnumType.Started,
OCPP20TriggerReasonEnumType.Authorized,
2,
)
await OCPP20ServiceUtils.sendTransactionEvent(
- mockChargingStation,
+ mockStation,
OCPP20TransactionEventEnumType.Updated,
OCPP20TriggerReasonEnumType.MeterValuePeriodic,
1,
transactionId1
)
- const connector1 = mockChargingStation.getConnectorStatus(1)
- const connector2 = mockChargingStation.getConnectorStatus(2)
+ const connector1 = mockStation.getConnectorStatus(1)
+ const connector2 = mockStation.getConnectorStatus(2)
expect(connector1?.transactionEventQueue?.length).toBe(2)
expect(connector2?.transactionEventQueue?.length).toBe(1)
const transactionId2 = generateUUID()
setOnline(false)
- OCPP20ServiceUtils.resetTransactionSequenceNumber(mockChargingStation, 1)
- OCPP20ServiceUtils.resetTransactionSequenceNumber(mockChargingStation, 2)
+ OCPP20ServiceUtils.resetTransactionSequenceNumber(mockStation, 1)
+ OCPP20ServiceUtils.resetTransactionSequenceNumber(mockStation, 2)
await OCPP20ServiceUtils.sendTransactionEvent(
- mockChargingStation,
+ mockStation,
OCPP20TransactionEventEnumType.Started,
OCPP20TriggerReasonEnumType.Authorized,
1,
)
await OCPP20ServiceUtils.sendTransactionEvent(
- mockChargingStation,
+ mockStation,
OCPP20TransactionEventEnumType.Started,
OCPP20TriggerReasonEnumType.Authorized,
2,
setOnline(true)
- await OCPP20ServiceUtils.sendQueuedTransactionEvents(mockChargingStation, 1)
+ await OCPP20ServiceUtils.sendQueuedTransactionEvents(mockStation, 1)
expect(sentRequests.length).toBe(1)
expect(sentRequests[0].payload.transactionInfo.transactionId).toBe(transactionId1)
- const connector2 = mockChargingStation.getConnectorStatus(2)
+ const connector2 = mockStation.getConnectorStatus(2)
expect(connector2?.transactionEventQueue?.length).toBe(1)
- await OCPP20ServiceUtils.sendQueuedTransactionEvents(mockChargingStation, 2)
+ await OCPP20ServiceUtils.sendQueuedTransactionEvents(mockStation, 2)
expect(sentRequests.length).toBe(2)
expect(sentRequests[1].payload.transactionInfo.transactionId).toBe(transactionId2)
await describe('E02 - OCPP 2.0.1 Periodic TransactionEvent at TxUpdatedInterval', async () => {
let mockTracking: MockStationWithTracking
- let mockChargingStation: ChargingStation
+ let mockStation: ChargingStation
let sentRequests: CapturedOCPPRequest[]
beforeEach(() => {
mockTracking = createMockStationWithRequestTracking()
- mockChargingStation = mockTracking.station
+ mockStation = mockTracking.station
sentRequests = mockTracking.sentRequests
})
afterEach(() => {
// Clean up any running timers
for (let connectorId = 1; connectorId <= 3; connectorId++) {
- const connector = mockChargingStation.getConnectorStatus(connectorId)
+ const connector = mockStation.getConnectorStatus(connectorId)
if (connector?.transactionTxUpdatedSetInterval != null) {
clearInterval(connector.transactionTxUpdatedSetInterval)
connector.transactionTxUpdatedSetInterval = undefined
const connectorId = 1
// Simulate startTxUpdatedInterval with zero interval
- const connector = mockChargingStation.getConnectorStatus(connectorId)
+ const connector = mockStation.getConnectorStatus(connectorId)
expect(connector).toBeDefined()
// Zero interval should not start timer
await it('should not start timer when interval is negative', () => {
const connectorId = 1
- const connector = mockChargingStation.getConnectorStatus(connectorId)
+ const connector = mockStation.getConnectorStatus(connectorId)
expect(connector).toBeDefined()
// Negative interval should not start timer
// Should not throw for non-existent connector
expect(() => {
- mockChargingStation.getConnectorStatus(nonExistentConnectorId)
+ mockStation.getConnectorStatus(nonExistentConnectorId)
}).not.toThrow()
// Should return undefined for non-existent connector
- expect(mockChargingStation.getConnectorStatus(nonExistentConnectorId)).toBeUndefined()
+ expect(mockStation.getConnectorStatus(nonExistentConnectorId)).toBeUndefined()
})
})
const transactionId = generateUUID()
// Reset sequence number
- OCPP20ServiceUtils.resetTransactionSequenceNumber(mockChargingStation, connectorId)
+ OCPP20ServiceUtils.resetTransactionSequenceNumber(mockStation, connectorId)
// Simulate sending periodic TransactionEvent (what the timer callback does)
await OCPP20ServiceUtils.sendTransactionEvent(
- mockChargingStation,
+ mockStation,
OCPP20TransactionEventEnumType.Updated,
OCPP20TriggerReasonEnumType.MeterValuePeriodic,
connectorId,
const transactionId = generateUUID()
// Reset sequence number for new transaction
- OCPP20ServiceUtils.resetTransactionSequenceNumber(mockChargingStation, connectorId)
+ OCPP20ServiceUtils.resetTransactionSequenceNumber(mockStation, connectorId)
// Send initial Started event
const startEvent = OCPP20ServiceUtils.buildTransactionEvent(
- mockChargingStation,
+ mockStation,
OCPP20TransactionEventEnumType.Started,
OCPP20TriggerReasonEnumType.Authorized,
connectorId,
// Send multiple periodic events (simulating timer ticks)
for (let i = 1; i <= 3; i++) {
const periodicEvent = OCPP20ServiceUtils.buildTransactionEvent(
- mockChargingStation,
+ mockStation,
OCPP20TransactionEventEnumType.Updated,
OCPP20TriggerReasonEnumType.MeterValuePeriodic,
connectorId,
}
// Verify sequence numbers are continuous: 0, 1, 2, 3
- const connector = mockChargingStation.getConnectorStatus(connectorId)
+ const connector = mockStation.getConnectorStatus(connectorId)
expect(connector?.transactionSeqNo).toBe(3)
})
const connectorId = 2
const transactionId = generateUUID()
- OCPP20ServiceUtils.resetTransactionSequenceNumber(mockChargingStation, connectorId)
+ OCPP20ServiceUtils.resetTransactionSequenceNumber(mockStation, connectorId)
// Send periodic event
await OCPP20ServiceUtils.sendTransactionEvent(
- mockChargingStation,
+ mockStation,
OCPP20TransactionEventEnumType.Updated,
OCPP20TriggerReasonEnumType.MeterValuePeriodic,
connectorId,
const connectorId = 1
const transactionId = generateUUID()
- OCPP20ServiceUtils.resetTransactionSequenceNumber(mockChargingStation, connectorId)
+ OCPP20ServiceUtils.resetTransactionSequenceNumber(mockStation, connectorId)
await OCPP20ServiceUtils.sendTransactionEvent(
- mockChargingStation,
+ mockStation,
OCPP20TransactionEventEnumType.Updated,
OCPP20TriggerReasonEnumType.MeterValuePeriodic,
connectorId,
const connectorId = 1
const transactionId = generateUUID()
- OCPP20ServiceUtils.resetTransactionSequenceNumber(mockChargingStation, connectorId)
+ OCPP20ServiceUtils.resetTransactionSequenceNumber(mockStation, connectorId)
await OCPP20ServiceUtils.sendTransactionEvent(
- mockChargingStation,
+ mockStation,
OCPP20TransactionEventEnumType.Updated,
OCPP20TriggerReasonEnumType.MeterValuePeriodic,
connectorId,
const transactionId = generateUUID()
// Reset for new transaction
- OCPP20ServiceUtils.resetTransactionSequenceNumber(mockChargingStation, connectorId)
+ OCPP20ServiceUtils.resetTransactionSequenceNumber(mockStation, connectorId)
// Simulate full transaction lifecycle with periodic updates
// 1. Started event (seqNo: 0)
const startEvent = OCPP20ServiceUtils.buildTransactionEvent(
- mockChargingStation,
+ mockStation,
OCPP20TransactionEventEnumType.Started,
OCPP20TriggerReasonEnumType.Authorized,
connectorId,
// 2. Multiple periodic updates (seqNo: 1, 2, 3)
for (let i = 1; i <= 3; i++) {
const updateEvent = OCPP20ServiceUtils.buildTransactionEvent(
- mockChargingStation,
+ mockStation,
OCPP20TransactionEventEnumType.Updated,
OCPP20TriggerReasonEnumType.MeterValuePeriodic,
connectorId,
// 3. Ended event (seqNo: 4)
const endEvent = OCPP20ServiceUtils.buildTransactionEvent(
- mockChargingStation,
+ mockStation,
OCPP20TransactionEventEnumType.Ended,
OCPP20TriggerReasonEnumType.StopAuthorized,
connectorId,
const transactionId2 = generateUUID()
// Reset sequence numbers for both connectors
- OCPP20ServiceUtils.resetTransactionSequenceNumber(mockChargingStation, 1)
- OCPP20ServiceUtils.resetTransactionSequenceNumber(mockChargingStation, 2)
+ OCPP20ServiceUtils.resetTransactionSequenceNumber(mockStation, 1)
+ OCPP20ServiceUtils.resetTransactionSequenceNumber(mockStation, 2)
// Build events for connector 1
const event1Start = OCPP20ServiceUtils.buildTransactionEvent(
- mockChargingStation,
+ mockStation,
OCPP20TransactionEventEnumType.Started,
OCPP20TriggerReasonEnumType.Authorized,
1,
transactionId1
)
const event1Update = OCPP20ServiceUtils.buildTransactionEvent(
- mockChargingStation,
+ mockStation,
OCPP20TransactionEventEnumType.Updated,
OCPP20TriggerReasonEnumType.MeterValuePeriodic,
1,
// Build events for connector 2
const event2Start = OCPP20ServiceUtils.buildTransactionEvent(
- mockChargingStation,
+ mockStation,
OCPP20TransactionEventEnumType.Started,
OCPP20TriggerReasonEnumType.Authorized,
2,
transactionId2
)
const event2Update = OCPP20ServiceUtils.buildTransactionEvent(
- mockChargingStation,
+ mockStation,
OCPP20TransactionEventEnumType.Updated,
OCPP20TriggerReasonEnumType.MeterValuePeriodic,
2,