From: Jérôme Benoit Date: Thu, 12 Mar 2026 23:04:47 +0000 (+0100) Subject: test(ocpp): add schema registration coverage tests for OCPP 1.6 and 2.0 X-Git-Tag: ocpp-server@v3.1.0~51 X-Git-Url: https://git.piment-noir.org/?a=commitdiff_plain;h=293588f1f28cb59d67ce3ea1aff16a91ae92ed0a;p=e-mobility-charging-stations-simulator.git test(ocpp): add schema registration coverage tests for OCPP 1.6 and 2.0 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. --- diff --git a/tests/charging-station/ocpp/1.6/OCPP16SchemaValidation.test.ts b/tests/charging-station/ocpp/1.6/OCPP16SchemaValidation.test.ts index ce9b85ef..93aa3af7 100644 --- a/tests/charging-station/ocpp/1.6/OCPP16SchemaValidation.test.ts +++ b/tests/charging-station/ocpp/1.6/OCPP16SchemaValidation.test.ts @@ -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}` + ) + } + }) + }) }) diff --git a/tests/charging-station/ocpp/2.0/OCPP20SchemaValidation.test.ts b/tests/charging-station/ocpp/2.0/OCPP20SchemaValidation.test.ts index f510c75a..59fa9adc 100644 --- a/tests/charging-station/ocpp/2.0/OCPP20SchemaValidation.test.ts +++ b/tests/charging-station/ocpp/2.0/OCPP20SchemaValidation.test.ts @@ -12,11 +12,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 { 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}` + ) + } + }) + }) })