]> Piment Noir Git Repositories - e-mobility-charging-stations-simulator.git/commitdiff
refactor: adopt canonical helpers over reimplementations (#2120)
authorJérôme Benoit <jerome.benoit@piment-noir.org>
Thu, 17 Sep 2026 19:09:14 +0000 (21:09 +0200)
committerGitHub <noreply@github.com>
Thu, 17 Sep 2026 19:09:14 +0000 (21:09 +0200)
37 files changed:
src/charging-station/meter-values/TransactionIntervalUtils.ts
src/charging-station/ocpp/1.6/OCPP16IncomingRequestService.ts
tests/charging-station/Bootstrap.test.ts
tests/charging-station/ChargingStation-AutoRegisterOcppProtocol.test.ts
tests/charging-station/ChargingStation-NumberOfPhases.test.ts
tests/charging-station/ChargingStation-ResetIdentity.test.ts
tests/charging-station/ChargingStationTestConstants.ts
tests/charging-station/TemplateValidation.test.ts
tests/charging-station/TransactionEventQueueUtils.test.ts
tests/charging-station/TransactionIntervalUtils.test.ts
tests/charging-station/broadcast-channel/ChargingStationWorkerBroadcastChannel.test.ts
tests/charging-station/meter-values/CoherentMeterValues.test.ts
tests/charging-station/meter-values/EvProfiles.test.ts
tests/charging-station/ocpp/1.6/OCPP16IncomingRequestService-LocalAuthList.test.ts
tests/charging-station/ocpp/1.6/OCPP16IncomingRequestService-TriggerMessage.test.ts
tests/charging-station/ocpp/1.6/OCPP16ServiceUtils.test.ts
tests/charging-station/ocpp/1.6/OCPP16TestUtils.ts
tests/charging-station/ocpp/2.0/OCPP20IncomingRequestService-LocalAuthList.test.ts
tests/charging-station/ocpp/2.0/OCPP20IncomingRequestService-TriggerMessage.test.ts
tests/charging-station/ocpp/2.0/OCPP20ResponseService-CacheUpdate.test.ts
tests/charging-station/ocpp/2.0/OCPP20ResponseService-TransactionEvent.test.ts
tests/charging-station/ocpp/2.0/OCPP20ServiceUtils-AlignedMeterValues.test.ts
tests/charging-station/ocpp/2.0/OCPP20ServiceUtils-AuthCache.test.ts
tests/charging-station/ocpp/2.0/OCPP20ServiceUtils-TransactionEvent.test.ts
tests/charging-station/ocpp/auth/OCPPAuthIntegration.test.ts
tests/charging-station/ocpp/auth/adapters/OCPP16AuthAdapter.test.ts
tests/charging-station/ocpp/auth/adapters/OCPP20AuthAdapter.test.ts
tests/charging-station/ocpp/auth/cache/InMemoryAuthCache.test.ts
tests/charging-station/ocpp/auth/cache/InMemoryLocalAuthListManager.test.ts
tests/charging-station/ocpp/auth/strategies/LocalAuthStrategy.test.ts
tests/charging-station/ui-server/UIMCPServer-Integration.test.ts
tests/utils/ConfigurationValidation.test.ts
ui/cli/tests/renderers.test.ts
ui/common/src/utils/payloadBuilders.ts
ui/common/tests/mocks.ts
ui/web/src/shared/utils/stationStatus.ts
ui/web/tests/unit/helpers.ts

index efef3b339b74652daa03deecb6efc17db5d892a4..1280b6faac604d0e56f9143951b4c415ee573cd3 100644 (file)
@@ -1,5 +1,5 @@
 import { type ConnectorStatus, CurrentType, MeterValueMeasurand } from '../../types/index.js'
-import { isEmpty } from '../../utils/index.js'
+import { Constants, isEmpty } from '../../utils/index.js'
 
 export interface TransactionIntervalState {
   consumed: number
@@ -112,7 +112,8 @@ export const getRepresentedTransactionIntervalEnergyWh = (
         : Number.parseFloat(sampledValue.value)
     if (!Number.isFinite(value)) continue
     const unit = sampledValue.unitOfMeasure?.unit ?? sampledValue.unit
-    const unitMultiplier = unit === 'kWh' ? 1000 : unit === 'MWh' ? 1_000_000 : 1
+    const unitMultiplier =
+      unit === 'kWh' ? Constants.UNIT_DIVIDER_KILO : unit === 'MWh' ? 1_000_000 : 1
     const decimalMultiplier = 10 ** (sampledValue.unitOfMeasure?.multiplier ?? 0)
     const phaseMultiplier = /^L[123](?:-N)?$/.test(sampledValue.phase ?? '') ? numberOfPhases : 1
     const locationMultiplier =
index d0b61685742a0819b42d81d9a7c67bb1969eccbc..9911148460665dd4059585c72343aa18c7289517 100644 (file)
@@ -2346,7 +2346,7 @@ export class OCPP16IncomingRequestService extends OCPPIncomingRequestService<OCP
       this.pendingTriggeredMeterValues.delete(target.connectorStatus)
     }
     stationState?.triggeredMeterValueTargets?.delete(target)
-    if (stationState?.triggeredMeterValueTargets?.size === 0) {
+    if (stationState != null && isEmpty(stationState.triggeredMeterValueTargets)) {
       delete stationState.triggeredMeterValueTargets
     }
   }
index a8d808f4b074d322cd0a6a4d3b71da56f5a2b31a..986a6fe3ba017d03c3446942cbdbc5e4c5be6dc1 100644 (file)
@@ -12,10 +12,9 @@ import { mkdirSync, readFileSync, rmSync, writeFileSync } from 'node:fs'
 import { tmpdir } from 'node:os'
 import { join } from 'node:path'
 import { afterEach, beforeEach, describe, it, mock } from 'node:test'
-import { setTimeout as sleep } from 'node:timers/promises'
 
 import { Bootstrap, STATE_FILE_VERSION } from '../../src/charging-station/index.js'
-import { logger } from '../../src/utils/index.js'
+import { logger, sleep } from '../../src/utils/index.js'
 import { resetSingleton, standardCleanup } from '../helpers/TestLifecycleHelpers.js'
 
 interface Barrier {
index 64df91dbbd9eda3e1141aeaecf1ccce53530e9f1..0b7f77797ea029055f82c6656b40624c3f8a797d 100644 (file)
@@ -17,7 +17,7 @@ import { afterEach, describe, it } from 'node:test'
 import type { ChargingStation } from '../../src/charging-station/ChargingStation.js'
 
 import { OCPPProtocol } from '../../src/types/index.js'
-import { buildAddedMessage } from '../../src/utils/MessageChannelUtils.js'
+import { buildAddedMessage } from '../../src/utils/index.js'
 import { flushMicrotasks, standardCleanup } from '../helpers/TestLifecycleHelpers.js'
 import {
   cleanupStationTemplates,
index db6e0907879712444345d7f0026be735d82315e5..d698e80ef33b6b5bad3c9bf777235106ebb7257a 100644 (file)
@@ -15,7 +15,7 @@ import { afterEach, describe, it } from 'node:test'
 
 import type { ChargingStation } from '../../src/charging-station/ChargingStation.js'
 
-import { buildAddedMessage } from '../../src/utils/MessageChannelUtils.js'
+import { buildAddedMessage } from '../../src/utils/index.js'
 import { flushMicrotasks, standardCleanup } from '../helpers/TestLifecycleHelpers.js'
 import {
   cleanupStationTemplates,
index 1a2fc72a766065982d0795bfbba2cb927ad5949b..d50614b43b19a5f3a4c56e5e531882e7fdf212b5 100644 (file)
@@ -8,12 +8,12 @@ import assert from 'node:assert/strict'
 import { existsSync, readdirSync, readFileSync } from 'node:fs'
 import { join } from 'node:path'
 import { afterEach, describe, it } from 'node:test'
-import { setTimeout as sleep } from 'node:timers/promises'
 
 import type { ChargingStation } from '../../src/charging-station/ChargingStation.js'
 import type { ChargingStationOptions } from '../../src/types/index.js'
 
 import { SharedLRUCache } from '../../src/charging-station/SharedLRUCache.js'
+import { sleep } from '../../src/utils/index.js'
 import { standardCleanup } from '../helpers/TestLifecycleHelpers.js'
 import {
   cleanupStationTemplates,
index 4e95d3996f884bea0e17074edcaf5e7e0d6e5872..85cd6e3695115e556f94eaddd07c09bdb06a7713 100644 (file)
@@ -7,6 +7,8 @@
  *   live in `OCPPSpecRequirements.md`.
  */
 
+import { Constants } from '../../src/utils/index.js'
+
 /**
  * Test Station Identifiers
  * Base identifiers used for creating test charging station instances
@@ -26,7 +28,7 @@ export const TEST_HEARTBEAT_INTERVAL_MS = 30000
 export const TEST_AUTHORIZATION_TIMEOUT_MS = 30000
 export const TEST_METER_VALUES_INTERVAL_MS = 30_000
 export const TEST_ONE_HOUR_SECONDS = 3600
-export const TEST_ONE_HOUR_MS = TEST_ONE_HOUR_SECONDS * 1000
+export const TEST_ONE_HOUR_MS = Constants.MS_PER_HOUR
 
 /**
  * Charging Station Information
index 24febf919532a2b299ae883e8f55b790f9a3c5c4..981a25a1559d9ebdecc3db2275840e8264a53c80 100644 (file)
@@ -10,7 +10,7 @@ import { ZodError } from 'zod'
 import { CURRENT_SCHEMA_VERSION } from '../../src/charging-station/index.js'
 import { TemplateValidationError, validateTemplate } from '../../src/charging-station/index.js'
 import { BaseError } from '../../src/exception/index.js'
-import { logger } from '../../src/utils/index.js'
+import { clone, logger } from '../../src/utils/index.js'
 import { mockLoggerWarnDebug, standardCleanup } from '../helpers/TestLifecycleHelpers.js'
 import { TEST_SUPERVISION_URL } from '../utils/TestNetworkConstants.js'
 import { TEST_CHARGING_STATION_BASE_NAME } from './ChargingStationTestConstants.js'
@@ -54,7 +54,7 @@ await describe('TemplateValidation', async () => {
         Connectors: { 0: {}, 1: {} },
         supervisionUrl: TEST_SUPERVISION_URL,
       })
-      const before = structuredClone(parsed)
+      const before = clone(parsed)
 
       validateTemplate(parsed, 'immutable.json')
 
index b8009cafaadfd29de152a1107fc73dedc12987ef..9b027e16546416d95ac688037bb01fd564230439 100644 (file)
@@ -41,7 +41,7 @@ import {
   OCPP20TriggerReasonEnumType,
   OCPP20UnitEnumType,
 } from '../../src/types/index.js'
-import { Constants } from '../../src/utils/index.js'
+import { clone, Constants } from '../../src/utils/index.js'
 import { standardCleanup } from '../helpers/TestLifecycleHelpers.js'
 
 const validateTransactionEvent = createAjv().compile(transactionEventRequestSchema)
@@ -1219,7 +1219,7 @@ await describe('TransactionEventQueueUtils', async () => {
       transactionEventQueue: existingEvents,
       transactionId,
     } as unknown as ConnectorStatus
-    const queueSnapshot = structuredClone(existingEvents)
+    const queueSnapshot = clone(existingEvents)
     const candidate = toQueuedEvent({
       customData: { payload: 'x'.repeat(400_000), vendorId: 'test' },
       eventType: OCPP20TransactionEventEnumType.Updated,
index 32c3acfe49d9585021504343a7a563a76ad8095d..b4aa964b2c9af07b315f2d28e3ea82fb62f5bb9a 100644 (file)
@@ -14,7 +14,7 @@ import {
   recordTransactionIntervalConsumption,
   restoreTransactionIntervalState,
   truncateTransactionIntervalValue,
-} from '../../src/charging-station/meter-values/TransactionIntervalUtils.js'
+} from '../../src/charging-station/meter-values/index.js'
 import { standardCleanup } from '../helpers/TestLifecycleHelpers.js'
 
 await describe('TransactionIntervalUtils', async () => {
index d5a3678ac95f1f1354405aaeeeda33fb801ec65d..2fcb4b78fe0b993dd0943f784a4e153b1a926892 100644 (file)
@@ -6,7 +6,6 @@
  */
 
 import assert from 'node:assert/strict'
-import { randomUUID } from 'node:crypto'
 import { afterEach, describe, it, mock } from 'node:test'
 
 import { ChargingStationWorkerBroadcastChannel } from '../../../src/charging-station/broadcast-channel/ChargingStationWorkerBroadcastChannel.js'
@@ -51,7 +50,7 @@ import {
   StandardParametersKey,
   VendorParametersKey,
 } from '../../../src/types/index.js'
-import { Constants } from '../../../src/utils/index.js'
+import { Constants, generateUUID } from '../../../src/utils/index.js'
 import {
   flushMicrotasks,
   setupConnectorWithTransaction,
@@ -2005,7 +2004,7 @@ await describe('ChargingStationWorkerBroadcastChannel', async () => {
 
       testable.requestHandler({
         data: [
-          randomUUID(),
+          generateUUID(),
           BroadcastChannelProcedureName.GET_15118_EV_CERTIFICATE,
           { hashIds: [station.stationInfo?.hashId] },
         ],
@@ -2025,7 +2024,7 @@ await describe('ChargingStationWorkerBroadcastChannel', async () => {
 
       testable.requestHandler({
         data: [
-          randomUUID(),
+          generateUUID(),
           BroadcastChannelProcedureName.LOG_STATUS_NOTIFICATION,
           { hashIds: [station.stationInfo?.hashId] },
         ],
@@ -2045,7 +2044,7 @@ await describe('ChargingStationWorkerBroadcastChannel', async () => {
 
       testable.requestHandler({
         data: [
-          randomUUID(),
+          generateUUID(),
           BroadcastChannelProcedureName.NOTIFY_CUSTOMER_INFORMATION,
           { hashIds: [station.stationInfo?.hashId] },
         ],
@@ -2065,7 +2064,7 @@ await describe('ChargingStationWorkerBroadcastChannel', async () => {
 
       testable.requestHandler({
         data: [
-          randomUUID(),
+          generateUUID(),
           BroadcastChannelProcedureName.NOTIFY_REPORT,
           { hashIds: [station.stationInfo?.hashId] },
         ],
@@ -2085,7 +2084,7 @@ await describe('ChargingStationWorkerBroadcastChannel', async () => {
 
       testable.requestHandler({
         data: [
-          randomUUID(),
+          generateUUID(),
           BroadcastChannelProcedureName.SECURITY_EVENT_NOTIFICATION,
           { hashIds: [station.stationInfo?.hashId] },
         ],
@@ -2119,7 +2118,7 @@ await describe('ChargingStationWorkerBroadcastChannel', async () => {
 
       testable.requestHandler({
         data: [
-          randomUUID(),
+          generateUUID(),
           BroadcastChannelProcedureName.METER_VALUES,
           { connectorId: 1, hashIds: [station.stationInfo?.hashId] },
         ],
@@ -2243,7 +2242,7 @@ await describe('ChargingStationWorkerBroadcastChannel', async () => {
 
       testable.requestHandler({
         data: [
-          randomUUID(),
+          generateUUID(),
           BroadcastChannelProcedureName.METER_VALUES,
           { evseId: 1, hashIds: [station.stationInfo?.hashId] },
         ],
@@ -2285,7 +2284,7 @@ await describe('ChargingStationWorkerBroadcastChannel', async () => {
 
       testable.requestHandler({
         data: [
-          randomUUID(),
+          generateUUID(),
           BroadcastChannelProcedureName.METER_VALUES,
           {
             connectorId: 1,
index 9dba091d17fa6760d8727f5cb606894d8e18c116..1887902f0181b6c646dbd38f9d4c5fa3ee1545fa 100644 (file)
 import assert from 'node:assert/strict'
 import { afterEach, describe, it } from 'node:test'
 
-import type { BuildVersionedSampledValue } from '../../../src/charging-station/meter-values/CoherentMeterValueBuilder.js'
 import type {
+  BuildVersionedSampledValue,
   CoherentSession,
   EvProfile,
   ICoherentContext,
-} from '../../../src/charging-station/meter-values/types.js'
+} from '../../../src/charging-station/meter-values/index.js'
 import type {
   ChargingStationInfo,
   ConnectorStatus,
@@ -25,18 +25,16 @@ import type {
   SampledValueTemplate,
 } from '../../../src/types/index.js'
 
-import {
-  buildCoherentMeterValue,
-  buildCoherentMeterValueSnapshot,
-} from '../../../src/charging-station/meter-values/CoherentMeterValueBuilder.js'
 import {
   computeCoherentSample,
   disposeCoherentSessionRuntime,
 } from '../../../src/charging-station/meter-values/CoherentSampleComputer.js'
 import {
+  buildCoherentMeterValue,
+  buildCoherentMeterValueSnapshot,
   createCoherentSession,
   resolveRootSeed,
-} from '../../../src/charging-station/meter-values/CoherentSession.js'
+} from '../../../src/charging-station/meter-values/index.js'
 import { hashLabel } from '../../../src/charging-station/meter-values/PRNG.js'
 import { buildOCPP20SampledValue } from '../../../src/charging-station/ocpp/2.0/OCPP20RequestBuilders.js'
 import {
index 2945517a7014775d186f6df24d544c098729f1c9..a2c748703b38bea7cda9244e9e197fd4307005bf 100644 (file)
@@ -12,7 +12,7 @@
 import assert from 'node:assert/strict'
 import { afterEach, describe, it } from 'node:test'
 
-import type { EvProfile } from '../../../src/charging-station/meter-values/types.js'
+import type { EvProfile } from '../../../src/charging-station/meter-values/index.js'
 
 import {
   interpolateChargingCurve,
index 1f4aaf28f4daf4702d64f41475a47c8efaae1a80..ca4a550bfc5d97535547456ae3f2397143df361b 100644 (file)
@@ -11,11 +11,13 @@ import type { ChargingStation } from '../../../../src/charging-station/index.js'
 import type {
   LocalAuthListManager,
   OCPPAuthService,
-} from '../../../../src/charging-station/ocpp/auth/interfaces/OCPPAuthService.js'
+} from '../../../../src/charging-station/ocpp/auth/index.js'
 import type { OCPP16SendLocalListRequest } from '../../../../src/types/index.js'
 
-import { InMemoryLocalAuthListManager } from '../../../../src/charging-station/ocpp/auth/cache/InMemoryLocalAuthListManager.js'
-import { OCPPAuthServiceFactory } from '../../../../src/charging-station/ocpp/auth/services/OCPPAuthServiceFactory.js'
+import {
+  InMemoryLocalAuthListManager,
+  OCPPAuthServiceFactory,
+} from '../../../../src/charging-station/ocpp/auth/index.js'
 import {
   OCPP16AuthorizationStatus,
   OCPP16StandardParametersKey,
index 0b7678476370a82ea6675b20c3776692da1805b7..40813f0a796f28feb2fbf20558ad89ea11d31f13 100644 (file)
@@ -20,7 +20,7 @@ import type {
   RequestParams,
 } from '../../../../src/types/index.js'
 
-import { TransactionMeterValueDeliveryBarrier } from '../../../../src/charging-station/meter-values/TransactionMeterValueDeliveryBarrier.js'
+import { TransactionMeterValueDeliveryBarrier } from '../../../../src/charging-station/meter-values/index.js'
 import { createTestableIncomingRequestService } from '../../../../src/charging-station/ocpp/1.6/__testable__/index.js'
 import { OCPP16IncomingRequestService } from '../../../../src/charging-station/ocpp/1.6/OCPP16IncomingRequestService.js'
 import { OCPP16ServiceUtils } from '../../../../src/charging-station/ocpp/1.6/OCPP16ServiceUtils.js'
index fc92df8b11ad92855d02a250b1a63af56c889b07..c5bf529d4909e6b932acca76ff777c05e3ecbb22 100644 (file)
@@ -51,6 +51,7 @@ import {
   OCPPVersion,
   type RequestParams,
 } from '../../../../src/types/index.js'
+import { clone } from '../../../../src/utils/index.js'
 import {
   flushMicrotasks,
   setupConnectorWithTransaction,
@@ -1514,7 +1515,7 @@ await describe('OCPP16ServiceUtils — pure functions', async () => {
           timestamp: new Date('2026-09-08T12:34:56.000Z'),
         },
       ]
-      const expectedTransactionData = structuredClone(transactionData)
+      const expectedTransactionData = clone(transactionData)
 
       const stop = OCPP16ServiceUtils.stopTransactionOnConnector(station, 1, undefined, {
         transactionData,
index 65cd58749f13eeb88ad0c4d3c9d3464f4fa631f1..aeae4cf6b67f810dfb73a0ad35cd8beb153aa6b2 100644 (file)
@@ -459,7 +459,7 @@ export const ReservationFixtures = {
     connectorId = 1,
     reservationId = 1,
     idTag = TEST_ID_TAG,
-    expiryDate = new Date(Date.now() + 3600000)
+    expiryDate = new Date(Date.now() + Constants.MS_PER_HOUR)
   ) => ({
     connectorId,
     expiryDate,
index bb95c5845283d7f219dbe7e46a7c74a897f18f31..eca41fa9a0b84d304e2081bfb0b463652f1ae681 100644 (file)
@@ -7,7 +7,7 @@ import assert from 'node:assert/strict'
 import { afterEach, beforeEach, describe, it } from 'node:test'
 
 import type { ChargingStation } from '../../../../src/charging-station/index.js'
-import type { LocalAuthListManager } from '../../../../src/charging-station/ocpp/auth/interfaces/OCPPAuthService.js'
+import type { LocalAuthListManager } from '../../../../src/charging-station/ocpp/auth/index.js'
 
 import { buildConfigKey } from '../../../../src/charging-station/index.js'
 import { createTestableIncomingRequestService } from '../../../../src/charging-station/ocpp/2.0/__testable__/index.js'
index dce77bbcd2b8bd8967d74d15051b275ba733b714..4db42dad7741d153c0ac5154ecc9b8432225ba25 100644 (file)
@@ -21,7 +21,7 @@ import type { MockChargingStation } from '../../helpers/StationHelpers.js'
 
 import { ChargingStation } from '../../../../src/charging-station/ChargingStation.js'
 import { addConfigurationKey, buildConfigKey } from '../../../../src/charging-station/index.js'
-import { TransactionMeterValueDeliveryBarrier } from '../../../../src/charging-station/meter-values/TransactionMeterValueDeliveryBarrier.js'
+import { TransactionMeterValueDeliveryBarrier } from '../../../../src/charging-station/meter-values/index.js'
 import { createTestableIncomingRequestService } from '../../../../src/charging-station/ocpp/2.0/__testable__/index.js'
 import { OCPP20IncomingRequestService } from '../../../../src/charging-station/ocpp/2.0/OCPP20IncomingRequestService.js'
 import { OCPP20ServiceUtils } from '../../../../src/charging-station/ocpp/2.0/OCPP20ServiceUtils.js'
index bc4541662fb81781ff6c8d5a078bae2d1775b852..a2e5a2834909cd0b95996ab41f68201c780ea0b8 100644 (file)
@@ -8,7 +8,7 @@ import assert from 'node:assert/strict'
 import { afterEach, beforeEach, describe, it } from 'node:test'
 
 import type { ChargingStation } from '../../../../src/charging-station/index.js'
-import type { AuthCache } from '../../../../src/charging-station/ocpp/auth/interfaces/OCPPAuthService.js'
+import type { AuthCache } from '../../../../src/charging-station/ocpp/auth/index.js'
 
 import {
   AuthResultStatus,
index 537144241063fd380c33a228c2607b0957d17722..a26042b821114c51db4be656a826a480613df375 100644 (file)
@@ -36,7 +36,7 @@ import {
   OCPP20TransactionEventEnumType,
   OCPPVersion,
 } from '../../../../src/types/index.js'
-import { Constants } from '../../../../src/utils/index.js'
+import { clone, Constants } from '../../../../src/utils/index.js'
 import {
   flushMicrotasks,
   setupConnectorWithTransaction,
@@ -381,7 +381,7 @@ await describe('D01 - TransactionEvent Response', async () => {
       OCPP20TransactionEventEnumType.Started
     )
     staleRequest.seqNo = 0
-    const replacementRequest = structuredClone(staleRequest)
+    const replacementRequest = clone(staleRequest)
     connectorStatus.transactionEventQueue = [
       { request: replacementRequest, seqNo: 0, timestamp: replacementRequest.timestamp },
     ]
index 94dc59efff5f233dd64f58d152e3db5be9a1ee45..8c01efcc597b5c8686d5f8e5b8606055f4230c6c 100644 (file)
@@ -10,7 +10,7 @@ import type { Mock } from 'node:test'
 import assert from 'node:assert/strict'
 import { afterEach, beforeEach, describe, it, mock } from 'node:test'
 
-import type { CoherentSession } from '../../../../src/charging-station/meter-values/types.js'
+import type { CoherentSession } from '../../../../src/charging-station/meter-values/index.js'
 import type {
   ChargingStationInfo,
   ConnectorStatus,
@@ -36,8 +36,10 @@ import {
   getConfigurationKey,
 } from '../../../../src/charging-station/index.js'
 import { computeCoherentSample } from '../../../../src/charging-station/meter-values/CoherentSampleComputer.js'
-import { recordTransactionIntervalConsumption } from '../../../../src/charging-station/meter-values/TransactionIntervalUtils.js'
-import { TransactionMeterValueDeliveryBarrier } from '../../../../src/charging-station/meter-values/TransactionMeterValueDeliveryBarrier.js'
+import {
+  recordTransactionIntervalConsumption,
+  TransactionMeterValueDeliveryBarrier,
+} from '../../../../src/charging-station/meter-values/index.js'
 import {
   createTestableIncomingRequestService,
   type TestableOCPP20IncomingRequestService,
@@ -83,7 +85,7 @@ import {
   SigningMethodEnumType,
   Voltage,
 } from '../../../../src/types/index.js'
-import { Constants } from '../../../../src/utils/index.js'
+import { clone, Constants } from '../../../../src/utils/index.js'
 import {
   setupConnectorWithTransaction,
   standardCleanup,
@@ -7460,7 +7462,7 @@ await describe('J01 - Autonomous clock-aligned MeterValues (#2011 Category 2F)',
           unit: 'Wh',
         },
       ] as unknown as EvseStatus['MeterValues']
-      stationEvse.MeterValues = structuredClone(sharedMeterValues)
+      stationEvse.MeterValues = clone(sharedMeterValues)
       evseStatus.MeterValues = sharedMeterValues
       upsertConfigurationKey(mockStation, ALIGNED_DATA_INTERVAL_KEY, '60')
       upsertConfigurationKey(mockStation, ALIGNED_ENABLED_KEY, 'true')
index d8c0be5a3badb333033c6e5d8ec3b35fc3304e8d..2edb348865a2371367260b0e1143b0940adafa2a 100644 (file)
@@ -8,7 +8,7 @@ import assert from 'node:assert/strict'
 import { afterEach, beforeEach, describe, it } from 'node:test'
 
 import type { ChargingStation } from '../../../../src/charging-station/index.js'
-import type { AuthCache } from '../../../../src/charging-station/ocpp/auth/interfaces/OCPPAuthService.js'
+import type { AuthCache } from '../../../../src/charging-station/ocpp/auth/index.js'
 
 import { OCPP20ServiceUtils } from '../../../../src/charging-station/ocpp/2.0/OCPP20ServiceUtils.js'
 import {
index bab684d2954030b7c09e8cf85bc9c3c8c6604ab1..24acb93a31e69e75009860a279574e1cad8ffb64 100644 (file)
@@ -13,7 +13,7 @@
 import assert from 'node:assert/strict'
 import { afterEach, beforeEach, describe, it, mock } from 'node:test'
 
-import type { CoherentSession } from '../../../../src/charging-station/meter-values/types.js'
+import type { CoherentSession } from '../../../../src/charging-station/meter-values/index.js'
 import type { ConnectorStatus, EmptyObject, EvseStatus } from '../../../../src/types/index.js'
 
 import { ChargingStation } from '../../../../src/charging-station/ChargingStation.js'
@@ -22,8 +22,10 @@ import {
   preparePersistedTransactionEventQueue,
 } from '../../../../src/charging-station/HelpersConnectorStatus.js'
 import { addConfigurationKey, buildConfigKey } from '../../../../src/charging-station/index.js'
-import { recordTransactionIntervalConsumption } from '../../../../src/charging-station/meter-values/TransactionIntervalUtils.js'
-import { TransactionMeterValueDeliveryBarrier } from '../../../../src/charging-station/meter-values/TransactionMeterValueDeliveryBarrier.js'
+import {
+  recordTransactionIntervalConsumption,
+  TransactionMeterValueDeliveryBarrier,
+} from '../../../../src/charging-station/meter-values/index.js'
 import { createTestableResponseService } from '../../../../src/charging-station/ocpp/2.0/__testable__/index.js'
 import { buildOCPP20SampledValue } from '../../../../src/charging-station/ocpp/2.0/OCPP20RequestBuilders.js'
 import { OCPP20ResponseService } from '../../../../src/charging-station/ocpp/2.0/OCPP20ResponseService.js'
@@ -72,7 +74,7 @@ import {
   SigningMethodEnumType,
   Voltage,
 } from '../../../../src/types/index.js'
-import { Constants, generateUUID } from '../../../../src/utils/index.js'
+import { clone, Constants, generateUUID } from '../../../../src/utils/index.js'
 import {
   flushMicrotasks,
   setupConnectorWithTransaction,
@@ -4451,7 +4453,7 @@ await describe('OCPP20 TransactionEvent ServiceUtils', async () => {
             requestParams.onTransportError?.(replayFailure, false)
             throw replayFailure
           }
-          transportedRequests.push(structuredClone(request))
+          transportedRequests.push(clone(request))
           requestParams.onMessageSent?.()
           requestParams.onResponseReceived?.()
           return {}
@@ -8698,7 +8700,7 @@ await describe('OCPP20 TransactionEvent ServiceUtils', async () => {
       connectorStatus.transactionStarting = true
       connectorStatus.transactionRestored = true
       const queuedEvent = connectorStatus.transactionEventQueue[0]
-      const originalPayload = structuredClone(queuedEvent.request)
+      const originalPayload = clone(queuedEvent.request)
       const saveQueueSpy = mock.method(station, 'saveTransactionEventQueues')
       online = true
 
@@ -9491,7 +9493,7 @@ await describe('OCPP20 TransactionEvent ServiceUtils', async () => {
           64
       )
       const originalQueue = [queuedUpdated]
-      const originalEvent = structuredClone(queuedUpdated)
+      const originalEvent = clone(queuedUpdated)
       connectorStatus.transactionEventQueue = originalQueue
       mock.method(mockTracking.station, 'persistTransactionEventQueues', () => {
         persistenceStarted.resolve(undefined)
@@ -9499,7 +9501,7 @@ await describe('OCPP20 TransactionEvent ServiceUtils', async () => {
       })
       const savedQueues: unknown[][] = []
       mock.method(mockTracking.station, 'saveTransactionEventQueues', () => {
-        savedQueues.push(structuredClone(connectorStatus.transactionEventQueue ?? []))
+        savedQueues.push(clone(connectorStatus.transactionEventQueue ?? []))
       })
 
       const stopped = OCPP20ServiceUtils.requestStopTransaction(
@@ -10353,7 +10355,7 @@ await describe('OCPP20 TransactionEvent ServiceUtils', async () => {
             64
         )
         const originalQueue = [queuedUpdated]
-        const originalEvent = structuredClone(queuedUpdated)
+        const originalEvent = clone(queuedUpdated)
         connectorStatus.transactionEventQueue = originalQueue
         let persistenceCalls = 0
         mock.method(mockTracking.station, 'persistTransactionEventQueues', () => {
@@ -10524,7 +10526,7 @@ await describe('OCPP20 TransactionEvent ServiceUtils', async () => {
           timestamp: new Date(10_000),
         },
       ]
-      const originalEndedMeterValues = structuredClone(connectorStatus.transactionEndedMeterValues)
+      const originalEndedMeterValues = clone(connectorStatus.transactionEndedMeterValues)
       OCPP20ServiceUtils.startEndedMeterValues(mockTracking.station, connectorId, 60_000, 1)
 
       await assert.rejects(
index 0bdbf5949ee89692cfc005c25fc1862d8a381475..c8138d5584659cc32ba797667742a3709cd34234 100644 (file)
@@ -9,14 +9,14 @@ import { afterEach, beforeEach, describe, it } from 'node:test'
 import type { ChargingStation } from '../../../../src/charging-station/index.js'
 
 import { InMemoryAuthCache } from '../../../../src/charging-station/ocpp/auth/cache/InMemoryAuthCache.js'
-import { OCPPAuthServiceImpl } from '../../../../src/charging-station/ocpp/auth/services/OCPPAuthServiceImpl.js'
-import { LocalAuthStrategy } from '../../../../src/charging-station/ocpp/auth/strategies/LocalAuthStrategy.js'
 import {
   AuthContext,
   AuthenticationMethod,
   AuthResultStatus,
   IdentifierType,
-} from '../../../../src/charging-station/ocpp/auth/types/AuthTypes.js'
+} from '../../../../src/charging-station/ocpp/auth/index.js'
+import { OCPPAuthServiceImpl } from '../../../../src/charging-station/ocpp/auth/services/OCPPAuthServiceImpl.js'
+import { LocalAuthStrategy } from '../../../../src/charging-station/ocpp/auth/strategies/LocalAuthStrategy.js'
 import { OCPPVersion } from '../../../../src/types/index.js'
 import { standardCleanup } from '../../../helpers/TestLifecycleHelpers.js'
 import { createMockChargingStation } from '../../helpers/StationHelpers.js'
index 4f2dda2471893e2faf2408e52cd4bc26cc607e60..049e2734fc6a527213dc1f60d397ec970cac7f7e 100644 (file)
@@ -15,8 +15,9 @@ import {
   AuthenticationMethod,
   AuthResultStatus,
   IdentifierType,
-} from '../../../../../src/charging-station/ocpp/auth/types/AuthTypes.js'
+} from '../../../../../src/charging-station/ocpp/auth/index.js'
 import { OCPP16AuthorizationStatus, OCPPVersion } from '../../../../../src/types/index.js'
+import { Constants } from '../../../../../src/utils/index.js'
 import { standardCleanup } from '../../../../helpers/TestLifecycleHelpers.js'
 import { TEST_ID_TAG_VALID } from '../../../ChargingStationTestConstants.js'
 import { createMockAuthorizationResult, createMockIdentifier } from '../helpers/MockFactories.js'
@@ -39,7 +40,7 @@ await describe('OCPP16AuthAdapter', async () => {
           new Promise<OCPP16AuthorizeResponse>(resolve => {
             resolve({
               idTagInfo: {
-                expiryDate: new Date(Date.now() + 86400000),
+                expiryDate: new Date(Date.now() + Constants.MS_PER_DAY),
                 parentIdTag: undefined,
                 status: OCPP16AuthorizationStatus.ACCEPTED,
               },
index 7f80781ca6f3016a86a508578df1314966bf848c..d7e9bb447755e7ddae69a1655c20c3cfca30f9a5 100644 (file)
@@ -15,7 +15,7 @@ import {
   AuthenticationMethod,
   AuthResultStatus,
   IdentifierType,
-} from '../../../../../src/charging-station/ocpp/auth/types/AuthTypes.js'
+} from '../../../../../src/charging-station/ocpp/auth/index.js'
 import {
   OCPP20AuthorizationStatusEnumType,
   OCPP20IdTokenEnumType,
index 7e81210542643708bfeaabcd88a3768ddb7b7042..bf8da084f8244753fc033511ca7db7969ed2b894 100644 (file)
@@ -5,13 +5,13 @@
 import assert from 'node:assert/strict'
 import { afterEach, beforeEach, describe, it } from 'node:test'
 
-import type { AuthorizationResult } from '../../../../../src/charging-station/ocpp/auth/types/AuthTypes.js'
+import type { AuthorizationResult } from '../../../../../src/charging-station/ocpp/auth/index.js'
 
 import { InMemoryAuthCache } from '../../../../../src/charging-station/ocpp/auth/cache/InMemoryAuthCache.js'
 import {
   AuthenticationMethod,
   AuthResultStatus,
-} from '../../../../../src/charging-station/ocpp/auth/types/AuthTypes.js'
+} from '../../../../../src/charging-station/ocpp/auth/index.js'
 import { standardCleanup, withMockTimers } from '../../../../helpers/TestLifecycleHelpers.js'
 import { createMockAuthorizationResult } from '../helpers/MockFactories.js'
 
index 68447a50b1961c37f251a09062d719469b043aa0..87d8203d1548e1b6a6fadb264305f346311c999c 100644 (file)
@@ -5,10 +5,12 @@
 import assert from 'node:assert/strict'
 import { afterEach, beforeEach, describe, it } from 'node:test'
 
-import type { DifferentialAuthEntry } from '../../../../../src/charging-station/ocpp/auth/interfaces/OCPPAuthService.js'
-import type { LocalAuthEntry } from '../../../../../src/charging-station/ocpp/auth/interfaces/OCPPAuthService.js'
+import type {
+  DifferentialAuthEntry,
+  LocalAuthEntry,
+} from '../../../../../src/charging-station/ocpp/auth/index.js'
 
-import { InMemoryLocalAuthListManager } from '../../../../../src/charging-station/ocpp/auth/cache/InMemoryLocalAuthListManager.js'
+import { InMemoryLocalAuthListManager } from '../../../../../src/charging-station/ocpp/auth/index.js'
 import { standardCleanup } from '../../../../helpers/TestLifecycleHelpers.js'
 
 const createEntry = (
index 0fe78be91918e1d9af170ebbf4db3deef78cedb0..5fa4dc5614831162917341fd7cfa2aa190d9fbcf 100644 (file)
@@ -17,6 +17,7 @@ import {
   AuthResultStatus,
   IdentifierType,
 } from '../../../../../src/charging-station/ocpp/auth/types/AuthTypes.js'
+import { Constants } from '../../../../../src/utils/index.js'
 import { standardCleanup } from '../../../../helpers/TestLifecycleHelpers.js'
 import {
   createMockAuthCache,
@@ -104,7 +105,7 @@ await describe('LocalAuthStrategy', async () => {
 
     await it('should authenticate using local auth list', () => {
       mockLocalAuthListManager.getEntry = () => ({
-        expiryDate: new Date(Date.now() + 86400000),
+        expiryDate: new Date(Date.now() + Constants.MS_PER_DAY),
         identifier: 'LOCAL_TAG',
         metadata: { source: 'local' },
         status: 'accepted',
index 1e821b29676b7ebb9d3e91cb3342a4c19be189d6..85f06c37ca86d6542aaf204c55e3a6411c4bf96e 100644 (file)
@@ -5,6 +5,7 @@
 
 import type { AddressInfo } from 'node:net'
 
+import { format } from 'date-fns'
 import assert from 'node:assert/strict'
 import { request as httpRequest, type Server } from 'node:http'
 import { join } from 'node:path'
@@ -200,7 +201,7 @@ await describe('UIMCPServer HTTP Integration', async () => {
     await it('should return log content with default date (current local date)', async () => {
       // Arrange
       const now = new Date()
-      const todayDate = `${now.getFullYear().toString()}-${(now.getMonth() + 1).toString().padStart(2, '0')}-${now.getDate().toString().padStart(2, '0')}`
+      const todayDate = format(now, 'yyyy-MM-dd')
       writeTempFile(
         logTmpDir,
         `combined-${todayDate}.log`,
index 21920219e5e869b364eaca0d8006c5401b27d76e..b12833ef39abfa7a0231fd177e5cefe74af4c24b 100644 (file)
@@ -15,7 +15,7 @@ import {
   DEPRECATED_KEY_REMAPPINGS,
 } from '../../src/utils/index.js'
 import { ConfigurationValidationError, validateConfiguration } from '../../src/utils/index.js'
-import { logger } from '../../src/utils/index.js'
+import { clone, logger } from '../../src/utils/index.js'
 import { standardCleanup } from '../helpers/TestLifecycleHelpers.js'
 import {
   buildLegacyConfiguration,
@@ -276,7 +276,7 @@ await describe('ConfigurationValidation', async () => {
     await it('should not mutate the caller-supplied parsed object', t => {
       t.mock.method(console, 'warn', () => undefined)
       const parsed = buildLegacyConfiguration()
-      const before = structuredClone(parsed)
+      const before = clone(parsed)
 
       validateConfiguration(parsed, 'immutable.json')
 
index 6acd0bfd284ef2e97819bb4ac3626c1f984f0764..5603496bd291c12912515af2ea6714800027ab79 100644 (file)
@@ -1,6 +1,11 @@
 import assert from 'node:assert'
 import { describe, it } from 'node:test'
-import { OCPP16AvailabilityType, OCPP16ChargePointStatus, ResponseStatus } from 'ui-common'
+import {
+  OCPP16AvailabilityType,
+  OCPP16ChargePointStatus,
+  ResponseStatus,
+  WebSocketReadyState,
+} from 'ui-common'
 
 import { tryRenderPayload } from '../src/output/renderers.js'
 import { captureStream } from './helpers.js'
@@ -25,7 +30,7 @@ const stationListPayload = {
         ocppVersion: '2.0.1',
         templateName: 'test.station-template',
       },
-      wsState: 1,
+      wsState: WebSocketReadyState.OPEN,
     },
   ],
   status: ResponseStatus.SUCCESS,
index 790fed1dbabc9cef5acace5deb5981a4e9370a4f..169a8045e9a5f17e7fb29a0926565b9e689bd9e4 100644 (file)
@@ -20,7 +20,7 @@ export function buildAuthorizePayload (
 ): RequestPayload {
   if (isOCPP20x(ocppVersion)) {
     return {
-      idToken: { idToken: idTag, type: OCPP20IdTokenEnumType.ISO14443 },
+      idToken: buildIdToken(idTag),
     }
   }
   assertOCPP16OrUndefined(ocppVersion)
@@ -63,9 +63,7 @@ export function buildStartTransactionPayload (
         connectorId,
         eventType: OCPP20TransactionEventEnumType.STARTED,
         ...(options?.evseId != null && { evseId: options.evseId }),
-        ...(options?.idTag != null && {
-          idToken: { idToken: options.idTag, type: OCPP20IdTokenEnumType.ISO14443 },
-        }),
+        ...(options?.idTag != null && { idToken: buildIdToken(options.idTag) }),
       },
       procedureName: ProcedureName.TRANSACTION_EVENT,
     }
index c429f64b510b25308cefa2a32e7a22d4c7a84675..d8dbde094286ae5e003e2bd16a4fc345aefd5ae6 100644 (file)
@@ -1,6 +1,6 @@
 /** @file Shared mock factories for WebSocket-based tests */
 
-import type { WebSocketLike } from '../src/client/types.js'
+import { type WebSocketLike, WebSocketReadyState } from '../src/client/types.js'
 
 export interface MockWebSocketLike extends WebSocketLike {
   sentMessages: string[]
@@ -19,11 +19,11 @@ export function createMockWebSocketLike (): MockWebSocketLike {
   let onmessageFn: ((event: { data: string }) => void) | null = null
   let onopenFn: (() => void) | null = null
   const sentMessages: string[] = []
-  let readyState: 0 | 1 | 2 | 3 = 1
+  let readyState: WebSocketReadyState = WebSocketReadyState.OPEN
 
   return {
     close (code?: number, reason?: string) {
-      readyState = 3
+      readyState = WebSocketReadyState.CLOSED
       oncloseFn?.({ code: code ?? 1000, reason: reason ?? '' })
     },
     get onclose () {
@@ -58,7 +58,7 @@ export function createMockWebSocketLike (): MockWebSocketLike {
     },
     sentMessages,
     triggerClose (code?: number, reason?: string) {
-      readyState = 3
+      readyState = WebSocketReadyState.CLOSED
       oncloseFn?.({ code: code ?? 1000, reason: reason ?? '' })
     },
     triggerError (message) {
index ae8479fc88167581ae5a94add3cb23c40736cad5..1f5aec875d2d2ed8ec7edcbb99fc1520fda8b198 100644 (file)
@@ -4,7 +4,12 @@
  * These are not Vue composables (no reactive state) — they are pure utility functions
  * consumed exclusively by skin components via the shared layer.
  */
-import type { ChargingStationData, ConnectorEntry, Status } from 'ui-common'
+import {
+  type ChargingStationData,
+  type ConnectorEntry,
+  type Status,
+  WebSocketReadyState,
+} from 'ui-common'
 
 /**
  * Status variant type for UI display.
@@ -82,11 +87,6 @@ export function getConnectorStatusVariant (status?: string): StatusVariant {
   return CONNECTOR_STATUS_VARIANT[status.toLowerCase()] ?? 'idle'
 }
 
-const WS_STATE_CLOSED = 3
-const WS_STATE_CLOSING = 2
-const WS_STATE_CONNECTING = 0
-const WS_STATE_OPEN = 1
-
 /**
  * Maps a WebSocket ready state to a display variant.
  * @param wsState - The WebSocket readyState value
@@ -94,13 +94,13 @@ const WS_STATE_OPEN = 1
  */
 export function getWebSocketStateVariant (wsState?: number): StatusVariant {
   switch (wsState) {
-    case WS_STATE_CLOSED:
+    case WebSocketReadyState.CLOSED:
       return 'err'
-    case WS_STATE_CLOSING:
+    case WebSocketReadyState.CLOSING:
       return 'warn'
-    case WS_STATE_CONNECTING:
+    case WebSocketReadyState.CONNECTING:
       return 'warn'
-    case WS_STATE_OPEN:
+    case WebSocketReadyState.OPEN:
       return 'ok'
     default:
       return 'idle'
index 9d256aed95aab14a49b4c1bbe61444438030c0d1..8ff7042725e7d38131f1d8e78128a669a3e06085 100644 (file)
@@ -2,7 +2,7 @@
  * @file Shared test utilities for Vue.js web UI unit tests
  * @description MockWebSocket, withSetup composable helper, mock factories.
  */
-import { ResponseStatus } from 'ui-common'
+import { ResponseStatus, WebSocketReadyState } from 'ui-common'
 import { vi } from 'vitest'
 import { type App, createApp } from 'vue'
 
@@ -73,23 +73,21 @@ export const ToggleButtonStub = {
 // ── MockWebSocket ─────────────────────────────────────────────────────────────
 
 export class MockWebSocket {
-  static readonly CLOSED = 3
-  static readonly CLOSING = 2
-  static readonly CONNECTING = 0
+  static readonly CLOSED = WebSocketReadyState.CLOSED
+  static readonly CLOSING = WebSocketReadyState.CLOSING
   static lastInstance: MockWebSocket | null = null
-  static readonly OPEN = 1
+  static readonly OPEN = WebSocketReadyState.OPEN
 
   addEventListener: ReturnType<typeof vi.fn>
   close: ReturnType<typeof vi.fn>
-  readonly CLOSED = 3
-  readonly CLOSING = 2
-  readonly CONNECTING = 0
+  readonly CLOSED = WebSocketReadyState.CLOSED
+  readonly CLOSING = WebSocketReadyState.CLOSING
   onclose: ((event: CloseEvent) => void) | null = null
   onerror: ((event: Event) => void) | null = null
   onmessage: ((event: MessageEvent) => void) | null = null
   onopen: (() => void) | null = null
-  readonly OPEN = 1
-  readyState: number = MockWebSocket.CONNECTING
+  readonly OPEN = WebSocketReadyState.OPEN
+  readyState: number = WebSocketReadyState.CONNECTING
   removeEventListener: ReturnType<typeof vi.fn>
   send: ReturnType<typeof vi.fn>
   sentMessages: string[] = []