From 6dec94dc6885944f18b566b6d26d8c0b49271f85 Mon Sep 17 00:00:00 2001 From: kazuya kawaguchi Date: Tue, 8 Dec 2015 01:43:48 +0900 Subject: [PATCH 01/11] release v2.0.0-alpha.6 --- CHANGELOG.md | 18 ++++++++++++++++++ README.md | 2 +- dist/vue-validator.common.js | 2 +- dist/vue-validator.js | 2 +- dist/vue-validator.min.js | 2 +- package.json | 2 +- 6 files changed, 23 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5d98378..2751d1a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,21 @@ + +# [2.0.0-alpha.6](https://github.com/vuejs/vue-validator/compare/v2.0.0-alpha.6...v2.0.0-alpha.6) (2015-12-07) + + +### Performances + +* **bundle**: more compact the vue-validator + about 20% smaller build with rollupjs. + + - before + - vue-validator.min.js 11701 + - vue-validator.js 26180 + - after + - vue-validator.min.js 9309 + - vue-validator.js 20713 + + + # [2.0.0-alpha.5](https://github.com/vuejs/vue-validator/compare/v2.0.0-alpha.4...v2.0.0-alpha.5) (2015-11-24) diff --git a/README.md b/README.md index b9ea95b..55b48b9 100644 --- a/README.md +++ b/README.md @@ -40,7 +40,7 @@ You don't need to do this when using the standalone build because it installs it ## CDN jsdelivr ```html - + ``` diff --git a/dist/vue-validator.common.js b/dist/vue-validator.common.js index 3540442..cee31c5 100644 --- a/dist/vue-validator.common.js +++ b/dist/vue-validator.common.js @@ -1,5 +1,5 @@ /*! - * vue-validator v2.0.0-alpha.5 + * vue-validator v2.0.0-alpha.6 * (c) 2015 kazuya kawaguchi * Released under the MIT License. */ diff --git a/dist/vue-validator.js b/dist/vue-validator.js index ee1bbe3..4f0e72d 100644 --- a/dist/vue-validator.js +++ b/dist/vue-validator.js @@ -1,5 +1,5 @@ /*! - * vue-validator v2.0.0-alpha.5 + * vue-validator v2.0.0-alpha.6 * (c) 2015 kazuya kawaguchi * Released under the MIT License. */ diff --git a/dist/vue-validator.min.js b/dist/vue-validator.min.js index 3dff9ae..7207075 100644 --- a/dist/vue-validator.min.js +++ b/dist/vue-validator.min.js @@ -1,5 +1,5 @@ /*! - * vue-validator v2.0.0-alpha.5 + * vue-validator v2.0.0-alpha.6 * (c) 2015 kazuya kawaguchi * Released under the MIT License. */ diff --git a/package.json b/package.json index 6cf0691..06977a3 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "vue-validator", "description": "Validator component for Vue.js", - "version": "2.0.0-alpha.5", + "version": "2.0.0-alpha.6", "author": { "name": "kazuya kawaguchi", "email": "kawakazu80@gmail.com" From e71064aef8e774e83bde7bfec363d33ee1910664 Mon Sep 17 00:00:00 2001 From: kazuya kawaguchi Date: Tue, 8 Dec 2015 01:43:48 +0900 Subject: [PATCH 02/11] chore(null): null commit From 89487f761a0df8aa22da7a7901e3265c316e031f Mon Sep 17 00:00:00 2001 From: kazuya kawaguchi Date: Wed, 9 Dec 2015 20:31:36 +0900 Subject: [PATCH 03/11] chore(git): add ignore file --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index ef3312f..d311984 100644 --- a/.gitignore +++ b/.gitignore @@ -3,5 +3,6 @@ coverage node_modules .DS_Store *.log +*.gz *.swp *~ From c912ff386d7e9978d481723824904a0b0e1e8941 Mon Sep 17 00:00:00 2001 From: kazuya kawaguchi Date: Wed, 9 Dec 2015 21:38:49 +0900 Subject: [PATCH 04/11] refactor(e2e): update e2e test --- config/webpack.e2e.conf.js | 26 ++++-- package.json | 5 +- test/e2e/.babelrc | 4 + test/e2e/helper.js | 24 ------ test/e2e/index.html | 113 ++++++++++++++++++++++++++ test/e2e/index.js | 22 +++++ test/e2e/registration.html | 111 ------------------------- test/e2e/{registration.js => test.js} | 52 +++++------- 8 files changed, 183 insertions(+), 174 deletions(-) create mode 100644 test/e2e/.babelrc delete mode 100644 test/e2e/helper.js create mode 100644 test/e2e/index.html create mode 100644 test/e2e/index.js delete mode 100644 test/e2e/registration.html rename test/e2e/{registration.js => test.js} (86%) diff --git a/config/webpack.e2e.conf.js b/config/webpack.e2e.conf.js index 4c5cf4c..3022f5d 100644 --- a/config/webpack.e2e.conf.js +++ b/config/webpack.e2e.conf.js @@ -1,17 +1,29 @@ +var webpack = require('webpack') + module.exports = { - entry: { - app: ['webpack/hot/dev-server', './test/e2e/index.js'] - }, + entry: './test/e2e/index.js', output: { path: './test/e2e', - filename: 'index.build.js' + filename: 'e2e.js' }, module: { loaders: [{ test: /\.js$/, - exclude: /node_modules/, - loader: 'babel' + exclude: /node_modules|vue\/dist/, + loader: 'babel', + query: { + presets: ['es2015'] + } }] }, - devtool: 'inline-source-map' + devtool: 'source-map', + devServer: { + contentBase: './test/e2e', + port: 8080, + hot: true, + inline: true + }, + plugins: [ + new webpack.HotModuleReplacementPlugin() + ] } diff --git a/package.json b/package.json index 06977a3..ddbb586 100644 --- a/package.json +++ b/package.json @@ -18,13 +18,14 @@ "babel-core": "^6.2.1", "babel-loader": "^6.2.0", "babel-plugin-espower": "^2.0.0", + "babel-plugin-transform-es2015-modules-commonjs": "^6.3.16", "babel-preset-es2015": "^6.1.18", "babel-preset-es2015-rollup": "^1.0.0", "commander": "^2.9.0", "cz-conventional-changelog": "^1.1.4", "eslint": "^1.10.2", "eslint-loader": "^1.1.1", - "espower-babel": "^3.3.0", + "espower-babel": "^4.0.0", "istanbul-instrumenter-loader": "^0.1.3", "json-loader": "^0.5.4", "karma": "^0.13.9", @@ -83,7 +84,7 @@ "coveralls": "VUE_VALIDATOR_TYPE=coveralls karma start config/karma.conf.js", "dev": "webpack-dev-server --quite --config config/webpack.dev.conf.js --host 0.0.0.0", "dev-test": "webpack-dev-server --quiet --config config/webpack.test.conf.js --host 0.0.0.0", - "e2e": "webpack-dev-server --quiet -h --config config/webpack.e2e.conf.js --content-base test/e2e & mocha -t 20000 --compilers js:espower-babel/guess test/e2e/test.js && kill $! || (kill $! && exit 1)", + "e2e": "webpack-dev-server --quiet --config config/webpack.e2e.conf.js & mocha -t 20000 --compilers js:espower-babel/guess test/e2e/test.js && kill $! || (kill $! && exit 1)", "ie": "VUE_VALIDATOR_TYPE=sauce SAUCE=batch2 karma start config/karma.conf.js", "lint": "eslint src test/specs", "mobile": "VUE_VALIDATOR_TYPE=sauce SAUCE=batch3 karma start config/karma.conf.js", diff --git a/test/e2e/.babelrc b/test/e2e/.babelrc new file mode 100644 index 0000000..6f20dd0 --- /dev/null +++ b/test/e2e/.babelrc @@ -0,0 +1,4 @@ +{ + "presets": ["es2015"], + "plugins": ["transform-es2015-modules-commonjs"] +} diff --git a/test/e2e/helper.js b/test/e2e/helper.js deleted file mode 100644 index a44907e..0000000 --- a/test/e2e/helper.js +++ /dev/null @@ -1,24 +0,0 @@ -/** - * Import(s) - */ - -var pathResolve = require('path').resolve; -var urlFormat = require('url').format; - - -/** - * Exports(s) - */ - -module.exports = { - resolve: resolve -} - - -function resolve (path) { - return urlFormat({ - protocol: 'file', - slashes: true, - pathname: pathResolve(__dirname, path) - }) -} diff --git a/test/e2e/index.html b/test/e2e/index.html new file mode 100644 index 0000000..51a2071 --- /dev/null +++ b/test/e2e/index.html @@ -0,0 +1,113 @@ + + + + registration + + + + + + + +
+ +
+
+ +
+ + + + {{ $validation.username.valid ? '(success)' : '(error)' }} + +
+
+
+ +
+ + + + {{ $validation.email.valid ? '(success)' : '(error)' }} + +
+
+
+ +
+ + + + {{ $validation.confirmEmail.valid ? '(success)' : '(error)' }} + +
+
+
+ +
+ + + + {{ $validation.password.valid ? '(success)' : '(error)' }} + +
+
+
+
+ +
+
+
+
+
+ + + diff --git a/test/e2e/index.js b/test/e2e/index.js new file mode 100644 index 0000000..c870173 --- /dev/null +++ b/test/e2e/index.js @@ -0,0 +1,22 @@ +import Vue from 'vue' +import plugin from '../../src/index' + +Vue.use(plugin) + +// register custom validator +Vue.validator('email', (val) => { + return /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/.test(val) +}) + +Vue.validator('same', (val, prop) => { + return val == this.$get(prop) +}) + +new Vue({ + data: { + username: '', + email: '', + confirmEmail: '', + password: '' + } +}).$mount('#registration') diff --git a/test/e2e/registration.html b/test/e2e/registration.html deleted file mode 100644 index 5cafd53..0000000 --- a/test/e2e/registration.html +++ /dev/null @@ -1,111 +0,0 @@ - - - - registration - - - - - - - - - -
-
-
- -
- - - -
-
-
- -
- - - -
-
-
- -
- - - -
-
-
- -
- - - -
-
-
-
- -
-
-
-
- - - diff --git a/test/e2e/registration.js b/test/e2e/test.js similarity index 86% rename from test/e2e/registration.js rename to test/e2e/test.js index e3afa58..c20524d 100644 --- a/test/e2e/registration.js +++ b/test/e2e/test.js @@ -1,46 +1,38 @@ -/** - * Import(s) - */ +import assert from 'power-assert' +import Nightmare from 'nightmare' +const url = 'http://localhost:' + (process.env.PORT || 8080) -var Nightmare = require('nightmare') -var assert = require('power-assert') -var resolve = require('./helper').resolve +describe('registration', () => { -/** - * Test(s) - */ - -describe('registration', function () { - - var expectOK = function (ret) { + let expectOK = (ret) => { assert(ret) } - var expectTextError = function (text) { + let expectTextError = (text) => { assert(text === '(error)') } - var expectTextSuccess = function (text) { + let expectTextSuccess = (text) => { assert(text === '(success)') } - var getUsernameStatus = function () { + let getUsernameStatus = () => { return document.querySelector('#inputUsernameStatus').innerText } - var getEmailStatus = function () { + let getEmailStatus = () => { return document.querySelector('#inputEmailStatus').innerText } - var getConfirmEmailStatus = function () { + let getConfirmEmailStatus = () => { return document.querySelector('#inputConfirmEmailStatus').innerText } - var getPasswordStatus = function () { + let getPasswordStatus = () => { return document.querySelector('#inputPasswordStatus').innerText } describe('first loaded page', function () { this.timeout(20000) - it('should be invalid', function (done) { + it('should be invalid', (done) => { new Nightmare() - .goto(resolve('./registration.html')) + .goto(url) .exists('#username .has-error', expectOK) .exists('#inputUsernameIcon .glyphicon-remove', expectOK) .evaluate(getUsernameStatus, expectTextError) @@ -62,9 +54,9 @@ describe('registration', function () { describe('input valid username', function () { this.timeout(20000) - it('should be valid', function (done) { + it('should be valid', (done) => { new Nightmare() - .goto(resolve('./registration.html')) + .goto(url) .type('#inputUsername', 'kazupon') .wait('#inputUsername') .exists('#username .has-success', expectOK) // success @@ -88,9 +80,9 @@ describe('registration', function () { describe('input valid email', function () { this.timeout(20000) - it('should be valid', function (done) { + it('should be valid', (done) => { new Nightmare() - .goto(resolve('./registration.html')) + .goto(url) .type('#inputEmail', 'foo@domain.com') .wait('#inputEmail') .exists('#username .has-error', expectOK) @@ -114,9 +106,9 @@ describe('registration', function () { describe('input valid confirm email', function () { this.timeout(20000) - it('should be valid', function (done) { + it('should be valid', (done) => { new Nightmare() - .goto(resolve('./registration.html')) + .goto(url) .type('#inputEmail', 'foo@domain.com') .wait('#inputEmail') .type('#inputConfirmEmail', 'foo@domain.com') @@ -142,7 +134,7 @@ describe('registration', function () { describe('input valid password', function () { this.timeout(20000) - it('should be valid', function (done) { + it('should be valid', (done) => { new Nightmare() .goto(resolve('./registration.html')) .type('#inputPassword', 'xxxxxxxxx') @@ -168,9 +160,9 @@ describe('registration', function () { describe('input valid fileds', function () { this.timeout(20000) - it('join button should be enabled', function (done) { + it('join button should be enabled', (done) => { new Nightmare() - .goto(resolve('./registration.html')) + .goto(url) .type('#inputUsername', 'kazupon') .wait('#inputUsername') .type('#inputEmail', 'foo@domain.com') From ad30a54b7391bfc44f55782d59893c129e4a7209 Mon Sep 17 00:00:00 2001 From: kazuya kawaguchi Date: Wed, 9 Dec 2015 21:40:44 +0900 Subject: [PATCH 05/11] style(lint): update linting --- config/karma.conf.js | 2 +- config/webpack.test.conf.js | 2 +- package.json | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/config/karma.conf.js b/config/karma.conf.js index 08ab418..624f8ab 100644 --- a/config/karma.conf.js +++ b/config/karma.conf.js @@ -29,7 +29,7 @@ module.exports = function (config) { devtool: 'source-map', module: { noParse: [ - /node_modules\/sinon\//, + /node_modules\/sinon\// ], loaders: [{ test: /\.js$/, diff --git a/config/webpack.test.conf.js b/config/webpack.test.conf.js index 2017d73..af1e301 100644 --- a/config/webpack.test.conf.js +++ b/config/webpack.test.conf.js @@ -10,7 +10,7 @@ module.exports = { devtool: 'source-map', module: { noParse: [ - /node_modules\/sinon\//, + /node_modules\/sinon\// ], preLoaders: [{ test: /\.js$/, diff --git a/package.json b/package.json index ddbb586..c11cb75 100644 --- a/package.json +++ b/package.json @@ -86,7 +86,7 @@ "dev-test": "webpack-dev-server --quiet --config config/webpack.test.conf.js --host 0.0.0.0", "e2e": "webpack-dev-server --quiet --config config/webpack.e2e.conf.js & mocha -t 20000 --compilers js:espower-babel/guess test/e2e/test.js && kill $! || (kill $! && exit 1)", "ie": "VUE_VALIDATOR_TYPE=sauce SAUCE=batch2 karma start config/karma.conf.js", - "lint": "eslint src test/specs", + "lint": "eslint src config test/specs", "mobile": "VUE_VALIDATOR_TYPE=sauce SAUCE=batch3 karma start config/karma.conf.js", "sauce": "npm run coolkids && npm run ie && npm run mobile", "test": "npm run ci", From 8733323b95ae7c0954d5677594a6de95ea2ac5e0 Mon Sep 17 00:00:00 2001 From: kazuya kawaguchi Date: Fri, 11 Dec 2015 00:55:08 +0900 Subject: [PATCH 06/11] refactor(syntax): change v-validate syntax BREAKING CHANGE: v-validate syntax has been changed modifire style to expression style. --- src/directives/validate.js | 7 +- src/validation.js | 40 ++--- test/specs/custom.js | 2 +- test/specs/directives/validate.js | 6 +- test/specs/dirty.js | 4 +- test/specs/event.js | 4 +- test/specs/group.js | 10 +- test/specs/invalid.js | 4 +- test/specs/messages.js | 14 +- test/specs/modified.js | 4 +- test/specs/multiple.js | 4 +- test/specs/pristine.js | 4 +- test/specs/syntax.js | 269 +++++++++++++----------------- test/specs/touched.js | 4 +- test/specs/untouched.js | 4 +- test/specs/valid.js | 4 +- 16 files changed, 164 insertions(+), 220 deletions(-) diff --git a/src/directives/validate.js b/src/directives/validate.js index 69bdfe8..4d6caa5 100644 --- a/src/directives/validate.js +++ b/src/directives/validate.js @@ -37,8 +37,6 @@ export default function (Vue) { if (_.isPlainObject(value)) { this.handleObject(value) - } else { - this.handleSingle(value) } this.validator.validate(this.validation) @@ -53,10 +51,11 @@ export default function (Vue) { each(value, (val, key) => { if (_.isPlainObject(val)) { if ('rule' in val) { - this.validation.updateValidate(key, val.rule, ('message' in val ? val.message : null)) + let msg = 'message' in val ? val.message : null + this.validation.setValidation(key, val.rule, msg) } } else { - this.validation.updateValidate(key, val) + this.validation.setValidation(key, val) } }, this) }, diff --git a/src/validation.js b/src/validation.js index 147b69b..8ba1a06 100644 --- a/src/validation.js +++ b/src/validation.js @@ -15,35 +15,25 @@ export default class Validation { this.touched = false this.dirty = false this.modified = false - this.validates = this._buildValidates(dir) + this.validators = Object.create(null) } - _buildValidates (dir, arg = null) { + setValidation (name, arg, msg, fn) { const resolveAsset = util.Vue.util.resolveAsset - const camelize = util.Vue.util.camelize - let ret = Object.create(null) - let validates = dir.modifiers - - for (let validate in validates) { - let fn = resolveAsset(dir.vm.$options, 'validators', camelize(validate)) - if (fn) { - ret[validate] = { arg: arg, fn: fn } - } + let validator = this.validators[name] + if (!validator) { + validator = this.validators[name] = {} + validator.fn = resolveAsset(this.dir.vm.$options, 'validators', name) + } + + validator.arg = arg + if (msg) { + validator.msg = msg } - return ret - } - - updateValidate (name, arg, msg, fn) { - if (this.validates[name]) { - this.validates[name].arg = arg - if (msg) { - this.validates[name].msg = msg - } - if (fn) { - this.validates[name].fn = fn - } + if (fn) { + validator.fn = fn } } @@ -72,8 +62,8 @@ export default class Validation { let messages = Object.create(null) let valid = true - each(this.validates, (descriptor, name) => { - let res = descriptor.fn(this.el.value, descriptor.arg) + each(this.validators, (descriptor, name) => { + let res = descriptor.fn.call(this.dir.vm, this.el.value, descriptor.arg) if (!res) { valid = false let msg = descriptor.msg diff --git a/test/specs/custom.js b/test/specs/custom.js index 60a63e0..04565df 100644 --- a/test/specs/custom.js +++ b/test/specs/custom.js @@ -20,7 +20,7 @@ describe('custom', () => { el.innerHTML = '' + '
' + - '' + + '' + '
' + '
' vm = new Vue({ diff --git a/test/specs/directives/validate.js b/test/specs/directives/validate.js index 61b4c1b..f9d9678 100644 --- a/test/specs/directives/validate.js +++ b/test/specs/directives/validate.js @@ -16,7 +16,7 @@ describe('validate directive', () => { el: el, template: '' + '
' + - '' + + '' + '
' + '
' }) @@ -46,7 +46,7 @@ describe('validate directive', () => { }, template: '' + '
' + - '' + + '' + '
' + '
' }) @@ -123,7 +123,7 @@ describe('validate directive', () => { }, template: '' + '
' + - '' + + '' + '
' + '
' }) diff --git a/test/specs/dirty.js b/test/specs/dirty.js index a1a96f8..a5e6bfa 100644 --- a/test/specs/dirty.js +++ b/test/specs/dirty.js @@ -11,8 +11,8 @@ describe('dirty', () => { el.innerHTML = '' + '
' + - '' + - '' + + '' + + '' + '
' + '
' vm = new Vue({ diff --git a/test/specs/event.js b/test/specs/event.js index ba76654..fad2e23 100644 --- a/test/specs/event.js +++ b/test/specs/event.js @@ -15,7 +15,7 @@ describe('event', () => { it('should be occured event', (done) => { el.innerHTML = '' + - '' + + '' + '' vm = new Vue({ el: el, @@ -38,7 +38,7 @@ describe('event', () => { it('should be occured event', (done) => { el.innerHTML = '' + - '' + + '' + '' vm = new Vue({ el: el, diff --git a/test/specs/group.js b/test/specs/group.js index bdd6a92..39e5b06 100644 --- a/test/specs/group.js +++ b/test/specs/group.js @@ -9,11 +9,11 @@ describe('group', () => { beforeEach((done) => { el = document.createElement('div') el.innerHTML = - '' + - '' + - '' + - '' + - '' + + '' + + '' + + '' + + '' + + '' + '' vm = new Vue({ el: el diff --git a/test/specs/invalid.js b/test/specs/invalid.js index 7f45f4d..e9f5b28 100644 --- a/test/specs/invalid.js +++ b/test/specs/invalid.js @@ -11,8 +11,8 @@ describe('invalid', () => { el.innerHTML = '' + '
' + - '' + - '' + + '' + + '' + '
' + '
' vm = new Vue({ diff --git a/test/specs/messages.js b/test/specs/messages.js index 46247fb..44b6f60 100644 --- a/test/specs/messages.js +++ b/test/specs/messages.js @@ -9,13 +9,13 @@ describe('messages', () => { beforeEach((done) => { el = document.createElement('div') el.innerHTML = - '' + - '' + - '' + - '' + - '' + - '' + - '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + '
  • ' + '

    {{$key}}:{{val}}

    ' + '
' + diff --git a/test/specs/modified.js b/test/specs/modified.js index 65114f8..fc2b788 100644 --- a/test/specs/modified.js +++ b/test/specs/modified.js @@ -11,8 +11,8 @@ describe('modified', () => { el.innerHTML = '' + '
' + - '' + - '' + + '' + + '' + '
' + '
' vm = new Vue({ diff --git a/test/specs/multiple.js b/test/specs/multiple.js index 22ec381..928497a 100644 --- a/test/specs/multiple.js +++ b/test/specs/multiple.js @@ -10,10 +10,10 @@ describe('multiple', () => { el = document.createElement('div') el.innerHTML = '' + - '' + + '' + '' + '' + - '' + + '' + '' vm = new Vue({ el: el diff --git a/test/specs/pristine.js b/test/specs/pristine.js index fcb89bd..27b197b 100644 --- a/test/specs/pristine.js +++ b/test/specs/pristine.js @@ -11,8 +11,8 @@ describe('pristine', () => { el.innerHTML = '' + '
' + - '' + - '' + + '' + + '' + '
' + '
' vm = new Vue({ diff --git a/test/specs/syntax.js b/test/specs/syntax.js index 9062f0b..3d4b9f0 100644 --- a/test/specs/syntax.js +++ b/test/specs/syntax.js @@ -11,200 +11,155 @@ describe('syntax', () => { }) - describe('simple', () => { - context('static', () => { + context('simple', () => { + beforeEach((done) => { + el.innerHTML = + '' + + '
' + + '' + + '
' + + '
' + vm = new Vue({ + el: el + }) + vm.$nextTick(done) + }) + + it('should be validated', (done) => { + // default + assert(vm.$validator1.field1.minlength === true) + + // change input value + let input = el.getElementsByTagName('input')[0] + input.value = 'foo' + trigger(input, 'input') + vm.$nextTick(() => { + assert(vm.$validator1.field1.minlength === false) + done() + }) + }) + }) + + context('strict', () => { + beforeEach((done) => { + el.innerHTML = + '' + + '
' + + '' + + '
' + + '
' + vm = new Vue({ + el: el + }) + vm.$nextTick(done) + }) + + it('should be validated', (done) => { + // default + assert(vm.$validator1.field1.minlength === false) + assert(vm.$validator1.field1.maxlength === false) + + // change input value + let input = el.getElementsByTagName('input')[0] + input.value = 'h' + trigger(input, 'input') + vm.$nextTick(() => { + assert(vm.$validator1.field1.minlength === true) + assert(vm.$validator1.field1.maxlength === false) + + input.value = 'hi kazupon' + trigger(input, 'input') + vm.$nextTick(() => { + assert(vm.$validator1.field1.minlength === false) + assert(vm.$validator1.field1.maxlength === true) + done() + }) + }) + }) + }) + + context('binding', () => { + context('primitive', () => { beforeEach((done) => { el.innerHTML = '' + '
' + - '' + + '' + '
' + '
' vm = new Vue({ - el: el + el: el, + data: { number: 10 } }) vm.$nextTick(done) }) it('should be validated', (done) => { // default - assert(vm.$validator1.field1.minlength === true) + assert(vm.$validator1.field1.max === false) // change input value let input = el.getElementsByTagName('input')[0] - input.value = 'foo' + input.value = '11' trigger(input, 'input') vm.$nextTick(() => { - assert(vm.$validator1.field1.minlength === false) + assert(vm.$validator1.field1.max === true) done() }) }) }) - context('binding', () => { - context('primitive', () => { - beforeEach((done) => { - el.innerHTML = - '' + - '
' + - '' + - '
' + - '
' - vm = new Vue({ - el: el, - data: { number: 10 } - }) - vm.$nextTick(done) - }) - - it('should be validated', (done) => { - // default - assert(vm.$validator1.field1.max === false) - - // change input value - let input = el.getElementsByTagName('input')[0] - input.value = '11' - trigger(input, 'input') - vm.$nextTick(() => { - assert(vm.$validator1.field1.max === true) - done() - }) - }) - }) - - context('function', () => { - beforeEach((done) => { - el.innerHTML = - '' + - '
' + - '' + - '
' + - '
' - vm = new Vue({ - el: el, - data: { condition: '' }, - methods: { - getMax (condition) { - let ret = 0 - switch (condition) { - case 'condition1': - ret = 5 - break - default: - ret = 10 - break - } - return ret + context('function', () => { + beforeEach((done) => { + el.innerHTML = + '' + + '
' + + '' + + '
' + + '
' + vm = new Vue({ + el: el, + data: { condition: '' }, + methods: { + getMax (condition) { + let ret = 0 + switch (condition) { + case 'condition1': + ret = 5 + break + default: + ret = 10 + break } + return ret } - }) - vm.$nextTick(done) - }) - - it('should be validated', (done) => { - // default - assert(vm.$validator1.field1.max === false) - - // change input value - let input = el.getElementsByTagName('input')[0] - vm.condition = 'condition1' - input.value = '11' - trigger(input, 'input') - vm.$nextTick(() => { - assert(vm.$validator1.field1.max === true) - done() - }) + } }) + vm.$nextTick(done) }) - }) - }) + it('should be validated', (done) => { + // default + assert(vm.$validator1.field1.max === false) - describe('object', () => { - context('static', () => { - context('loose', () => { - beforeEach((done) => { - el.innerHTML = - '' + - '
' + - '' + - '
' + - '
' - vm = new Vue({ - el: el - }) - vm.$nextTick(done) - }) - - it('should be validated', (done) => { - // default - assert(vm.$validator1.field1.min === false) - assert(vm.$validator1.field1.max === false) - - // change input value - let input = el.getElementsByTagName('input')[0] - input.value = '0' - trigger(input, 'input') - vm.$nextTick(() => { - assert(vm.$validator1.field1.min === true) - assert(vm.$validator1.field1.max === false) - - input.value = '6' - trigger(input, 'input') - vm.$nextTick(() => { - assert(vm.$validator1.field1.min === false) - assert(vm.$validator1.field1.max === true) - done() - }) - }) - }) - }) - - context('strict', () => { - beforeEach((done) => { - el.innerHTML = - '' + - '
' + - '' + - '
' + - '
' - vm = new Vue({ - el: el - }) - vm.$nextTick(done) - }) - - it('should be validated', (done) => { - // default - assert(vm.$validator1.field1.minlength === false) - assert(vm.$validator1.field1.maxlength === false) - - // change input value - let input = el.getElementsByTagName('input')[0] - input.value = 'h' - trigger(input, 'input') - vm.$nextTick(() => { - assert(vm.$validator1.field1.minlength === true) - assert(vm.$validator1.field1.maxlength === false) - - input.value = 'hi kazupon' - trigger(input, 'input') - vm.$nextTick(() => { - assert(vm.$validator1.field1.minlength === false) - assert(vm.$validator1.field1.maxlength === true) - done() - }) - }) + // change input value + let input = el.getElementsByTagName('input')[0] + vm.condition = 'condition1' + input.value = '11' + trigger(input, 'input') + vm.$nextTick(() => { + assert(vm.$validator1.field1.max === true) + done() }) }) }) - context('binding', () => { + context('object', () => { beforeEach((done) => { el.innerHTML = '' + '
' + - '' + + '' + '
' + '
' vm = new Vue({ diff --git a/test/specs/touched.js b/test/specs/touched.js index f90461b..c7f03cf 100644 --- a/test/specs/touched.js +++ b/test/specs/touched.js @@ -11,8 +11,8 @@ describe('touched', () => { el.innerHTML = '' + '
' + - '' + - '' + + '' + + '' + '
' + '
' vm = new Vue({ diff --git a/test/specs/untouched.js b/test/specs/untouched.js index a0ea789..646ca55 100644 --- a/test/specs/untouched.js +++ b/test/specs/untouched.js @@ -11,8 +11,8 @@ describe('ununtouched', () => { el.innerHTML = '' + '
' + - '' + - '' + + '' + + '' + '
' + '
' vm = new Vue({ diff --git a/test/specs/valid.js b/test/specs/valid.js index af039be..afc255e 100644 --- a/test/specs/valid.js +++ b/test/specs/valid.js @@ -11,8 +11,8 @@ describe('valid', () => { el.innerHTML = '' + '
' + - '' + - '' + + '' + + '' + '
' + '
' vm = new Vue({ From d126cbc887dd824c2ade9275de589574106e9686 Mon Sep 17 00:00:00 2001 From: kazuya kawaguchi Date: Fri, 11 Dec 2015 01:12:14 +0900 Subject: [PATCH 07/11] feat(syntax): support array syntax on v-validate expression --- src/directives/validate.js | 9 ++++++--- test/specs/syntax.js | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 38 insertions(+), 3 deletions(-) diff --git a/src/directives/validate.js b/src/directives/validate.js index 4d6caa5..c403c86 100644 --- a/src/directives/validate.js +++ b/src/directives/validate.js @@ -37,14 +37,17 @@ export default function (Vue) { if (_.isPlainObject(value)) { this.handleObject(value) + } else if (Array.isArray(value)) { + this.handleArray(value) } this.validator.validate(this.validation) }, - handleSingle (value) { - let validateKey = Object.keys(this.validation.validates)[0] - this.validation.updateValidate(validateKey, value) + handleArray (value) { + each(value, (val) => { + this.validation.setValidation(val) + }, this) }, handleObject (value) { diff --git a/test/specs/syntax.js b/test/specs/syntax.js index 3d4b9f0..5578422 100644 --- a/test/specs/syntax.js +++ b/test/specs/syntax.js @@ -40,6 +40,37 @@ describe('syntax', () => { }) }) + + context('array', () => { + beforeEach((done) => { + el.innerHTML = + '' + + '
' + + '' + + '
' + + '
' + vm = new Vue({ + el: el + }) + vm.$nextTick(done) + }) + + it('should be validated', (done) => { + // default + assert(vm.$validator1.field1.required === true) + + // change input value + let input = el.getElementsByTagName('input')[0] + input.value = 'foo' + trigger(input, 'input') + vm.$nextTick(() => { + assert(vm.$validator1.field1.required === false) + done() + }) + }) + }) + + context('strict', () => { beforeEach((done) => { el.innerHTML = @@ -78,6 +109,7 @@ describe('syntax', () => { }) }) + context('binding', () => { context('primitive', () => { beforeEach((done) => { From d0e436bc1496339429444f637c59f05cfad548fa Mon Sep 17 00:00:00 2001 From: kazuya kawaguchi Date: Fri, 11 Dec 2015 01:47:03 +0900 Subject: [PATCH 08/11] docs(README): change old syntax to new syntax --- README.md | 54 ++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 36 insertions(+), 18 deletions(-) diff --git a/README.md b/README.md index 55b48b9..ccc80df 100644 --- a/README.md +++ b/README.md @@ -58,8 +58,8 @@ We can use `validator` element directive and `v-validate` directive. The followi
- - + +
Required your name. Your comment is too long. @@ -139,40 +139,44 @@ The various top-level properties has been defined in the validation scope, and t - `modified`: if modified field exist even **one** in validate fields, return `true`, else `false`. - `dirty`: if dirty field exist even **one** in validate fields, return `true`, else `false`. - `pristine`: whether **all** fields is pristine, if so, return `true`, else `false`. -- `errors`: if invalid even one exist, return all field error message wrapped with object, else `undefined`. +- `messages`: if invalid even one exist, return all field error message wrapped with object, else `undefined`. # Validator syntax `v-validate` directive syntax the below: ``` - v-validate:field.[validator]+[="primitive literal | object literal | binding"] + v-validate:field="array literal | object literal | binding" ``` ## Literal -### Primitive -The below is example that using literal of string value: +### Array +The below is example that using array literal: ```html - Zip:
+ Zip:
- Invalid format of your zip code. + Required zip code.
``` +Like the `required`, if you don't need to specify the rule, you should use it. + + ### Object The below is example that using object literal: ```html
- ID:
+ ID:
+ Required Your ID. Your ID is too short. Your ID is too long.
@@ -180,6 +184,21 @@ The below is example that using object literal: ``` +You can specify the rule value on the object literal. Like the `required`, you can specify the **dummy rule** value on the literal object. + +And also, you can specify strict object as the below: + +```html + + + ID:
+
+ Your ID is too short. + Your ID is too long. +
+ +``` + ## Binding The below is example that using binding: @@ -198,7 +217,7 @@ new Vue({
- ID:
+ ID:
Your ID is too short. Your ID is too long. @@ -215,9 +234,9 @@ You can grouping validation results. the below example: ```html - username:
- password:
- password (confirm): + username:
+ password:
+ password (confirm):
Required your name.
@@ -232,10 +251,10 @@ You can specify error message that can get the validation scope. ```html - username:
- password:
@@ -270,7 +289,7 @@ new Vue({ ```html
- comment: + comment:
``` @@ -295,7 +314,7 @@ new Vue({ ```html
- address:
+ address:
invalid your email address format.
@@ -308,7 +327,6 @@ new Vue({ # TODO - async validation -- errors properties - validate timing customize with options - local asset registration (`compontents` asset-like) - server-side validation error applying From 9cb9328492ccc56725cb2125b7af974f229dd6ed Mon Sep 17 00:00:00 2001 From: kazuya kawaguchi Date: Fri, 11 Dec 2015 01:51:38 +0900 Subject: [PATCH 09/11] test(e2e): update e2e test template --- test/e2e/index.html | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/e2e/index.html b/test/e2e/index.html index 51a2071..4e9861a 100644 --- a/test/e2e/index.html +++ b/test/e2e/index.html @@ -24,7 +24,7 @@ id="inputUsername" placeholder="Username" aria-describedby="inputUsernameStatus" - v-validate:username.required.maxlength="{ required: true, maxlength: 16 }"> + v-validate:username="{ required: true, maxlength: 16 }">