diff --git a/README.md b/README.md index 78a06af..af0c02b 100644 --- a/README.md +++ b/README.md @@ -60,17 +60,17 @@ const result = validate(value, validations) #### Presence vs allowNull -| | presence: true | allowNull: false | -| ------------- | ------------------| ---------------- | -| 'Text' | Valid | Valid | -| 123 | Valid | Valid | -| 0 | Valid | Valid | -| ' ' | | Valid | -| '' | | Valid | -| [] | | Valid | -| {} | | Valid | -| null | | | -| undefined | | | +| | presence: true | allowNull: false | +| --------- | -------------- | ---------------- | +| 'Text' | Valid | Valid | +| 123 | Valid | Valid | +| 0 | Valid | Valid | +| ' ' | | Valid | +| '' | | Valid | +| [] | | Valid | +| {} | | Valid | +| null | | | +| undefined | | | @@ -370,6 +370,21 @@ const result = validate(value, validations) ``` +#### Javascript Identifier + + The javascript identifier validator ensures that the input is a valid javascript identifier. Javascript identifiers validator rules can be found [`here`](https://developer.mozilla.org/pt-BR/docs/Glossary/Identifier). + + +```javascript +const value = "1GetTest" +const validations = { javascriptIdentifier: true } +const result = validate(value, validations) +/* { + value: '1GetTest', + errors: [{ invalidJavascriptIdentifier: true }] +} */ +``` + #### URL The URL validator ensures that the input is a valid URL. Validating URLs are pretty tricky but this validator is inspired on a gist that can be found [`here`](https://gist.github.com/dperini/729294). diff --git a/src/checker.js b/src/checker.js index 8e97dba..ee4618c 100644 --- a/src/checker.js +++ b/src/checker.js @@ -158,6 +158,65 @@ class Checker { return this.isValidFormat(value, new RegExp(regex, 'i')) } + static isValidJavascriptIdentifier(value) { + const validName = /^[$A-Z_][0-9A-Z_$]*$/i + const reserved = [ + 'break', + 'case', + 'catch', + 'class', + 'const', + 'continue', + 'debugger', + 'default', + 'delete', + 'do', + 'else', + 'export', + 'extends', + 'finally', + 'for', + 'function', + 'if', + 'import', + 'in', + 'instanceof', + 'new', + 'return', + 'super', + 'switch', + 'this', + 'throw', + 'try', + 'typeof', + 'var', + 'void', + 'while', + 'with', + 'yield', + 'abstract', + 'boolean', + 'byte', + 'char', + 'double', + 'final', + 'float', + 'goto', + 'int', + 'long', + 'native', + 'short', + 'synchronized', + 'throws', + 'transient', + 'true', + 'false', + 'volatile' + ] + + return validName.test(value) && !reserved.includes(String(value)) + } + static isTooShort(value, minimum) { if (!this.isNumber(minimum)) throw Error(`Invalid minimum length. It must be a number.`) diff --git a/src/errorCodes.js b/src/errorCodes.js index 9cb5325..a2380f0 100644 --- a/src/errorCodes.js +++ b/src/errorCodes.js @@ -20,7 +20,8 @@ const codes = { notContains: 'notContains', contains: 'contains', invalidURL: 'invalidURL', - invalidEmail: 'invalidEmail' + invalidEmail: 'invalidEmail', + invalidJavascriptIdentifier: 'invalidJavascriptIdentifier' } module.exports = codes diff --git a/src/suma.js b/src/suma.js index a8f538c..79e8c27 100644 --- a/src/suma.js +++ b/src/suma.js @@ -7,6 +7,7 @@ const validators = { numericality: require('./validators/numericality'), datetime: require('./validators/datetime'), url: require('./validators/url'), + javascriptIdentifier: require('./validators/javascriptIndetifier'), email: require('./validators/email'), contains: require('./validators/contains'), custom: require('./validators/custom'), diff --git a/src/validators/javascriptIndetifier.js b/src/validators/javascriptIndetifier.js new file mode 100644 index 0000000..418822b --- /dev/null +++ b/src/validators/javascriptIndetifier.js @@ -0,0 +1,11 @@ +const checker = require("../checker") +const err = require("../errorCodes") + +function javascriptIndentifier(value) { + if (checker.isEmpty(value)) return { [err.cantBeEmpty]: true } + + const result = checker.isValidJavascriptIdentifier(value) + return result ? null: { [err.invalidJavascriptIdentifier]: true } +} + +module.exports = javascriptIndentifier diff --git a/test/validators/javascriptIndetifier.js b/test/validators/javascriptIndetifier.js new file mode 100644 index 0000000..82257e0 --- /dev/null +++ b/test/validators/javascriptIndetifier.js @@ -0,0 +1,89 @@ +const assert = require("assert") +const { validate, errorCodes } = require("../../src/suma") +const err = errorCodes + +describe("javascriptIdentifier validation", () => { + it('does not allow empty values', () => { + + const samples = [ + {}, + null, + '', + undefined + ] + for (const value of samples) { + // given + const validations = { javascriptIdentifier: true } + // when + const ret = validate(value, validations) + // then + assert.deepStrictEqual(ret, { value: value, errors: [{ [err.cantBeEmpty]: true }] }) + } + }) + + it("does not allow non strings", function () { + + const samples = [ + 3.14, + 192.168, + true, + { key: "i'm a string" } + ] + + for (const value of samples) { + // given + const validations = { javascriptIdentifier: true } + // when + const ret = validate(value, validations) + // then + assert.deepStrictEqual(ret, { value: value, errors: [{ [err.invalidJavascriptIdentifier]: true }] }) + } + + }) + + + it("does not allow 'invalid' javascriptIdentifiers", function () { + + const samples = [ + "http://", + "//", + "//a", + "true", + "false", + "boolean", + "1getTest", + "1124", + "get##", + "%$@" + ] + + for (const value of samples) { + // given + const validations = { javascriptIdentifier: true } + // when + const ret = validate(value, validations) + // then + assert.deepStrictEqual(ret, { value: value, errors: [{ [err.invalidJavascriptIdentifier]: true }] }) + } + + }) + + + it('does allows valid javascriptidentifiers', () => { + + const samples = [ + "getTest", + "getTest23", + "get_Test", + "get_Test$", + ] + for (const value of samples) { + // given + const validations = { javascriptIdentifier: true } + // when + const ret = validate(value, validations) + // then + assert.deepStrictEqual(ret, { value: value, errors: [] }) + } + }) +})