]> Piment Noir Git Repositories - e-mobility-charging-stations-simulator.git/commitdiff
test(ocpp): add schema registration coverage tests for OCPP 1.6 and 2.0
authorJérôme Benoit <jerome.benoit@sap.com>
Thu, 12 Mar 2026 23:04:47 +0000 (00:04 +0100)
committerJérôme Benoit <jerome.benoit@sap.com>
Thu, 12 Mar 2026 23:04:47 +0000 (00:04 +0100)
Verify every command enum value has its request and response schemas
registered in ServiceUtils, and that all referenced schema files exist
on disk. Prevents regressions where a command is implemented but its
schema registration is forgotten.

tests/charging-station/ocpp/1.6/OCPP16SchemaValidation.test.ts
tests/charging-station/ocpp/2.0/OCPP20SchemaValidation.test.ts

index ce9b85ef77e032dddbd9fbca49052522c06eb090..93aa3af785ba024d554050ee2076744d54a75b4a 100644 (file)
@@ -9,11 +9,13 @@
 import _Ajv, { type ValidateFunction } from 'ajv'
 import _ajvFormats from 'ajv-formats'
 import assert from 'node:assert/strict'
-import { readFileSync } from 'node:fs'
+import { existsSync, readFileSync } from 'node:fs'
 import { join } from 'node:path'
 import { afterEach, describe, it } from 'node:test'
 import { fileURLToPath } from 'node:url'
 
+import { OCPP16ServiceUtils } from '../../../../src/charging-station/ocpp/1.6/OCPP16ServiceUtils.js'
+import { OCPP16IncomingRequestCommand, OCPP16RequestCommand } from '../../../../src/types/index.js'
 import { standardCleanup } from '../../../helpers/TestLifecycleHelpers.js'
 
 const AjvConstructor = _Ajv.default
@@ -274,4 +276,53 @@ await describe('OCPP16SchemaValidation', async () => {
       assert.strictEqual(valid, true)
     })
   })
+
+  await describe('schema registration coverage', async () => {
+    await it('should register an incoming request schema for every OCPP16IncomingRequestCommand', () => {
+      const configs = OCPP16ServiceUtils.createIncomingRequestPayloadConfigs()
+      const registered = new Set(configs.map(([cmd]) => cmd))
+      for (const command of Object.values(OCPP16IncomingRequestCommand)) {
+        assert.ok(registered.has(command), `missing incoming request schema for: ${command}`)
+      }
+    })
+
+    await it('should register an incoming response schema for every OCPP16IncomingRequestCommand', () => {
+      const configs = OCPP16ServiceUtils.createIncomingRequestResponsePayloadConfigs()
+      const registered = new Set(configs.map(([cmd]) => cmd))
+      for (const command of Object.values(OCPP16IncomingRequestCommand)) {
+        assert.ok(registered.has(command), `missing incoming response schema for: ${command}`)
+      }
+    })
+
+    await it('should register an outgoing request schema for every OCPP16RequestCommand', () => {
+      const configs = OCPP16ServiceUtils.createRequestPayloadConfigs()
+      const registered = new Set(configs.map(([cmd]) => cmd))
+      for (const command of Object.values(OCPP16RequestCommand)) {
+        assert.ok(registered.has(command), `missing outgoing request schema for: ${command}`)
+      }
+    })
+
+    await it('should register an outgoing response schema for every OCPP16RequestCommand', () => {
+      const configs = OCPP16ServiceUtils.createResponsePayloadConfigs()
+      const registered = new Set(configs.map(([cmd]) => cmd))
+      for (const command of Object.values(OCPP16RequestCommand)) {
+        assert.ok(registered.has(command), `missing outgoing response schema for: ${command}`)
+      }
+    })
+
+    await it('should reference existing schema files for all registered schemas', () => {
+      const allConfigs = [
+        ...OCPP16ServiceUtils.createIncomingRequestPayloadConfigs(),
+        ...OCPP16ServiceUtils.createIncomingRequestResponsePayloadConfigs(),
+        ...OCPP16ServiceUtils.createRequestPayloadConfigs(),
+        ...OCPP16ServiceUtils.createResponsePayloadConfigs(),
+      ]
+      for (const [command, { schemaPath }] of allConfigs) {
+        assert.ok(
+          existsSync(join(SCHEMA_DIR, schemaPath)),
+          `schema file missing for ${command}: ${schemaPath}`
+        )
+      }
+    })
+  })
 })
