自定义比较 css 匹配器
自定义匹配器是一个函数,接收两个参数。
自定义匹配器
下面我们自定义一个匹配器,用来比较两个 css 字符串达到的效果是否一样。
ts
import {
matcherErrorMessage,
matcherHint,
printDiffOrStringify,
printExpected,
printReceived,
printWithType
} from "jest-matcher-utils"
// 自定义匹配器约定的返回类型
interface MatcherResult {
// 匹配结果
pass: boolean
// 匹配失败时给出的相关信息
message: () => string
}
const removeFormat = (str: string) => str.trim().replace(/[;\s]+/g, "")
// 自定义匹配器
// 把两个 CSS 字符串中的“分号”和“空白”去掉后进行比对,若相等则表示匹配成功
// 匹配器是一个函数
export const cssMatcher = (received: string, expected: string): MatcherResult => {
const receivedWithoutFormat = removeFormat(received)
const expectedWithoutFormat = removeFormat(expected)
const pass = receivedWithoutFormat === expectedWithoutFormat
// 利用 `jest-matcher-utils` 生成更有可读性的匹配失败信息
// 比较不同
const diffMessage = printDiffOrStringify(
expectedWithoutFormat, // 断言的值
receivedWithoutFormat, // 接收传入的值
"Expected CSS", // 断言的值 label
"Received CSS",// 接收传入的值 label
true // 为 true 代表会深度比较对象或数组的每个属性或元素。
// 为 false 只会显示对象或数组的高层结构,不会展开所有嵌套结构
)
// matcherHint 第一个参数传入匹配器的名字
const passMessage = matcherHint(".not.toMatchCss") +
"\n\n" +
"Two CSS classes should not be equal while ignoring white-space and semicolon (using ===):\n" +
diffMessage
const failMessage = matcherHint(".toMatchCss") +
"\n\n" +
"Two CSS classes should be equal while ignoring white-space and semicolon (using ===):\n" +
diffMessage
// message 的作用是输出错误信息,并给予提示
// 不使用 not,pass 为 true 代表通过,不会输出 message。否则输出 message。
// 使用 not,pass 为 true 被视为不通过,会调用 message 函数,输出 mesage。
return { pass, message: () => (pass ? passMessage : failMessage) }
}注册匹配器
ts
import {cssMatcher} from '../customMater/cssMatcher'
// 扩展匹配器
expect.extend({
toMatchCss: cssMatcher,
toBeFoo(received, expected) {
const { isNot } = this
return {
pass: received === 'foo',
message: () => `${received} is ${isNot ? ' not' : ''} foo`
}
}
})
describe('判断生成 css 是否相同', () => {
const generatedCss = `
.clay {
background-color: #f87171;
}
`
const expectedCss = `.clay { background-color: #f87171; }`
// .skip 跳过这个测试。因为肯定不通过。
test.skip('test', () => {
expect(generatedCss).toBe(expectedCss);
})
// 在验证前格式化字符串。但是比较麻烦
test('test2', () => {
expect(generatedCss.trim().replace(/[;\s]+/g, ""))
.toBe(`.clay { background-color: #f87171; }`.trim().replace(/[;\s]+/g, ""))
})
// 使用我们的自定义匹配器
test('test3', () => {
expect(generatedCss).toMatchCss(expectedCss)
})
});ts 支持
官网说建一个 vitest.d.ts 文件,写入如下类型,然后在 tsconfig.json 里包含该声明文件即可。但实际会发现会把原有的类型全部变为 any。
ts
interface CustomMatchers<R = unknown> {
toMatchCss(): R
}
declare module 'vitest' {
interface Assertion<T = any> extends CustomMatchers<T> {}
interface AsymmetricMatchersContaining extends CustomMatchers {}
}