diff --git a/hello/FOTAJob.spec.ts b/hello/FOTAJob.spec.ts new file mode 100644 index 00000000..5af42034 --- /dev/null +++ b/hello/FOTAJob.spec.ts @@ -0,0 +1,46 @@ +import assert from 'node:assert/strict' +import { describe, it } from 'node:test' +import { validateWithTypeBox } from 'validator/validateWithTypeBox.js' +import { UpgradePath } from './FOTAJob.js' + +const v = validateWithTypeBox(UpgradePath) + +void describe('UpgradePath', () => { + void it('should accept an upgrade path with plain versions', () => + assert.equal( + hasError( + v({ + '2.0.0': 'APP*1e29dfa3*v2.0.1', + '2.0.1': 'APP*cd5412d9*v2.0.2', + }), + ), + false, + )) + + void describe('support semver ranges', () => { + for (const range of [ + '<', // Less than + '<=', // Less than or equal to + '>', // Greater than + '>=', // Greater than or equal to + ]) { + void it(range, () => + assert.equal( + hasError( + v({ + [`${range}2.0.0`]: 'APP*1e29dfa3*v2.0.1', + }), + ), + false, + ), + ) + } + }) + + void describe('reject invalid upgrade paths', () => { + void it('should reject an upgrade path with an invalid version', () => + assert.equal(hasError(v({ foo: 'bar' } as any)), true)) + }) +}) + +const hasError = (result: ReturnType) => 'errors' in result diff --git a/hello/FOTAJob.ts b/hello/FOTAJob.ts index 6109191d..cab940d3 100644 --- a/hello/FOTAJob.ts +++ b/hello/FOTAJob.ts @@ -16,10 +16,14 @@ export enum FOTAJobTarget { } export const UpgradePath = Type.Record( - Type.RegExp(/[0-9]+\.[0-9]+\.[0-9]+/, { - title: 'Version', - description: 'The version the bundle is targeting', - }), + Type.RegExp( + new RegExp(`^(${['<', '<=', '>', '>='].join('|')})?[0-9]+.[0-9]+.[0-9]+$`), + { + title: 'Version', + description: + 'The version the bundle is targeting. Supports ranges (e.g >=1.0.0).', + }, + ), Type.RegExp( /^(APP|MODEM|BOOT|SOFTDEVICE|BOOTLOADER|MDM_FULL)\*[0-9a-zA-Z]{8}\*.*$/, { @@ -27,7 +31,7 @@ export const UpgradePath = Type.Record( description: 'The nRF Cloud firmware bundle ID', }, ), - { minProperties: 1 }, + { minProperties: 1, additionalProperties: false }, ) export const FOTAJob = Type.Object(