Chai 中文文档 下载 App

.match / regexp 正则匹配与 .satisfy 自定义谓词

.match —— 正则匹配

expect('hello123').to.match(/^\w+\d+$/);          // 通过
expect('user@example.com').to.match(/^[^\s@]+@[^\s@]+\.[^\s@]+$/);  // 通过
expect('INVALID').to.match(/^\d+$/);              // 失败

参数可以是 RegExp 对象也可以是正则字符串(建议用 RegExp 字面量,避免转义):

expect('hello').to.match(/^h/);
expect('hello').to.match('^h');  // 也可以,但转义麻烦

配合 .not:

expect('password123').to.not.match(/\s/);  // 不应该包含空白字符

.regexp —— .match 的别名

expect('hello').to.regexp(/^h/);  // 同 .match

完全等价,选哪个都行。

.satisfy —— 自定义谓词

当内置断言不够用时,.satisfy 接受一个函数,返回 boolean:

// 自定义:必须是偶数
expect(42).to.satisfy(n => n % 2 === 0);        // 通过
expect(43).to.satisfy(n => n % 2 === 0);        // 失败

// 自定义:字符串长度在 [5, 10] 之间且首字母大写
expect('Hello').to.satisfy(s => {
  return s.length >= 5 && s.length <= 10 && /^[A-Z]/.test(s);
});

函数的第一个参数是被断言的值,返回 true 表示通过,false 表示失败。

.satisfy 的错误消息

.satisfy 失败时的错误消息信息量有限:

expect(43).to.satisfy(n => n % 2 === 0);
// AssertionError: expected 43 to satisfy [Function]

函数名如果有帮助会更好:

function isEven(n) { return n % 2 === 0; }
expect(43).to.satisfy(isEven);
// AssertionError: expected 43 to satisfy isEven

或者加自定义消息(expect 风格支持):

expect(43, '应该是偶数').to.satisfy(n => n % 2 === 0);
// AssertionError: 应该是偶数: expected 43 to satisfy [Function]

何时用 .satisfy

何时不用 .satisfy

assert 风格中的 .match / .satisfy

assert.match('hello', /^h/);  // assert.match (v5+)
assert.notMatch('hello', /^w/);

// assert 风格没有 satisfy,用 assert(expression) 代替
assert(n % 2 === 0, '应该是偶数');

正则常见场景

邮箱格式

expect(email).to.match(/^[^\s@]+@[^\s@]+\.[^\s@]+$/);

URL 格式

expect(url).to.match(/^https?:\/\/[^\s]+$/);

只包含安全字符(XSS 防护)

expect(input).to.not.match(/[<>"]/);  // 不包含 < > "

密码强度

expect(password).to.match(/^(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{8,}$/);
// 至少 8 字符,含数字、小写、大写

下一步