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 +99 -3
- package/dist/assertions/index.d.ts +4 -2
- package/dist/assertions/index.js +7 -6
- package/dist/assertions/{errorsEquivalent.d.ts → isError.d.ts} +1 -1
- package/dist/assertions/{errorsEquivalent.js → isError.js} +3 -3
- package/dist/assertions/throws.d.ts +1 -1
- package/dist/assertions/throws.js +36 -10
- package/dist/lib/deepStrictEqual.d.ts +1 -1
- package/dist/lib/deepStrictEqual.js +29 -19
- package/dist/test.d.ts +1 -3
- package/package.json +1 -1
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
|
-
//
|
|
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
|
|
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;
|
package/dist/assertions/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.createAssertionPredicates = createAssertionPredicates;
|
|
4
|
-
const
|
|
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) => (
|
|
14
|
-
fail: (description) => (
|
|
15
|
-
isTrue: (condition, description) => (
|
|
16
|
-
isFalse: (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
|
-
|
|
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
|
|
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.
|
|
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
|
|
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=
|
|
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
|
|
5
|
-
const errorsEquivalent_1 = require("./errorsEquivalent");
|
|
13
|
+
const isError_1 = require("./isError");
|
|
6
14
|
function throws(assertions, experiment, expectedErr, description) {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
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(
|
|
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(
|
|
6
|
-
if (
|
|
5
|
+
function deepStrictEqual(actual, expected) {
|
|
6
|
+
if (actual === expected)
|
|
7
7
|
return true;
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
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
|
|
22
|
+
if (typeof actual !== typeof expected)
|
|
13
23
|
return false;
|
|
14
|
-
if (
|
|
24
|
+
if (actual === null || expected === null)
|
|
15
25
|
return false;
|
|
16
26
|
// Handle Map objects
|
|
17
|
-
if (
|
|
18
|
-
if (
|
|
27
|
+
if (actual instanceof Map && expected instanceof Map) {
|
|
28
|
+
if (actual.size !== expected.size)
|
|
19
29
|
return false;
|
|
20
|
-
for (const [key, value] of
|
|
21
|
-
if (!
|
|
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 (
|
|
28
|
-
if (
|
|
37
|
+
if (actual instanceof Set && expected instanceof Set) {
|
|
38
|
+
if (actual.size !== expected.size)
|
|
29
39
|
return false;
|
|
30
|
-
for (const item of
|
|
40
|
+
for (const item of actual) {
|
|
31
41
|
let matchFound = false;
|
|
32
|
-
for (const item2 of
|
|
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(
|
|
45
|
-
const keys2 = Object.keys(
|
|
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(
|
|
59
|
+
if (!Object.prototype.hasOwnProperty.call(expected, key))
|
|
50
60
|
return false;
|
|
51
|
-
if (!deepStrictEqual(
|
|
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 {
|
|
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.
|
|
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",
|