kizu 3.7.7 → 3.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -22,6 +22,7 @@ Designed to help you write simple, readable, and maintainable tests.
22
22
 
23
23
  ### **😀 Easy to Use**
24
24
  - Very simple functional [assertion API](docs/api.md). No need to learn a DSL or framework.
25
+ - **One assertion method does it all**: `assert.equal()` handles primitives, objects, arrays, Maps, Sets, and even RegExp pattern matching!
25
26
  - Built-in [powerful diff visualization tool](/docs/visualDiff.md)
26
27
  - Clean, organized output.
27
28
  - Failed tests are easy to find, grouped at the end of the output.
@@ -38,6 +39,20 @@ Designed to help you write simple, readable, and maintainable tests.
38
39
  - Works great with [c8](https://github.com/bcoe/c8) for code coverage.
39
40
  - Handles compilation errors gracefully.
40
41
 
42
+ ### **✨ Powerful `assert.equal()` - One Assertion to Rule Them All**
43
+ The `assert.equal()` method is incredibly versatile and handles most of your testing needs:
44
+
45
+ - **Primitive comparison**: Numbers, strings, booleans, null, undefined
46
+ - **Deep object equality**: Compares nested objects, arrays, Maps, and Sets
47
+ - **RegExp pattern matching**: Test string values against RegExp patterns in the expected value
48
+ - **Mixed comparisons**: Combine exact values and RegExp patterns in the same object
49
+ - **Visual diffs**: Beautiful, detailed output when assertions fail
50
+ - **Type safety**: Full TypeScript support with proper type checking
51
+
52
+ Note: `assert.equal()` compares values by value (deep equality), not by reference.
53
+
54
+ This single assertion method eliminates the need for multiple specialized assertion methods or complex mocking while providing powerful, flexible testing capabilities.
55
+
41
56
  ## Quick Examples
42
57
 
43
58
  For more examples, see the [examples](examples) and [src](src) folders.
@@ -55,7 +70,6 @@ npx kizu 'src/example.test.ts'
55
70
  import {test} from 'kizu';
56
71
 
57
72
  // Basic test
58
-
59
73
  function greet(name: string): string {
60
74
  return `hello, ${name}`;
61
75
  }
@@ -64,8 +78,73 @@ test('greet', (assert) => {
64
78
  assert.equal(greet('world'), 'hello, world');
65
79
  });
66
80
 
67
- // Error handling
81
+ // Deep object comparison
82
+ test('user object', (assert) => {
83
+ const actual = {
84
+ name: 'John',
85
+ age: 30,
86
+ email: 'john@example.com',
87
+ preferences: {
88
+ theme: 'dark',
89
+ notifications: true
90
+ }
91
+ };
92
+
93
+ const expected = {
94
+ name: 'John',
95
+ age: 30,
96
+ email: 'john@example.com',
97
+ preferences: {
98
+ theme: 'dark',
99
+ notifications: true
100
+ }
101
+ };
102
+
103
+ assert.equal(actual, expected); // Deep equality comparison
104
+ });
105
+
106
+ // RegExp pattern matching ✨ NEW!
107
+ test('email validation', (assert) => {
108
+ const email = 'user@example.com';
109
+
110
+ // Match email pattern
111
+ assert.equal(email, /^[^@]+@[^@]+\.[^@]+$/);
112
+
113
+ // Match domain
114
+ assert.equal(email, /@example\.com$/);
115
+
116
+ // Match username
117
+ assert.equal(email, /^user@/);
118
+ });
119
+
120
+ // Complex data structures
121
+ test('complex data', (assert) => {
122
+ const actual = {
123
+ users: [
124
+ { name: 'Alice', email: 'alice@company.com' },
125
+ { name: 'Bob', email: 'bob@company.com' }
126
+ ],
127
+ metadata: {
128
+ count: 2,
129
+ lastUpdated: '2024-01-15'
130
+ }
131
+ };
132
+
133
+ const expected = {
134
+ users: [
135
+ { name: 'Alice', email: /@company\.com$/ }, // RegExp in nested objects!
136
+ { name: 'Bob', email: /@company\.com$/ }
137
+ ],
138
+ metadata: {
139
+ count: 2,
140
+ lastUpdated: /^\d{4}-\d{2}-\d{2}$/ // Date pattern
141
+ }
142
+ };
143
+
144
+ assert.equal(actual, expected);
145
+ });
68
146
 
147
+ // Error handling
69
148
  function throwError(): never {
70
149
  throw new Error('oops');
71
150
  }
@@ -75,7 +154,6 @@ test('throwError', (assert) => {
75
154
  });
76
155
 
77
156
  // Async test
78
-
79
157
  async function fetchData(): Promise<string> {
80
158
  return Promise.resolve('data');
81
159
  }
@@ -105,6 +183,24 @@ test('fetchData', async (assert) => {
105
183
  To install and get started with `kizu`, see our [Getting Started](docs/gettingStarted.md) guide.
106
184
  See the [examples](examples) and [src](src) folders for more examples.
107
185
 
186
+ ## Why `assert.equal()` is Amazing
187
+
188
+ With just one assertion method, you can test:
189
+
190
+ ✅ **Simple values**: `assert.equal(42, 42)`
191
+ ✅ **Complex objects**: Deep comparison of nested structures
192
+ ✅ **Pattern matching**: `assert.equal('user@example.com', /@example\.com$/)`
193
+ ✅ **Mixed data**: Combine exact values and RegExp patterns
194
+ ✅ **Collections**: Arrays, Maps, and Sets with full deep equality
195
+ ✅ **Beautiful failures**: Visual diffs show exactly what's different
196
+
197
+ No need to learn multiple assertion methods or complex APIs. `assert.equal()` handles it all with elegance and power!
198
+
199
+ ```typescript
200
+ // One assertion method to rule them all! ✨
201
+ assert.equal(actual, expected);
202
+ ```
203
+
108
204
  ## Support, feedback, and contributions
109
205
 
110
206
  - Star this repo if you like it!
@@ -1,10 +1,12 @@
1
1
  import { Assertion } from '../test';
2
- export declare function createAssertionPredicates(assertions: Assertion[]): {
2
+ export type AssertionAPI = {
3
3
  pass: (description?: string) => void;
4
4
  fail: (description?: string) => void;
5
5
  isTrue: (condition: boolean, description?: string) => void;
6
6
  isFalse: (condition: boolean, description?: string) => void;
7
7
  equal: (actual: any, expected: any, description?: string) => void;
8
+ isError: (actual: any, expected: any, description?: string) => void;
8
9
  errorsEquivalent: (actual: any, expected: any, description?: string) => void;
9
- throws: (experiment: () => any, expectedErr: Error | RegExp, description?: string) => void;
10
+ throws: (experiment: () => any, expectedErr: Error | RegExp, description?: string) => Promise<void>;
10
11
  };
12
+ export declare function createAssertionPredicates(assertions: Assertion[]): AssertionAPI;
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.createAssertionPredicates = createAssertionPredicates;
4
- const errorsEquivalent_1 = require("./errorsEquivalent");
4
+ const isError_1 = require("./isError");
5
5
  const equal_1 = require("./equal");
6
6
  const throws_1 = require("./throws");
7
7
  const isTrue_1 = require("./isTrue");
@@ -10,12 +10,13 @@ const fail_1 = require("./fail");
10
10
  const pass_1 = require("./pass");
11
11
  function createAssertionPredicates(assertions) {
12
12
  return {
13
- pass: (description) => ((0, pass_1.pass)(assertions, description)),
14
- fail: (description) => ((0, fail_1.fail)(assertions, description)),
15
- isTrue: (condition, description) => ((0, isTrue_1.isTrue)(assertions, condition, description)),
16
- isFalse: (condition, description) => ((0, isFalse_1.isFalse)(assertions, condition, description)),
13
+ pass: (description) => (0, pass_1.pass)(assertions, description),
14
+ fail: (description) => (0, fail_1.fail)(assertions, description),
15
+ isTrue: (condition, description) => (0, isTrue_1.isTrue)(assertions, condition, description),
16
+ isFalse: (condition, description) => (0, isFalse_1.isFalse)(assertions, condition, description),
17
17
  equal: (actual, expected, description) => ((0, equal_1.equal)(assertions, actual, expected, description)),
18
- errorsEquivalent: (actual, expected, description) => ((0, errorsEquivalent_1.errorsEquivalent)(assertions, actual, expected, description)),
18
+ isError: (actual, expected, description) => ((0, isError_1.isError)(assertions, actual, expected, description)),
19
+ errorsEquivalent: (actual, expected, description) => ((0, isError_1.isError)(assertions, actual, expected, description)), // deprecated
19
20
  throws: (experiment, expectedErr, description) => ((0, throws_1.throws)(assertions, experiment, expectedErr, description)),
20
21
  };
21
22
  }
@@ -1,3 +1,3 @@
1
1
  import { Assertion } from '../test';
2
- export declare function errorsEquivalent(assertions: Assertion[], actualErr: Error, expectedErr: Error | RegExp, description?: string): void;
2
+ export declare function isError(assertions: Assertion[], actualErr: Error, expectedErr: Error | RegExp, description?: string): void;
3
3
  export declare function createDiagnosticRegexMismatch(actualErrMsg: string, expectedRegEx: RegExp): string;
@@ -3,14 +3,14 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.errorsEquivalent = errorsEquivalent;
6
+ exports.isError = isError;
7
7
  exports.createDiagnosticRegexMismatch = createDiagnosticRegexMismatch;
8
8
  const serialize_error_1 = require("serialize-error");
9
9
  const equal_1 = require("./equal");
10
10
  const pass_1 = require("./pass");
11
11
  const AssertionError_1 = require("./AssertionError");
12
12
  const kleur_1 = __importDefault(require("kleur"));
13
- function errorsEquivalent(assertions, actualErr, expectedErr, description) {
13
+ function isError(assertions, actualErr, expectedErr, description) {
14
14
  if (!(actualErr instanceof Error))
15
15
  throw new Error('actualErr is not an instance of Error');
16
16
  if (!(expectedErr instanceof Error) && !(expectedErr instanceof RegExp))
@@ -46,4 +46,4 @@ function createDiagnosticRegexMismatch(actualErrMsg, expectedRegEx) {
46
46
  const expected = `\n\n${kleur_1.default.grey().bold('Expected RegEx:')}\n\n${expectedRegEx}`;
47
47
  return `${actual}${expected}\n\n`;
48
48
  }
49
- //# sourceMappingURL=errorsEquivalent.js.map
49
+ //# sourceMappingURL=isError.js.map
@@ -1,2 +1,2 @@
1
1
  import { Assertion } from '../test';
2
- export declare function throws(assertions: Assertion[], experiment: () => any, expectedErr: Error | RegExp, description?: string): void;
2
+ export declare function throws(assertions: Assertion[], experiment: () => any, expectedErr: Error | RegExp, description?: string): Promise<void>;
@@ -1,16 +1,42 @@
1
1
  "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
2
11
  Object.defineProperty(exports, "__esModule", { value: true });
3
12
  exports.throws = throws;
4
- const toResult_1 = require("../lib/toResult");
5
- const errorsEquivalent_1 = require("./errorsEquivalent");
13
+ const isError_1 = require("./isError");
6
14
  function throws(assertions, experiment, expectedErr, description) {
7
- if (typeof experiment !== 'function')
8
- throw new Error('experiment must be a function');
9
- if (!(expectedErr instanceof Error) && !(expectedErr instanceof RegExp))
10
- throw new Error('expectedErr is not an instance of Error or a RegExp');
11
- const [actualErr] = (0, toResult_1.toResult)(experiment);
12
- if (!actualErr)
13
- throw new Error('experiment did not throw an error');
14
- (0, errorsEquivalent_1.errorsEquivalent)(assertions, actualErr, expectedErr, description || 'throws()');
15
+ return __awaiter(this, void 0, void 0, function* () {
16
+ if (typeof experiment !== 'function')
17
+ throw new Error('experiment must be a function');
18
+ if (!(expectedErr instanceof Error) && !(expectedErr instanceof RegExp))
19
+ throw new Error('expectedErr is not an instance of Error or a RegExp');
20
+ let actualErr;
21
+ try {
22
+ const result = experiment();
23
+ // Check if the result is a Promise
24
+ if (result && typeof result.then === 'function') {
25
+ // Handle async function - wait for the promise to resolve or reject
26
+ yield result;
27
+ // If we get here, the promise resolved without throwing
28
+ throw new Error('experiment did not throw an error');
29
+ }
30
+ // If we get here, the sync function completed without throwing
31
+ throw new Error('experiment did not throw an error');
32
+ }
33
+ catch (e) {
34
+ actualErr = e;
35
+ }
36
+ if (!actualErr) {
37
+ throw new Error('experiment did not throw an error');
38
+ }
39
+ (0, isError_1.isError)(assertions, actualErr, expectedErr, description || 'throws()');
40
+ });
15
41
  }
16
42
  //# sourceMappingURL=throws.js.map
@@ -1 +1 @@
1
- export declare function deepStrictEqual(obj1: any, obj2: any): boolean;
1
+ export declare function deepStrictEqual(actual: any, expected: any): boolean;
@@ -2,34 +2,44 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.deepStrictEqual = deepStrictEqual;
4
4
  /* eslint-disable max-lines-per-function */
5
- function deepStrictEqual(obj1, obj2) {
6
- if (obj1 === obj2)
5
+ function deepStrictEqual(actual, expected) {
6
+ if (actual === expected)
7
7
  return true;
8
- if (isPrimitive(obj1) && isPrimitive(obj2))
9
- return obj1 === obj2;
10
- if (Array.isArray(obj1) !== Array.isArray(obj2))
8
+ // Handle RegExp comparison - expected can be RegExp, actual should be string
9
+ if (expected instanceof RegExp) {
10
+ if (typeof actual !== 'string')
11
+ return false;
12
+ return expected.test(actual);
13
+ }
14
+ // Handle case where actual is RegExp but expected is not RegExp
15
+ if (actual instanceof RegExp && !(expected instanceof RegExp)) {
16
+ return false;
17
+ }
18
+ if (isPrimitive(actual) && isPrimitive(expected))
19
+ return actual === expected;
20
+ if (Array.isArray(actual) !== Array.isArray(expected))
11
21
  return false;
12
- if (typeof obj1 !== typeof obj2)
22
+ if (typeof actual !== typeof expected)
13
23
  return false;
14
- if (obj1 === null || obj2 === null)
24
+ if (actual === null || expected === null)
15
25
  return false;
16
26
  // Handle Map objects
17
- if (obj1 instanceof Map && obj2 instanceof Map) {
18
- if (obj1.size !== obj2.size)
27
+ if (actual instanceof Map && expected instanceof Map) {
28
+ if (actual.size !== expected.size)
19
29
  return false;
20
- for (const [key, value] of obj1) {
21
- if (!obj2.has(key) || !deepStrictEqual(value, obj2.get(key)))
30
+ for (const [key, value] of actual) {
31
+ if (!expected.has(key) || !deepStrictEqual(value, expected.get(key)))
22
32
  return false;
23
33
  }
24
34
  return true;
25
35
  }
26
36
  // Handle Set objects
27
- if (obj1 instanceof Set && obj2 instanceof Set) {
28
- if (obj1.size !== obj2.size)
37
+ if (actual instanceof Set && expected instanceof Set) {
38
+ if (actual.size !== expected.size)
29
39
  return false;
30
- for (const item of obj1) {
40
+ for (const item of actual) {
31
41
  let matchFound = false;
32
- for (const item2 of obj2) {
42
+ for (const item2 of expected) {
33
43
  if (deepStrictEqual(item, item2)) {
34
44
  matchFound = true;
35
45
  break;
@@ -41,14 +51,14 @@ function deepStrictEqual(obj1, obj2) {
41
51
  return true;
42
52
  }
43
53
  // Handle object comparison
44
- const keys1 = Object.keys(obj1);
45
- const keys2 = Object.keys(obj2);
54
+ const keys1 = Object.keys(actual);
55
+ const keys2 = Object.keys(expected);
46
56
  if (keys1.length !== keys2.length)
47
57
  return false;
48
58
  for (const key of keys1) {
49
- if (!Object.prototype.hasOwnProperty.call(obj2, key))
59
+ if (!Object.prototype.hasOwnProperty.call(expected, key))
50
60
  return false;
51
- if (!deepStrictEqual(obj1[key], obj2[key]))
61
+ if (!deepStrictEqual(actual[key], expected[key]))
52
62
  return false;
53
63
  }
54
64
  return true;
package/dist/test.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { createAssertionPredicates } from './assertions';
1
+ import { AssertionAPI } from './assertions';
2
2
  import { ErrorObject } from 'serialize-error';
3
3
  export type TestResults = {
4
4
  description: string;
@@ -11,6 +11,4 @@ export type Assertion = {
11
11
  diagnostic?: string;
12
12
  stack?: string;
13
13
  };
14
- type AssertionAPI = ReturnType<typeof createAssertionPredicates>;
15
14
  export declare function test(description: string, experiment: (assert: AssertionAPI) => void): Promise<void>;
16
- export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "kizu",
3
- "version": "3.7.7",
3
+ "version": "3.9.0",
4
4
  "description": "An easy-to-use, fast, and defensive Typescript/Javascript test runner designed to help you to write simple, readable, and maintainable tests.",
5
5
  "license": "MIT",
6
6
  "main": "./dist/index.js",