Skip to content

Commit

Permalink
Add custom matcher support in the vitest
Browse files Browse the repository at this point in the history
  • Loading branch information
nazarhussain committed Oct 12, 2023
1 parent 00b495a commit d08b6e8
Show file tree
Hide file tree
Showing 3 changed files with 119 additions and 0 deletions.
55 changes: 55 additions & 0 deletions scripts/vitest/customMatchers.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
// eslint-disable-next-line import/no-extraneous-dependencies
import {expect} from "vitest";

expect.extend({
toBeValidEpochCommittee: (
committee: {index: number; slot: number; validators: unknown[]},
{
committeeCount,
validatorsPerCommittee,
slotsPerEpoch,
}: {committeeCount: number; validatorsPerCommittee: number; slotsPerEpoch: number}
) => {
if (committee.index < 0 || committee.index > committeeCount - 1) {
return {
message: () =>
`Committee index out of range. Expected between 0-${committeeCount - 1}, but got ${committee.index}`,
pass: false,
};
}

if (committee.slot < 0 || committee.slot > slotsPerEpoch - 1) {
return {
message: () =>
`Committee slot out of range. Expected between 0-${slotsPerEpoch - 1}, but got ${committee.slot}`,
pass: false,
};
}

if (committee.validators.length !== validatorsPerCommittee) {
return {
message: () =>
`Incorrect number of validators in committee. Expected ${validatorsPerCommittee}, but got ${committee.validators.length}`,
pass: false,
};
}

return {
message: () => "Committee is valid",
pass: true,
};
},
toBeWithMessage: (received: unknown, expected: unknown, message: string) => {
if (received === expected) {
return {
message: () => "Expected value is truthy",
pass: true,
};
}

return {
pass: false,
message: () => message,
};
},
});
35 changes: 35 additions & 0 deletions types/vitest/index.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// eslint-disable-next-line import/no-extraneous-dependencies, @typescript-eslint/no-unused-vars
import * as vitest from "vitest";

interface CustomMatchers<R = unknown> {
toBeValidEpochCommittee(opts: {committeeCount: number; validatorsPerCommittee: number; slotsPerEpoch: number}): R;
/**
* @deprecated
* We highly recommend to not use this matcher instead use detail test case
* where you don't need message to explain assertion
*
* @example
* ```ts
* it("should work as expected", () => {
* const a = 1;
* const b = 2;
* expect(a).toBeWithMessage(b, "a must be equal to b");
* });
* ```
* can be written as:
* ```ts
* it("a should always same as b", () => {
* const a = 1;
* const b = 2;
* expect(a).toBe(b);
* });
* ```
* */
toBeWithMessage(expected: unknown, message: string): R;
}

declare module "vitest" {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
interface Assertion<T = any> extends CustomMatchers<T> {}
interface AsymmetricMatchersContaining extends CustomMatchers {}
}
29 changes: 29 additions & 0 deletions vitest.base.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import path from "node:path";
import {defineConfig} from "vitest/config";
const __dirname = new URL(".", import.meta.url).pathname;

export default defineConfig({
test: {
setupFiles: [path.join(__dirname, "./scripts/vitest/customMatchers.ts")],
reporters: ["default", "hanging-process"],
coverage: {
clean: true,
all: false,
extension: [".ts"],
provider: "v8",
reporter: [["lcovonly", {file: "lcov.info"}], ["text"]],
reportsDirectory: "./coverage",
exclude: [
"**/*.d.ts",
"**/*.js",
"**/lib/**",
"**/coverage/**",
"**/scripts/**",
"**/test/**",
"**/types/**",
"**/bin/**",
"**/node_modules/**",
],
},
},
});

0 comments on commit d08b6e8

Please sign in to comment.