diff --git a/README.md b/README.md index f8d10bb..ea757df 100644 --- a/README.md +++ b/README.md @@ -48,6 +48,10 @@ JavaScript validation example (using [tv4 library](https://github.com/geraintluf var postSchema = apidocs.getSchema('item'); var valid = tv4.validate(myPost, postSchema); +Some of our schemas provide user-friendly error messages. To enable them, load the custom error reporter: + + apidocs.enableCustomErrors(tv4); + Blueprints ---------- diff --git a/index.coffee b/index.coffee index 9b8d835..d5d1ef6 100644 --- a/index.coffee +++ b/index.coffee @@ -1,11 +1,7 @@ - yaml = require 'js-yaml' path = require 'path' fs = require 'fs' -path = require 'path' -fs = require 'fs' - schemaPath = './schema' exports.listSchemas = () -> @@ -25,3 +21,12 @@ exports.getExamples = (name) -> filepath = path.join __dirname, './examples', name+'.yml' content = fs.readFileSync filepath, { encoding: 'utf-8' } return yaml.safeLoad content + +exports.enableCustomErrors = (validator) -> + unless typeof validator.setErrorReporter is 'function' + throw 'Your validator doesn\'t support custom error messages' + validator.setErrorReporter (error, data, schema) -> + return error.message unless schema.messages + lastSchemaPath = error.schemaPath.split('/').pop() + return error.message unless schema.messages[lastSchemaPath] + schema.messages[lastSchemaPath] diff --git a/schemata/base.yaml b/schemata/base.yaml index 5d109f2..143ee4a 100644 --- a/schemata/base.yaml +++ b/schemata/base.yaml @@ -9,31 +9,43 @@ definitions: pattern: "^[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}$" example: 01234567-89ab-cdef-0123-456789abcdef type: string + messages: + pattern: 'Must be a properly-formed UUID' url: description: Unique Resource Locator format: uri example: http://thegrid.io type: string + messages: + format: 'Must be a properly-formed URL' email: description: Email address format: email example: 'info@thegrid.io' type: string + messages: + format: 'Must be a properly-formed email' hostname: description: Hostname format: hostname example: 'blog.thegrid.io' type: string + messages: + format: 'Must be a properly-formed hostname' hexcolor: description: "#RGB color" format: rgbhexcolor pattern: "^#([a-fA-F0-9]{6}|[a-fA-F0-9]{3})$" example: "#aa33cc" type: string + messages: + pattern: 'Must be a RGB hex string' site: type: string example: "the-domains/the-grid" pattern: "^[a-z0-9-_\\.]+\/[a-z0-9-_\\.]+$" + messages: + pattern: 'Must be a valid GitHub repository name' sites: type: array description: Collection of websites associated with the resource diff --git a/spec/custom-errors.coffee b/spec/custom-errors.coffee new file mode 100644 index 0000000..18b4901 --- /dev/null +++ b/spec/custom-errors.coffee @@ -0,0 +1,33 @@ +tv4 = require 'tv4' +tv4Formats = require 'tv4-formats' +lib = require '../index' +chai = require 'chai' if not chai + +describe 'Custom errors', -> + schemas = {} + validator = null + before -> + validator = tv4.freshApi() + validator.addFormat tv4Formats + lib.enableCustomErrors validator + lib.listSchemas().forEach (schemaName) -> + schema = lib.getSchema schemaName + validator.addSchema schema.id, schema + schemas[schemaName] = schema + after -> + validator.dropSchemas() + validator.reset() + + describe 'invalid repo name', -> + it 'should produce a custom error', (done) -> + baseSchema = schemas['base'] + chai.expect(baseSchema.definitions.site.messages).to.be.an 'object' + chai.expect(baseSchema.definitions.site.messages.pattern).to.exist + result = validator.validateMultiple + name: 'The Grid' + repo: 'foo' + path: '/foo' + , 'site.json' + chai.expect(result.valid).to.equal false + chai.expect(result.errors[0].message).to.equal baseSchema.definitions.site.messages.pattern + done() diff --git a/spec/schemas.coffee b/spec/schemas.coffee index 1e00210..2828dd8 100644 --- a/spec/schemas.coffee +++ b/spec/schemas.coffee @@ -1,4 +1,3 @@ - tv4 = require 'tv4' tv4Formats = require 'tv4-formats' chai = require 'chai' if not chai @@ -9,15 +8,16 @@ lib = require '../index' describe 'Schemas', -> schemas = [] + validator = tv4.freshApi() before -> - tv4.addFormat tv4Formats + validator.addFormat tv4Formats after -> - tv4.reset() - tv4.dropSchemas() + validator.reset() + validator.dropSchemas() lib.listSchemas().forEach (schemaName) -> schema = lib.getSchema schemaName - tv4.addSchema schema.id, schema + validator.addSchema schema.id, schema schemas.push schema schemas.forEach (schema) -> @@ -31,16 +31,16 @@ describe 'Schemas', -> cases.forEach (testcase) -> describe "#{testcase._name}", -> - tv4.addSchema schema.id, schema + validator.addSchema schema.id, schema if testcase._valid it "should be valid", -> - results = tv4.validateMultiple testcase._data, schema.id + results = validator.validateMultiple testcase._data, schema.id chai.expect(results.errors).to.eql [] chai.expect(results.missing).to.eql [] chai.expect(results.valid).to.equal true else it "should be invalid", -> - results = tv4.validateMultiple testcase._data, schema.id + results = validator.validateMultiple testcase._data, schema.id chai.expect(results.errors).to.not.eql [] chai.expect(results.missing).to.eql [] chai.expect(results.valid).to.equal false diff --git a/spec/validate-schemas.coffee b/spec/validate-schemas.coffee index dbd9afe..86bb2c6 100644 --- a/spec/validate-schemas.coffee +++ b/spec/validate-schemas.coffee @@ -15,21 +15,22 @@ loadSchema = (filepath) -> describe 'Schema meta validation', -> schemas = fs.readdirSync path.join __dirname, schemaPath schemaNames = [] + validator = tv4.freshApi() before -> metaSchema = loadSchema path.join __dirname, 'json-schema.json' - tv4.addSchema 'http://json-schema.org/draft-04/schema', metaSchema + validator.addSchema 'http://json-schema.org/draft-04/schema', metaSchema after -> - tv4.reset() - tv4.dropSchemas() + validator.reset() + validator.dropSchemas() schemas.forEach (schemaFile) -> schema = getSchema schemaFile - tv4.addSchema schema.id, schema + validator.addSchema schema.id, schema schemaNames.push schema schemaNames.forEach (schema) -> describe "#{schema.id} (#{schema.title or schema.description})", -> it 'should validate against JSON meta schema', -> - result = tv4.validateMultiple schema, 'http://json-schema.org/draft-04/schema' + result = validator.validateMultiple schema, 'http://json-schema.org/draft-04/schema' chai.expect(result.missing).to.eql [] chai.expect(result.errors).to.eql [] chai.expect(result.valid).to.equal true