laravelinput值必须不等于0_【第⼗⼀期】实现Javascript版本
的Lara。。。
对于任何 api 来说,输⼊参数的校验,是⾮常重要的⼀个步骤;很多框架和⼯具也都提供了输⼊参数验证功能;今天,我们来学习其中⼀种,并尝试从零开始,创建⼀个 Javascript 版本的 Laravel 风格参数验证器。
关于 Laravel
laravel/laravel g ithub
是⼀个基于 PHP 实现的 web 框架,它提供了api参数验证功能,其中对于验证规则的组织很简洁:
public function store(Request $request)
{
$validatedData = $request->validate([
'title' => 'required|max:255',
'body' => 'required',
]);
// ...
}
通过上⾯的 php 代码我们看到,对于参数 title,有两个验证规则,它们分别是:
1. required 这代表 title 参数必传,如果没有传递 title 参数,或 title 参数的值为:null、空字符串、空数组、空对象,则验证不会通过。
2. max:255 这代表参数作为字符串、数字或数组,上限必须⼩于或等于255(对于字符串和数组来说,则判定其 length 的值)
以上验证规则,使⽤符号 | 分割,看起来很紧凑。
我们参照上⾯的这些内容,设计⼀个 JavaScript 版本的验证器。
需求
⾸先,我们列出对于验证器的需求:
输⼊:验证器接收⾄少两个参数:输⼊参数列表 和 针对每个输⼊参数的验证规则定义列表
输出:验证器返回⼀个数组,其中包含了验证参数失败的信息,默认只返回第⼀个验证失败的参数,⽀持返回所有验证失败的参数;如验证全部通过,则返回空数组。
验证规则:验证器除⽀持基本类型验证外,还需⽀持以下验证规则 required、max、min
扩展性:验证器⽀持扩展⾃定义验证规则和验证失败信息
语⾔⽀持:验证器⽀持多语⾔验证失败信息,⾄少⽀持:中⽂ 和 英⽂, 默认返回 中⽂ 错误信息
验证规则详情:
required,参数值为:null、undefined、NaN、空字符串、空数组、空对象,则验证不通过
max,参数值类型如果是:数字,则值不能⼤于(可以等于) max: 后⾯指定的值;参数值类型如果是:字符串、数组,则长度不能⼤于(可以等于)max: 后⾯指定的值
min,参数值类型如果是:数字,则值不能⼩于(可以等于) min: 后⾯指定的值;参数值类型如果是:字符串、数组,则长度不能⼩于(可以等于)min: 后⾯指定的值
实现
接下来,我们创建⼯程,并根据需求,设计好⼯程⽂件⽬录结构:
第⼀步:创建⼯程,搭建单元测试环境,并设计⼯程⽬录结构与⽂件
step1:创建⼯程
mkdir validator && cd validator && yarn init
然后安装我们需要的代码检查⼯具(standard)、单元测试⼯具(jest)和 git hook ⼯具(husky):
yarn add -D standard jest husky
安装完毕后,package.json 的内容如下:
{
"name": "validator",
"version": "1.0.0",
"main": "index.js",
"license": "MIT",
"devDependencies": {
"husky": "^3.0.5",
"jest": "^24.9.0",
"standard": "^14.3.0"
}
}
我们添加两个命令:
lint ⽤于启动代码检查
test ⽤于启动单元测试:
{
...
"scripts": {
"lint": "standard",
"test": "jest"
},
...
}
并设定每次执⾏ git commit 前,⾃动运⾏ yarn lint 和 yarn test:
{
...
"husky": {
"hooks": {
"pre-commit": "yarn lint && yarn test"
}
}
}
step2:配置单元测试环境
我们新建 fig.js ⽂件,并在其中指定单元测试覆盖率:
'collectCoverage': true,
'coverageThreshold': {
'global': {
'branches': 100,
'functions': 100,
'lines': 100,
'statements': 100
}
}
}
另外,因为在使⽤ jest 撰写单元测试时,会使⽤到两个全局变量:test 和 expect 所以,需要在 package.json 中将其添加到 standard ⽩名单:
{
...
"standard": {
"globals": [
"test",
"expect"
]
}
...
}
最终,package.json 的内容如下:
{
"name": "validator",
"version": "1.0.0",
"main": "index.js",
"license": "MIT",
"scripts": {
"lint": "standard",
"test": "jest"
},
"devDependencies": {
"husky": "^3.0.5",
"jest": "^24.9.0",
"standard": "^14.3.0"
},
"husky": {
"hooks": {
"pre-commit": "yarn lint && yarn test"
}
},
"standard": {
"globals": [
"test",
"expect"
]
}
}
step3:设计⽬录结构与⽂件
回顾⼀下需求,我们确定有如下⼏个功能⽂件:
index.js 功能⼊⼝⽂件,提供 validator 最终的 api 接⼝
rules.js 负责实现验证规则的细节
language.js 负责实现所有语⾔版本的验证失败信息
type.js 负责提供基本的类型校验功能
除 index.js 外(创建⼯程时已经创建了此⽂件),我们建好上述其他⽂件。接下来,我们新建两个⽂件夹:
lib 存放 rules.js、type.js、language.js
test存放 st.js
最终,⽬录如下:
├── fig.js
├── lib
│├── language.js
│├── rules.js
│└── type.js
├── package.json
├── test
│└── st.js
└── yarn.lock
到此,我们已经有了初步的环境和⽬录结构,接下来,我们撰写单元测试。第⼆步:实现单元测试
单元测试本质上是站在⽤户(使⽤者)的⾓度去验证功能⾏为,因此,在开始撰写单元测试之前,我们先要确定 validator 的 api:
step1:确定 Api
我们预期 validator 像如下这般使⽤:
const V = require('validator')
const params = { name:'hello world', age: 18 }
const schema = { name: 'string|required|max:10', age: 'number' }
const options = { language: 'en', deep: true }
const invalidList = V(params, schema, options)
// check invalidList ...
/* the invalidlist will be
[
{
令数组全部的值为0paramName: 'name',
actualValue: 'hello world',
invalidMessage: 'name can not gt 10. hello world given.'
}
]
*/
上述代码表达了如下内容:
1. params 是输⼊参数对象,其中包含两个参数:name 和 age,值分别为 hello world 和 18
2. schema 是针对输⼊参数对象所描述的具体验证规则,这⾥实际上要求 name 参数为字符串类型,且必须必传,且最⼤长度不能超过
10(可以等于 10),⽽ age 参数为数字类型
3. options 作为 validator 的配置参数,决定验证失败信息使⽤中⽂还是英⽂(默认为中⽂ zh),以及是否返回所有验证失败的参数信息
(默认只返回第⼀个验证失败的参数信息)
4. invalidList 是⼀个数组,如果内容不为空,则其中包含了验证失败参数的信息,包括:参数名称(paramName)、失败描述
(invalidMessage)、实际值(actualValue)
step2:设计测试⽤例
确定了 api 之后,我们来确认撰写测试⽤例的注意事项:
测试⽤例需要覆盖所有的验证规则,且每个规则需要覆盖 正 和 反 两个 case,其中,正 的 case 代表验证通过;反 的 case 代表验证失败
测试⽤例需要覆盖 中⽂ 和 英⽂ 两个 case
测试⽤例需要覆盖必传参数没有传递的 case
测试⽤例需要覆盖返回所有验证失败的参数的 case
接下来我们设计测试⽤例,最终代码如下:
const V = require('../index.js')
test('invalid value of params or schema or both', () => {
expect(V({ name: 'jarone' })).toEqual([])
expect(V({ name: 'jarone' }, 0)).toEqual([])
expect(V({ name: 'jarone' }, false)).toEqual([])
expect(V({ name: 'jarone' }, '')).toEqual([])
expect(V({ name: 'jarone' }, 123)).toEqual([])
expect(V({ name: 'jarone' }, 'abc')).toEqual([])
expect(V({ name: 'jarone' }, [])).toEqual([])
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论