diff --git a/src/lib/validation-error.ts b/src/lib/validation-error.ts index 687aa3b7..facc041b 100644 --- a/src/lib/validation-error.ts +++ b/src/lib/validation-error.ts @@ -14,12 +14,6 @@ * limitations under the License. */ -import { DefinedError } from 'ajv'; - export class ValidationError { - readonly message: string; - - constructor(readonly error: DefinedError) { - this.message = `invalid: ${error.instancePath} | ${error.schemaPath} | ${error.message}`; - } + constructor(public readonly message: string) {} } diff --git a/src/lib/workflow-validator.ts b/src/lib/workflow-validator.ts index 37938035..6214822e 100644 --- a/src/lib/workflow-validator.ts +++ b/src/lib/workflow-validator.ts @@ -14,14 +14,16 @@ * limitations under the License. */ -import { ValidateFunction, DefinedError } from 'ajv'; +import { ValidateFunction } from 'ajv'; import { Specification } from './definitions'; import { validators } from './validators'; import { ValidationError } from './validation-error'; +import { schemaVersion } from '../../package.json'; + export class WorkflowValidator { /** The validation errors after running validate(), if any */ - readonly errors: ValidationError[] | never[] = []; + readonly errors: ValidationError[] = []; /** Whether the workflow is valid or not */ readonly isValid: boolean; @@ -32,9 +34,20 @@ export class WorkflowValidator { */ constructor(private workflow: Specification.Workflow) { const validateFn = validators.get('Workflow') as ValidateFunction; - this.isValid = validateFn(this.workflow); + validateFn(this.workflow); if (validateFn.errors) { - this.errors = validateFn.errors.map((error) => new ValidationError(error as DefinedError)); + this.errors = validateFn.errors.map((error) => { + const message = `invalid: ${error.instancePath} | ${error.schemaPath} | ${error.message}`; + return new ValidationError(message); + }); + } + + const specVersion = workflow.specVersion; + if (schemaVersion !== specVersion) { + const message = `provided workflow.specVersion value '${specVersion}' can not be different from the SDK supported version '${schemaVersion}'`; + this.errors.push(new ValidationError(message)); } + + this.isValid = this.errors.length === 0; } } diff --git a/tests/lib/workflow-validator.spec.ts b/tests/lib/workflow-validator.spec.ts index 396897ff..e9e6cc62 100644 --- a/tests/lib/workflow-validator.spec.ts +++ b/tests/lib/workflow-validator.spec.ts @@ -17,48 +17,62 @@ import { ValidationError, WorkflowValidator } from '../../src'; import { Workflow } from '../../src/lib/definitions/workflow'; -describe('workflow-validator', () => { +const validWorkflow = { + id: 'helloworld', + version: '1.0', + specVersion: '0.7', + name: 'Hello World Workflow', + description: 'Inject Hello World', + start: 'Hello State', + states: [ + { + name: 'Hello State', + type: 'inject', + data: { + result: 'Hello World!', + }, + end: true, + }, + ], +}; + +describe('workflow-validator, invalid state', () => { it('should return errors instance of ValidationError if the workflow provided is not valid', () => { // @ts-ignore - const workflow = { - id: 'helloworld', - name: 'Hello World Workflow', - version: '1.0', - specVersion: '0.7', - description: 'Inject Hello World', - start: 'Hello State', - states: [], - } as Workflow; + const workflowWithEmptyStates = Object.assign({ ...validWorkflow }, { states: [] }) as Workflow; - const workflowValidator = new WorkflowValidator(workflow); - expect(workflowValidator.isValid).toBeFalsy('Expected isValid to be false'); - expect(workflowValidator.errors.length).toBe(1); - expect(workflowValidator.errors[0].constructor === ValidationError).toBeTruthy( - 'Expected errors to be instance of ValidationError' - ); + const workflowValidator = new WorkflowValidator(workflowWithEmptyStates); + + const numErrors = 1; + expectInvalidWorkflow(workflowValidator, numErrors); expect(workflowValidator.errors[0].message).toMatch('states'); }); + it('should check if specVersion match the supported sdk version', () => { + // @ts-ignore + const workflowWithInvalidSpecVersion = Object.assign({ ...validWorkflow }, { specVersion: '0.1' }) as Workflow; + + const workflowValidator = new WorkflowValidator(workflowWithInvalidSpecVersion); + + const numErrors = 1; + expectInvalidWorkflow(workflowValidator, numErrors); + + expect(workflowValidator.errors[0].message).toMatch('specVersion'); + }); + + function expectInvalidWorkflow(workflowValidator: WorkflowValidator, numErrors: number) { + expect(workflowValidator.isValid).toBeFalsy('Expected isValid to be false'); + expect(workflowValidator.errors.length).toBe(numErrors); + workflowValidator.errors.forEach((error) => { + expect(error.constructor === ValidationError).toBeTruthy('Expected errors to be instance of ValidationError'); + }); + } +}); + +describe('workflow-validator, valid state', () => { it('should have no errors if the workflow is valid', () => { // @ts-ignore - const workflow = { - id: 'helloworld', - version: '1.0', - specVersion: '0.7', - name: 'Hello World Workflow', - description: 'Inject Hello World', - start: 'Hello State', - states: [ - { - name: 'Hello State', - type: 'inject', - data: { - result: 'Hello World!', - }, - end: true, - }, - ], - } as Workflow; + const workflow = validWorkflow as Workflow; const workflowValidator = new WorkflowValidator(workflow); expect(workflowValidator.errors.length).toBe(0);