index f510c75a8c5916be2812096da3cd6b025be21359..59fa9adcd2c23b0a62bcccce7423b46d9cc3e42e 100644 (file)
 import _Ajv, { type ValidateFunction } from 'ajv'
 import _ajvFormats from 'ajv-formats'
 import assert from 'node:assert/strict'
-import { readFileSync } from 'node:fs'
+import { existsSync, readFileSync } from 'node:fs'
 import { join } from 'node:path'
 import { afterEach, describe, it } from 'node:test'
 import { fileURLToPath } from 'node:url'
 
+import { OCPP20ServiceUtils } from '../../../../src/charging-station/ocpp/2.0/OCPP20ServiceUtils.js'
+import { OCPP20IncomingRequestCommand, OCPP20RequestCommand } from '../../../../src/types/index.js'
 import { standardCleanup } from '../../../helpers/TestLifecycleHelpers.js'
 
 const AjvConstructor = _Ajv.default
@@ -204,4 +206,53 @@ await describe('OCPP 2.0 schema validation — negative tests', async () => {
     assert.strictEqual(validate({ requestedMessage: 'Heartbeat' }), true)
     assert.strictEqual(validate({ requestedMessage: 'BootNotification' }), true)
   })
+
+  await describe('schema registration coverage', async () => {
+    await it('should register an incoming request schema for every OCPP20IncomingRequestCommand', () => {
+      const configs = OCPP20ServiceUtils.createIncomingRequestPayloadConfigs()
+      const registered = new Set(configs.map(([cmd]) => cmd))
+      for (const command of Object.values(OCPP20IncomingRequestCommand)) {
+        assert.ok(registered.has(command), `missing incoming request schema for: ${command}`)
+      }
+    })
+
+    await it('should register an incoming response schema for every OCPP20IncomingRequestCommand', () => {
+      const configs = OCPP20ServiceUtils.createIncomingRequestResponsePayloadConfigs()
+      const registered = new Set(configs.map(([cmd]) => cmd))
+      for (const command of Object.values(OCPP20IncomingRequestCommand)) {
+        assert.ok(registered.has(command), `missing incoming response schema for: ${command}`)
+      }
+    })
+
+    await it('should register an outgoing request schema for every OCPP20RequestCommand', () => {
+      const configs = OCPP20ServiceUtils.createRequestPayloadConfigs()
+      const registered = new Set(configs.map(([cmd]) => cmd))
+      for (const command of Object.values(OCPP20RequestCommand)) {
+        assert.ok(registered.has(command), `missing outgoing request schema for: ${command}`)
+      }
+    })
+
+    await it('should register an outgoing response schema for every OCPP20RequestCommand', () => {
+      const configs = OCPP20ServiceUtils.createResponsePayloadConfigs()
+      const registered = new Set(configs.map(([cmd]) => cmd))
+      for (const command of Object.values(OCPP20RequestCommand)) {
+        assert.ok(registered.has(command), `missing outgoing response schema for: ${command}`)
+      }
+    })
+
+    await it('should reference existing schema files for all registered schemas', () => {
+      const allConfigs = [
+        ...OCPP20ServiceUtils.createIncomingRequestPayloadConfigs(),
+        ...OCPP20ServiceUtils.createIncomingRequestResponsePayloadConfigs(),
+        ...OCPP20ServiceUtils.createRequestPayloadConfigs(),
+        ...OCPP20ServiceUtils.createResponsePayloadConfigs(),
+      ]
+      for (const [command, { schemaPath }] of allConfigs) {
+        assert.ok(
+          existsSync(join(SCHEMA_DIR, schemaPath)),
+          `schema file missing for ${command}: ${schemaPath}`
+        )
+      }
+    })
+  })
 })