From f0eefd683a90a9dfd1ce142964eb280435c8822f Mon Sep 17 00:00:00 2001 From: Congcong Cai Date: Mon, 24 Nov 2025 13:58:03 +0800 Subject: [PATCH] feat: support not matcher --- assembly/expect.ts | 44 ++++++++++++++++++++++++---------- docs/api-documents/matchers.md | 13 ++++++++-- tests/as/expect.test.ts | 19 +++++++++++++++ 3 files changed, 62 insertions(+), 14 deletions(-) diff --git a/assembly/expect.ts b/assembly/expect.ts index fc1f326..fc4d839 100644 --- a/assembly/expect.ts +++ b/assembly/expect.ts @@ -12,8 +12,28 @@ export class Value { constructor(_data: T) { this.data = _data; } - isNull(codeInfoIndex: u32 = EXPECT_MAX_INDEX): Value { + + private collect( + result: bool, + codeInfoIndex: number, + actualValue: string, + expectValue: string, + ): void { assertResult.collectCheckResult( + this.reversed ? !result : result, + codeInfoIndex, + actualValue, + expectValue, + ); + } + + get not(): Value { + this.reversed = !this.reversed; + return this; + } + + isNull(codeInfoIndex: u32 = EXPECT_MAX_INDEX): Value { + this.collect( isNull(this.data), codeInfoIndex, toJson(this.data), @@ -22,7 +42,7 @@ export class Value { return this; } notNull(codeInfoIndex: u32 = EXPECT_MAX_INDEX): Value { - assertResult.collectCheckResult( + this.collect( !isNull(this.data), codeInfoIndex, toJson(this.data), @@ -32,7 +52,7 @@ export class Value { } equal(checkValue: T, codeInfoIndex: u32 = EXPECT_MAX_INDEX): Value { - assertResult.collectCheckResult( + this.collect( equal(this.data, checkValue), codeInfoIndex, toJson(this.data), @@ -41,7 +61,7 @@ export class Value { return this; } notEqual(checkValue: T, codeInfoIndex: u32 = EXPECT_MAX_INDEX): Value { - assertResult.collectCheckResult( + this.collect( !equal(this.data, checkValue), codeInfoIndex, toJson(this.data), @@ -51,7 +71,7 @@ export class Value { } greaterThan(checkValue: T, codeInfoIndex: u32 = EXPECT_MAX_INDEX): Value { - assertResult.collectCheckResult( + this.collect( this.data > checkValue, codeInfoIndex, toJson(this.data), @@ -63,7 +83,7 @@ export class Value { checkValue: T, codeInfoIndex: u32 = EXPECT_MAX_INDEX, ): Value { - assertResult.collectCheckResult( + this.collect( this.data >= checkValue, codeInfoIndex, toJson(this.data), @@ -72,7 +92,7 @@ export class Value { return this; } lessThan(checkValue: T, codeInfoIndex: u32 = EXPECT_MAX_INDEX): Value { - assertResult.collectCheckResult( + this.collect( this.data < checkValue, codeInfoIndex, toJson(this.data), @@ -84,7 +104,7 @@ export class Value { checkValue: T, codeInfoIndex: u32 = EXPECT_MAX_INDEX, ): Value { - assertResult.collectCheckResult( + this.collect( this.data <= checkValue, codeInfoIndex, toJson(this.data), @@ -100,7 +120,7 @@ export class Value { ): Value { const data = this.data; if (isFloat(checkValue) && isFloat(data)) { - assertResult.collectCheckResult( + this.collect( abs(data - checkValue) < delta, codeInfoIndex, toJson(this.data), @@ -113,7 +133,7 @@ export class Value { } isa(codeInfoIndex: u32 = EXPECT_MAX_INDEX): Value { - assertResult.collectCheckResult( + this.collect( // @ts-ignore this.data instanceof ExpectType, codeInfoIndex, @@ -127,7 +147,7 @@ export class Value { isExactly(codeInfoIndex: u32 = EXPECT_MAX_INDEX): Value { if (isNullable()) { if (this.data == null) { - assertResult.collectCheckResult( + this.collect( false, codeInfoIndex, `<>`, @@ -137,7 +157,7 @@ export class Value { } } const rtid = load(changetype(this.data) - 8); - assertResult.collectCheckResult( + this.collect( rtid == idof(), codeInfoIndex, `RTID<${rtid}>`, diff --git a/docs/api-documents/matchers.md b/docs/api-documents/matchers.md index 212b064..2178552 100644 --- a/docs/api-documents/matchers.md +++ b/docs/api-documents/matchers.md @@ -10,6 +10,15 @@ test('two plus two is four', () => { In this code, `expect(2+2)` returns an "Value" object. You typically won't do much with these objects except call matchers on them. In this code, `.equal(4)` is the matcher. When Jest runs, it tracks all the failing matchers so that it can print out nice error messages for you. +### Not + +`not` matcher can reverse the matching results of all subsequent `matcher` statements. + +```ts +expect(1).not.equal(2); // success +expect(1).not.equal(1); // fail +``` + ### Equal In the most condition, `equal` is similar as `==`, you can use this matcher to compare `i32 | i64 | u32 | u64 | f32 | f64 | string` just like `==`. What's more, it can also be used to compare some inner type, such as `Array | Map | Set`. @@ -24,12 +33,12 @@ Most ways of comparing numbers have matcher equivalents, like `equal`, `greaterT Specially, for float type, use `closeTo` instead of `equal` to avoid rounding error. -## Nullable +### Nullable `isNull` and `notNull` matchers can be used to a nullable object. Of course, you can also use `equal` and `notEqual` to do same thing with explicit generic declaration `expect()` -## Typing +### Typing `isa` and `isExactly` matchers can be used to compare typing. diff --git a/tests/as/expect.test.ts b/tests/as/expect.test.ts index 020fc4d..9c420a2 100644 --- a/tests/as/expect.test.ts +++ b/tests/as/expect.test.ts @@ -3,6 +3,7 @@ import { describe, expect, test } from "../../assembly"; class Base {} class Ext_0 extends Base {} class Ext_0_0 extends Ext_0 {} +class Ext_0_0_0 extends Ext_0 {} class Ext_1 extends Base {} class Ext_1_1 extends Ext_1 {} @@ -19,11 +20,29 @@ describe("expect", () => { expect(null).isNull(); expect("test").notNull(); }); + test("not", () => { + expect(1).not.equal(2); + }); test("isa", () => { let ext: Base = new Ext_0_0(); expect(ext).isa(); expect(ext).isa(); expect(ext).isa(); + expect(ext).not.isa(); + expect(ext).not.isa(); + expect(ext).not.isa(); + }); + test("isExactly", () => { + let ext: Base = new Ext_0_0(); expect(ext).isExactly(); + expect(ext).not.isExactly(); + expect(ext).not.isExactly(); + expect(ext).not.isExactly(); + }); + test("nullable isExactly", () => { + let extNull: Base | null = null; + let extNonNull: Base | null = new Base(); + expect(extNull).not.isExactly(); + expect(extNonNull).isExactly(); }); });