expect-matcher-node-mock 1.1.2 → 1.1.3
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 +23 -7
- package/lib/index.mjs +3 -3
- package/lib/mockMethodMatchers.mjs +270 -339
- package/package.json +9 -10
package/README.md
CHANGED
|
@@ -22,15 +22,15 @@ This package bridges that gap by:
|
|
|
22
22
|
## Installation
|
|
23
23
|
|
|
24
24
|
```bash
|
|
25
|
-
npm install expect-matcher-node-mock
|
|
25
|
+
npm install --save-dev expect-matcher-node-mock
|
|
26
26
|
```
|
|
27
27
|
|
|
28
28
|
```bash
|
|
29
|
-
yarn add expect-matcher-node-mock
|
|
29
|
+
yarn add --dev expect-matcher-node-mock
|
|
30
30
|
```
|
|
31
31
|
|
|
32
32
|
```bash
|
|
33
|
-
pnpm add expect-matcher-node-mock
|
|
33
|
+
pnpm add --save-dev expect-matcher-node-mock
|
|
34
34
|
```
|
|
35
35
|
|
|
36
36
|
## Usage
|
|
@@ -163,14 +163,24 @@ https://jestjs.io/docs/expect#tohaventhreturnedwithnthcall-value
|
|
|
163
163
|
## Requirements
|
|
164
164
|
|
|
165
165
|
- **Node.js 18.0.0 or higher** (for native test runner support)
|
|
166
|
-
- **expect package** (peer dependency) -
|
|
166
|
+
- **expect package** (peer dependency) - Version 29.0.0 or higher
|
|
167
|
+
- **jest-matcher-utils package** (peer dependency) - Version 29.0.0 or higher
|
|
168
|
+
- **chalk package** (peer dependency) - Version 4.0.0 or higher
|
|
167
169
|
|
|
168
170
|
## Peer Dependencies
|
|
169
171
|
|
|
170
|
-
This package requires the
|
|
172
|
+
This package requires the following libraries to be installed in your project:
|
|
171
173
|
|
|
172
174
|
```bash
|
|
173
|
-
npm install expect
|
|
175
|
+
npm install expect jest-matcher-utils chalk
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
```bash
|
|
179
|
+
yarn add expect jest-matcher-utils chalk
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
```bash
|
|
183
|
+
pnpm add expect jest-matcher-utils chalk
|
|
174
184
|
```
|
|
175
185
|
|
|
176
186
|
## Troubleshooting
|
|
@@ -225,8 +235,14 @@ npm install
|
|
|
225
235
|
# Run tests
|
|
226
236
|
npm test
|
|
227
237
|
|
|
228
|
-
# Run linting
|
|
238
|
+
# Run linting (uses Biome)
|
|
229
239
|
npm run lint
|
|
240
|
+
|
|
241
|
+
# Auto-fix linting issues
|
|
242
|
+
npm run lint:fix
|
|
243
|
+
|
|
244
|
+
# Format code
|
|
245
|
+
npm run format
|
|
230
246
|
```
|
|
231
247
|
|
|
232
248
|
## Changelog
|
package/lib/index.mjs
CHANGED
|
@@ -6,12 +6,12 @@ import {
|
|
|
6
6
|
toHaveBeenCalledWith,
|
|
7
7
|
toHaveBeenLastCalledWith,
|
|
8
8
|
toHaveBeenNthCalledWith,
|
|
9
|
-
|
|
9
|
+
toHaveLastReturnedWith,
|
|
10
|
+
toHaveNthReturnedWith,
|
|
10
11
|
toHaveReturned,
|
|
11
12
|
toHaveReturnedTimes,
|
|
12
13
|
toHaveReturnedWith,
|
|
13
|
-
|
|
14
|
-
toHaveNthReturnedWith,
|
|
14
|
+
toReturn,
|
|
15
15
|
} from './mockMethodMatchers.mjs';
|
|
16
16
|
|
|
17
17
|
expect.extend({
|
|
@@ -13,13 +13,44 @@ export const INVERTED_COLOR = chalk.inverse;
|
|
|
13
13
|
export const BOLD_WEIGHT = chalk.bold;
|
|
14
14
|
export const DIM_COLOR = chalk.dim;
|
|
15
15
|
|
|
16
|
+
/**
|
|
17
|
+
* Helper function to check if arguments match using deep equality
|
|
18
|
+
* @param {Array} callArgs - The arguments from the actual call
|
|
19
|
+
* @param {Array} expectedArgs - The expected arguments
|
|
20
|
+
* @returns {boolean} - Whether the arguments match
|
|
21
|
+
*/
|
|
22
|
+
function argumentsMatch(callArgs, expectedArgs) {
|
|
23
|
+
if (callArgs.length !== expectedArgs.length) {
|
|
24
|
+
return false;
|
|
25
|
+
}
|
|
26
|
+
return expectedArgs.every((arg, index) => {
|
|
27
|
+
try {
|
|
28
|
+
expect(callArgs[index]).toEqual(arg);
|
|
29
|
+
return true;
|
|
30
|
+
} catch (_) {
|
|
31
|
+
return false;
|
|
32
|
+
}
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Helper function to format expected arguments message
|
|
38
|
+
* @param {Array} args - The arguments to format
|
|
39
|
+
* @returns {string} - Formatted message
|
|
40
|
+
*/
|
|
41
|
+
function formatExpectedArgs(args) {
|
|
42
|
+
return args.length === 0
|
|
43
|
+
? 'called with 0 arguments'
|
|
44
|
+
: args.map(arg => printExpected(arg)).join(', ');
|
|
45
|
+
}
|
|
46
|
+
|
|
16
47
|
/**
|
|
17
48
|
* Function to ensure that the received value is a mock function
|
|
18
|
-
* @param {Function} received
|
|
19
|
-
* @param {string} matcherName
|
|
20
|
-
* @param {Object} options
|
|
21
|
-
* @returns {boolean}
|
|
22
|
-
* @throws {TypeError}
|
|
49
|
+
* @param {Function} received - The value to check if it's a mock function
|
|
50
|
+
* @param {string} matcherName - The name of the matcher being used
|
|
51
|
+
* @param {Object} [options={}] - Optional configuration for error messages
|
|
52
|
+
* @returns {boolean} - Returns true if validation passes
|
|
53
|
+
* @throws {TypeError} - Throws if received is not a function or not a mock function
|
|
23
54
|
*/
|
|
24
55
|
function ensureReceivedIsNodeMock(received, matcherName, options = {}) {
|
|
25
56
|
if (typeof received !== 'function') {
|
|
@@ -45,11 +76,11 @@ function ensureReceivedIsNodeMock(received, matcherName, options = {}) {
|
|
|
45
76
|
|
|
46
77
|
/**
|
|
47
78
|
* Factory function to create a matcher object
|
|
48
|
-
* @param {string} matcherName
|
|
49
|
-
* @param {Object} options
|
|
50
|
-
* @param {boolean} options.isNot
|
|
51
|
-
* @param {boolean} options.promise
|
|
52
|
-
* @returns {Object}
|
|
79
|
+
* @param {string} matcherName - The name of the matcher
|
|
80
|
+
* @param {Object} [options={}] - Optional configuration
|
|
81
|
+
* @param {boolean} [options.isNot] - Whether this is a negated matcher
|
|
82
|
+
* @param {boolean} [options.promise] - Whether this is a promise matcher
|
|
83
|
+
* @returns {Object} - An object containing matcherName, options, and receivedText
|
|
53
84
|
*/
|
|
54
85
|
function matcherFactory(matcherName, { isNot, promise } = {}) {
|
|
55
86
|
return {
|
|
@@ -64,9 +95,11 @@ function matcherFactory(matcherName, { isNot, promise } = {}) {
|
|
|
64
95
|
}
|
|
65
96
|
|
|
66
97
|
/**
|
|
67
|
-
*
|
|
68
|
-
*
|
|
69
|
-
*
|
|
98
|
+
* Matcher to verify that a mock function was called at least once
|
|
99
|
+
* @param {Function} receivedMethod - The mock function to check
|
|
100
|
+
* @param {...any} args - Should not be provided (will cause an error if present)
|
|
101
|
+
* @returns {Object} - An object with pass and message properties
|
|
102
|
+
* @see https://jestjs.io/docs/expect#tohavebeencalled
|
|
70
103
|
*/
|
|
71
104
|
function toHaveBeenCalled(receivedMethod, ...args) {
|
|
72
105
|
const { matcherName, options, receivedText } = matcherFactory(
|
|
@@ -74,46 +107,37 @@ function toHaveBeenCalled(receivedMethod, ...args) {
|
|
|
74
107
|
this
|
|
75
108
|
);
|
|
76
109
|
|
|
77
|
-
|
|
78
|
-
let message = `\n${matcherHint(
|
|
79
|
-
matcherName,
|
|
80
|
-
receivedText,
|
|
81
|
-
'',
|
|
82
|
-
options
|
|
83
|
-
)}\n\n`;
|
|
84
|
-
let pass = false;
|
|
110
|
+
ensureReceivedIsNodeMock(receivedMethod, matcherName, options);
|
|
85
111
|
|
|
86
|
-
|
|
87
|
-
message += `Matcher error: this matcher must not have an expected argument
|
|
88
|
-
\nExpected has type: ${typeof args[0]}\nExpected has value: ${EXPECTED_COLOR(
|
|
89
|
-
args[0]
|
|
90
|
-
)}\n`;
|
|
91
|
-
} else {
|
|
92
|
-
pass = receivedMethod.mock.calls.length > 0;
|
|
93
|
-
if (pass) {
|
|
94
|
-
message += `Expected number of calls: ${EXPECTED_COLOR(
|
|
95
|
-
'0'
|
|
96
|
-
)}\nReceived number of calls: ${RECEIVED_COLOR(
|
|
97
|
-
receivedMethod.mock.calls.length
|
|
98
|
-
)}\n`;
|
|
99
|
-
} else {
|
|
100
|
-
message += `Expected number of calls: >= ${EXPECTED_COLOR(
|
|
101
|
-
'1'
|
|
102
|
-
)}\nReceived number of calls: ${RECEIVED_COLOR('0')}\n`;
|
|
103
|
-
}
|
|
104
|
-
}
|
|
112
|
+
const hint = `\n${matcherHint(matcherName, receivedText, '', options)}\n\n`;
|
|
105
113
|
|
|
114
|
+
if (args.length > 0) {
|
|
106
115
|
return {
|
|
107
|
-
pass,
|
|
108
|
-
message: () =>
|
|
116
|
+
pass: false,
|
|
117
|
+
message: () =>
|
|
118
|
+
`${hint}Matcher error: this matcher must not have an expected argument\n` +
|
|
119
|
+
`Expected has type: ${typeof args[0]}\nExpected has value: ${EXPECTED_COLOR(args[0])}\n`,
|
|
109
120
|
};
|
|
110
121
|
}
|
|
122
|
+
|
|
123
|
+
const pass = receivedMethod.mock.calls.length > 0;
|
|
124
|
+
const callsCount = receivedMethod.mock.calls.length;
|
|
125
|
+
const message = pass
|
|
126
|
+
? `Expected number of calls: ${EXPECTED_COLOR('0')}\nReceived number of calls: ${RECEIVED_COLOR(callsCount)}\n`
|
|
127
|
+
: `Expected number of calls: >= ${EXPECTED_COLOR('1')}\nReceived number of calls: ${RECEIVED_COLOR('0')}\n`;
|
|
128
|
+
|
|
129
|
+
return {
|
|
130
|
+
pass,
|
|
131
|
+
message: () => hint + message,
|
|
132
|
+
};
|
|
111
133
|
}
|
|
112
134
|
|
|
113
135
|
/**
|
|
114
|
-
*
|
|
115
|
-
*
|
|
116
|
-
*
|
|
136
|
+
* Matcher to verify that a mock function was called an exact number of times
|
|
137
|
+
* @param {Function} receivedMethod - The mock function to check
|
|
138
|
+
* @param {number} expected - The expected number of calls
|
|
139
|
+
* @returns {Object} - An object with pass and message properties
|
|
140
|
+
* @see https://jestjs.io/docs/expect#tohavebeencalledtimesnumber
|
|
117
141
|
*/
|
|
118
142
|
function toHaveBeenCalledTimes(receivedMethod, expected) {
|
|
119
143
|
const { matcherName, options, receivedText } = matcherFactory(
|
|
@@ -147,9 +171,11 @@ function toHaveBeenCalledTimes(receivedMethod, expected) {
|
|
|
147
171
|
}
|
|
148
172
|
|
|
149
173
|
/**
|
|
150
|
-
*
|
|
151
|
-
*
|
|
152
|
-
*
|
|
174
|
+
* Matcher to verify that a mock function was called with specific arguments at least once
|
|
175
|
+
* @param {Function} receivedMethod - The mock function to check
|
|
176
|
+
* @param {...any} args - The expected arguments
|
|
177
|
+
* @returns {Object} - An object with pass and message properties
|
|
178
|
+
* @see https://jestjs.io/docs/expect#tohavebeencalledwitharg1-arg2-
|
|
153
179
|
*/
|
|
154
180
|
function toHaveBeenCalledWith(receivedMethod, ...args) {
|
|
155
181
|
const { matcherName, options, receivedText } = matcherFactory(
|
|
@@ -157,77 +183,41 @@ function toHaveBeenCalledWith(receivedMethod, ...args) {
|
|
|
157
183
|
this
|
|
158
184
|
);
|
|
159
185
|
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
args.every((arg, index) => {
|
|
180
|
-
try {
|
|
181
|
-
expect(call.arguments[index]).toEqual(arg);
|
|
182
|
-
return true;
|
|
183
|
-
} catch (_) {
|
|
184
|
-
return false;
|
|
185
|
-
}
|
|
186
|
-
})
|
|
187
|
-
);
|
|
188
|
-
});
|
|
189
|
-
|
|
190
|
-
message = `Expected: ${pass ? 'not ' : ''}`;
|
|
191
|
-
|
|
192
|
-
if (argsCount === 0) {
|
|
193
|
-
message += `called with 0 arguments`;
|
|
194
|
-
} else {
|
|
195
|
-
message += `${args.map(arg => printExpected(arg)).join(', ')}`;
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
message += `\n\nReceived\n${receivedArgs.reduce(
|
|
199
|
-
(receivedText, args, index) =>
|
|
200
|
-
(receivedText +=
|
|
201
|
-
args.length === 0
|
|
202
|
-
? '\t' + index + ': called with 0 arguments\n'
|
|
203
|
-
: '\t' +
|
|
204
|
-
index +
|
|
205
|
-
': ' +
|
|
206
|
-
args.map(arg => printReceived(arg)).join(', ') +
|
|
207
|
-
'\n'),
|
|
208
|
-
''
|
|
209
|
-
)}`;
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
return {
|
|
213
|
-
pass,
|
|
214
|
-
message: () =>
|
|
215
|
-
`\n${matcherHint(
|
|
216
|
-
matcherName,
|
|
217
|
-
receivedText,
|
|
218
|
-
'...expected',
|
|
219
|
-
options
|
|
220
|
-
)}\n\n${message}\n\nNumber of calls: ${RECEIVED_COLOR(
|
|
221
|
-
receivedMethod.mock.calls.length
|
|
222
|
-
)}\n`,
|
|
223
|
-
};
|
|
186
|
+
ensureReceivedIsNodeMock(receivedMethod, matcherName, options);
|
|
187
|
+
|
|
188
|
+
const calls = receivedMethod.mock.calls;
|
|
189
|
+
const pass = calls.some(call => argumentsMatch(call.arguments, args));
|
|
190
|
+
|
|
191
|
+
const expectedMsg = `Expected: ${pass ? 'not ' : ''}${formatExpectedArgs(args)}`;
|
|
192
|
+
|
|
193
|
+
let receivedMsg = '';
|
|
194
|
+
if (calls.length === 0) {
|
|
195
|
+
receivedMsg = 'But the function was not called';
|
|
196
|
+
} else {
|
|
197
|
+
receivedMsg = `\n\nReceived\n${calls
|
|
198
|
+
.map((call, index) => {
|
|
199
|
+
const callArgs = call.arguments;
|
|
200
|
+
return callArgs.length === 0
|
|
201
|
+
? `\t${index}: called with 0 arguments`
|
|
202
|
+
: `\t${index}: ${callArgs.map(arg => printReceived(arg)).join(', ')}`;
|
|
203
|
+
})
|
|
204
|
+
.join('\n')}`;
|
|
224
205
|
}
|
|
206
|
+
|
|
207
|
+
return {
|
|
208
|
+
pass,
|
|
209
|
+
message: () =>
|
|
210
|
+
`\n${matcherHint(matcherName, receivedText, '...expected', options)}\n\n` +
|
|
211
|
+
`${expectedMsg}${receivedMsg}\n\nNumber of calls: ${RECEIVED_COLOR(calls.length)}\n`,
|
|
212
|
+
};
|
|
225
213
|
}
|
|
226
214
|
|
|
227
215
|
/**
|
|
228
|
-
*
|
|
229
|
-
*
|
|
230
|
-
*
|
|
216
|
+
* Matcher to verify that a mock function was last called with specific arguments
|
|
217
|
+
* @param {Function} receivedMethod - The mock function to check
|
|
218
|
+
* @param {...any} args - The expected arguments
|
|
219
|
+
* @returns {Object} - An object with pass and message properties
|
|
220
|
+
* @see https://jestjs.io/docs/expect#tohavebeenlastcalledwitharg1-arg2-
|
|
231
221
|
*/
|
|
232
222
|
function toHaveBeenLastCalledWith(receivedMethod, ...args) {
|
|
233
223
|
const { matcherName, options, receivedText } = matcherFactory(
|
|
@@ -235,67 +225,44 @@ function toHaveBeenLastCalledWith(receivedMethod, ...args) {
|
|
|
235
225
|
this
|
|
236
226
|
);
|
|
237
227
|
|
|
238
|
-
|
|
239
|
-
const argsCount = args.length;
|
|
240
|
-
const receivedArgs = [];
|
|
241
|
-
let pass = false;
|
|
242
|
-
let message = '';
|
|
243
|
-
const callsCount = receivedMethod.mock.calls.length;
|
|
244
|
-
|
|
245
|
-
if (!callsCount) {
|
|
246
|
-
pass = false;
|
|
247
|
-
message = `Expected: `;
|
|
248
|
-
if (argsCount === 0) {
|
|
249
|
-
message += `called with 0 arguments`;
|
|
250
|
-
} else {
|
|
251
|
-
message += `${args.map(arg => printExpected(arg)).join(', ')}`;
|
|
252
|
-
}
|
|
253
|
-
} else {
|
|
254
|
-
const lastCall = receivedMethod.mock.calls[callsCount - 1];
|
|
255
|
-
receivedArgs.push(lastCall.arguments);
|
|
256
|
-
pass =
|
|
257
|
-
argsCount &&
|
|
258
|
-
args.every((arg, index) => {
|
|
259
|
-
try {
|
|
260
|
-
expect(lastCall.arguments[index]).toEqual(arg);
|
|
261
|
-
return true;
|
|
262
|
-
} catch (_) {
|
|
263
|
-
return false;
|
|
264
|
-
}
|
|
265
|
-
});
|
|
266
|
-
|
|
267
|
-
message = `Expected: ${pass ? 'not ' : ''}`;
|
|
268
|
-
|
|
269
|
-
if (argsCount === 0) {
|
|
270
|
-
message += `called with 0 arguments`;
|
|
271
|
-
} else {
|
|
272
|
-
message += `${args.map(arg => printExpected(arg)).join(', ')}`;
|
|
273
|
-
}
|
|
274
|
-
|
|
275
|
-
message += `\n\n\nReceived: ${receivedArgs.map(args =>
|
|
276
|
-
args.map(arg => printReceived(arg)).join(', ')
|
|
277
|
-
)}`;
|
|
278
|
-
}
|
|
228
|
+
ensureReceivedIsNodeMock(receivedMethod, matcherName, options);
|
|
279
229
|
|
|
230
|
+
const calls = receivedMethod.mock.calls;
|
|
231
|
+
const callsCount = calls.length;
|
|
232
|
+
|
|
233
|
+
if (callsCount === 0) {
|
|
280
234
|
return {
|
|
281
|
-
pass,
|
|
235
|
+
pass: false,
|
|
282
236
|
message: () =>
|
|
283
|
-
`${matcherHint(
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
'...expected',
|
|
287
|
-
options
|
|
288
|
-
)}\n\n${message}\n\nNumber of calls: ${RECEIVED_COLOR(
|
|
289
|
-
receivedMethod.mock.calls.length
|
|
290
|
-
)}\n`,
|
|
237
|
+
`${matcherHint(matcherName, receivedText, '...expected', options)}\n\n` +
|
|
238
|
+
`Expected: ${formatExpectedArgs(args)}\n` +
|
|
239
|
+
`But the function was not called\n\nNumber of calls: ${RECEIVED_COLOR(0)}\n`,
|
|
291
240
|
};
|
|
292
241
|
}
|
|
242
|
+
|
|
243
|
+
const lastCall = calls[callsCount - 1];
|
|
244
|
+
const pass = argumentsMatch(lastCall.arguments, args);
|
|
245
|
+
const receivedArgs = lastCall.arguments
|
|
246
|
+
.map(arg => printReceived(arg))
|
|
247
|
+
.join(', ');
|
|
248
|
+
|
|
249
|
+
return {
|
|
250
|
+
pass,
|
|
251
|
+
message: () =>
|
|
252
|
+
`${matcherHint(matcherName, receivedText, '...expected', options)}\n\n` +
|
|
253
|
+
`Expected: ${pass ? 'not ' : ''}${formatExpectedArgs(args)}\n\n\n` +
|
|
254
|
+
`Received: ${receivedArgs || 'called with 0 arguments'}\n\n` +
|
|
255
|
+
`Number of calls: ${RECEIVED_COLOR(callsCount)}\n`,
|
|
256
|
+
};
|
|
293
257
|
}
|
|
294
258
|
|
|
295
259
|
/**
|
|
296
|
-
*
|
|
297
|
-
*
|
|
298
|
-
*
|
|
260
|
+
* Matcher to verify that a mock function was called with specific arguments on the nth call
|
|
261
|
+
* @param {Function} receivedMethod - The mock function to check
|
|
262
|
+
* @param {number} nthCallIndex - The call number to check (1-indexed)
|
|
263
|
+
* @param {...any} args - The expected arguments
|
|
264
|
+
* @returns {Object} - An object with pass and message properties
|
|
265
|
+
* @see https://jestjs.io/docs/expect#tohavebeennthcalledwithnthcall-arg1-arg2-
|
|
299
266
|
*/
|
|
300
267
|
function toHaveBeenNthCalledWith(receivedMethod, nthCallIndex, ...args) {
|
|
301
268
|
const { matcherName, options, receivedText } = matcherFactory(
|
|
@@ -303,71 +270,45 @@ function toHaveBeenNthCalledWith(receivedMethod, nthCallIndex, ...args) {
|
|
|
303
270
|
this
|
|
304
271
|
);
|
|
305
272
|
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
let message = `n: ${nthCallIndex}\n`;
|
|
311
|
-
const callsCount = receivedMethod.mock.calls.length;
|
|
312
|
-
|
|
313
|
-
if (!callsCount || nthCallIndex > callsCount) {
|
|
314
|
-
pass = false;
|
|
315
|
-
message += `Expected: `;
|
|
316
|
-
if (argsCount === 0) {
|
|
317
|
-
message += `called with 0 arguments`;
|
|
318
|
-
} else {
|
|
319
|
-
message += `${args.map(arg => printExpected(arg)).join(', ')}`;
|
|
320
|
-
}
|
|
321
|
-
} else {
|
|
322
|
-
const nthCall = receivedMethod.mock.calls[nthCallIndex - 1];
|
|
323
|
-
receivedArgs.push(nthCall.arguments);
|
|
324
|
-
pass =
|
|
325
|
-
argsCount &&
|
|
326
|
-
args.every((arg, index) => {
|
|
327
|
-
try {
|
|
328
|
-
expect(nthCall.arguments[index]).toEqual(arg);
|
|
329
|
-
return true;
|
|
330
|
-
} catch (_) {
|
|
331
|
-
return false;
|
|
332
|
-
}
|
|
333
|
-
});
|
|
334
|
-
|
|
335
|
-
message += `Expected: ${pass ? 'not ' : ''}`;
|
|
336
|
-
|
|
337
|
-
if (argsCount === 0) {
|
|
338
|
-
message += `called with 0 arguments`;
|
|
339
|
-
} else {
|
|
340
|
-
message += `${args.map(arg => printExpected(arg)).join(', ')}`;
|
|
341
|
-
}
|
|
342
|
-
|
|
343
|
-
message += `\nReceived: ${
|
|
344
|
-
receivedArgs.length
|
|
345
|
-
? receivedArgs.map(args =>
|
|
346
|
-
args.map(arg => printReceived(arg)).join(', ')
|
|
347
|
-
)
|
|
348
|
-
: 'called with 0 arguments'
|
|
349
|
-
}`;
|
|
350
|
-
}
|
|
273
|
+
ensureReceivedIsNodeMock(receivedMethod, matcherName, options);
|
|
274
|
+
|
|
275
|
+
const calls = receivedMethod.mock.calls;
|
|
276
|
+
const callsCount = calls.length;
|
|
351
277
|
|
|
278
|
+
if (nthCallIndex < 1 || nthCallIndex > callsCount) {
|
|
352
279
|
return {
|
|
353
|
-
pass,
|
|
280
|
+
pass: false,
|
|
354
281
|
message: () =>
|
|
355
|
-
`${matcherHint(
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
)}\n\n${message}\n\nNumber of calls: ${RECEIVED_COLOR(
|
|
361
|
-
receivedMethod.mock.calls.length
|
|
362
|
-
)}\n`,
|
|
282
|
+
`${matcherHint(matcherName, receivedText, '...expected', options)}\n\n` +
|
|
283
|
+
`n: ${nthCallIndex}\n` +
|
|
284
|
+
`Expected: ${formatExpectedArgs(args)}\n` +
|
|
285
|
+
`But the function was ${callsCount === 0 ? 'not called' : `only called ${callsCount} time(s)`}\n\n` +
|
|
286
|
+
`Number of calls: ${RECEIVED_COLOR(callsCount)}\n`,
|
|
363
287
|
};
|
|
364
288
|
}
|
|
289
|
+
|
|
290
|
+
const nthCall = calls[nthCallIndex - 1];
|
|
291
|
+
const pass = argumentsMatch(nthCall.arguments, args);
|
|
292
|
+
const receivedArgs = nthCall.arguments
|
|
293
|
+
.map(arg => printReceived(arg))
|
|
294
|
+
.join(', ');
|
|
295
|
+
|
|
296
|
+
return {
|
|
297
|
+
pass,
|
|
298
|
+
message: () =>
|
|
299
|
+
`${matcherHint(matcherName, receivedText, '...expected', options)}\n\n` +
|
|
300
|
+
`n: ${nthCallIndex}\n` +
|
|
301
|
+
`Expected: ${pass ? 'not ' : ''}${formatExpectedArgs(args)}\n` +
|
|
302
|
+
`Received: ${receivedArgs || 'called with 0 arguments'}\n\n` +
|
|
303
|
+
`Number of calls: ${RECEIVED_COLOR(callsCount)}\n`,
|
|
304
|
+
};
|
|
365
305
|
}
|
|
366
306
|
|
|
367
307
|
/**
|
|
368
|
-
*
|
|
369
|
-
*
|
|
370
|
-
*
|
|
308
|
+
* Matcher to verify that a mock function successfully returned (without error) at least once
|
|
309
|
+
* @param {Function} receivedMethod - The mock function to check
|
|
310
|
+
* @returns {Object} - An object with pass and message properties
|
|
311
|
+
* @see https://jestjs.io/docs/expect#tohavereturned
|
|
371
312
|
*/
|
|
372
313
|
function toHaveReturned(receivedMethod) {
|
|
373
314
|
const { matcherName, options, receivedText } = matcherFactory(
|
|
@@ -405,18 +346,21 @@ function toHaveReturned(receivedMethod) {
|
|
|
405
346
|
}
|
|
406
347
|
|
|
407
348
|
/**
|
|
408
|
-
*
|
|
409
|
-
*
|
|
410
|
-
*
|
|
349
|
+
* Alias for toHaveReturned - verifies that a mock function successfully returned at least once
|
|
350
|
+
* @param {Function} receivedMethod - The mock function to check
|
|
351
|
+
* @returns {Object} - An object with pass and message properties
|
|
352
|
+
* @see https://jestjs.io/docs/expect#tohavereturned
|
|
411
353
|
*/
|
|
412
354
|
function toReturn(receivedMethod) {
|
|
413
355
|
return toHaveReturned(receivedMethod);
|
|
414
356
|
}
|
|
415
357
|
|
|
416
358
|
/**
|
|
417
|
-
*
|
|
418
|
-
*
|
|
419
|
-
*
|
|
359
|
+
* Matcher to verify that a mock function successfully returned a specific number of times
|
|
360
|
+
* @param {Function} receivedMethod - The mock function to check
|
|
361
|
+
* @param {number} times - The expected number of successful returns
|
|
362
|
+
* @returns {Object} - An object with pass and message properties
|
|
363
|
+
* @see https://jestjs.io/docs/expect#tohavereturnedtimesnumber
|
|
420
364
|
*/
|
|
421
365
|
function toHaveReturnedTimes(receivedMethod, times) {
|
|
422
366
|
const { matcherName, options, receivedText } = matcherFactory(
|
|
@@ -424,40 +368,28 @@ function toHaveReturnedTimes(receivedMethod, times) {
|
|
|
424
368
|
this
|
|
425
369
|
);
|
|
426
370
|
|
|
427
|
-
|
|
428
|
-
const noErrorCalls = receivedMethod.mock.calls.filter(
|
|
429
|
-
call => call.error === undefined
|
|
430
|
-
);
|
|
431
|
-
const pass = noErrorCalls.length === times;
|
|
432
|
-
|
|
433
|
-
let message = `\n${matcherHint(
|
|
434
|
-
matcherName,
|
|
435
|
-
receivedText,
|
|
436
|
-
'expected',
|
|
437
|
-
options
|
|
438
|
-
)}\n\n`;
|
|
371
|
+
ensureReceivedIsNodeMock(receivedMethod, matcherName, options);
|
|
439
372
|
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
} else {
|
|
445
|
-
message += `Expected: ${printExpected(times)}\nReceived: ${printReceived(
|
|
446
|
-
noErrorCalls.length
|
|
447
|
-
)}`;
|
|
448
|
-
}
|
|
373
|
+
const successfulReturns = receivedMethod.mock.calls.filter(
|
|
374
|
+
call => call.error === undefined
|
|
375
|
+
).length;
|
|
376
|
+
const pass = successfulReturns === times;
|
|
449
377
|
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
378
|
+
return {
|
|
379
|
+
pass,
|
|
380
|
+
message: () =>
|
|
381
|
+
`\n${matcherHint(matcherName, receivedText, 'expected', options)}\n\n` +
|
|
382
|
+
`Expected: ${pass ? 'not ' : ''}${printExpected(times)}\n` +
|
|
383
|
+
`Received: ${printReceived(successfulReturns)}`,
|
|
384
|
+
};
|
|
455
385
|
}
|
|
456
386
|
|
|
457
387
|
/**
|
|
458
|
-
*
|
|
459
|
-
*
|
|
460
|
-
*
|
|
388
|
+
* Matcher to verify that a mock function returned a specific value at least once
|
|
389
|
+
* @param {Function} receivedMethod - The mock function to check
|
|
390
|
+
* @param {any} expected - The expected return value
|
|
391
|
+
* @returns {Object} - An object with pass and message properties
|
|
392
|
+
* @see https://jestjs.io/docs/expect#tohavereturnedwithvalue
|
|
461
393
|
*/
|
|
462
394
|
function toHaveReturnedWith(receivedMethod, expected) {
|
|
463
395
|
const { matcherName, options, receivedText } = matcherFactory(
|
|
@@ -465,43 +397,34 @@ function toHaveReturnedWith(receivedMethod, expected) {
|
|
|
465
397
|
this
|
|
466
398
|
);
|
|
467
399
|
|
|
468
|
-
|
|
469
|
-
const pass = receivedMethod.mock.calls.some(
|
|
470
|
-
call => call.result === expected
|
|
471
|
-
);
|
|
400
|
+
ensureReceivedIsNodeMock(receivedMethod, matcherName, options);
|
|
472
401
|
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
if (pass) {
|
|
481
|
-
message += `Expected: ${printExpected(
|
|
482
|
-
expected
|
|
483
|
-
)}\nReceived: ${printReceived(
|
|
484
|
-
receivedMethod.mock.calls.map(call => call.result)
|
|
485
|
-
)}`;
|
|
486
|
-
} else {
|
|
487
|
-
message += `Expected: ${printExpected(
|
|
488
|
-
expected
|
|
489
|
-
)}\nReceived: ${printReceived(
|
|
490
|
-
receivedMethod.mock.calls.map(call => call.result)
|
|
491
|
-
)}`;
|
|
402
|
+
const pass = receivedMethod.mock.calls.some(call => {
|
|
403
|
+
try {
|
|
404
|
+
expect(call.result).toEqual(expected);
|
|
405
|
+
return true;
|
|
406
|
+
} catch (_) {
|
|
407
|
+
return false;
|
|
492
408
|
}
|
|
409
|
+
});
|
|
493
410
|
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
411
|
+
const allResults = receivedMethod.mock.calls.map(call => call.result);
|
|
412
|
+
|
|
413
|
+
return {
|
|
414
|
+
pass,
|
|
415
|
+
message: () =>
|
|
416
|
+
`\n${matcherHint(matcherName, receivedText, 'expected', options)}\n\n` +
|
|
417
|
+
`Expected: ${pass ? 'not ' : ''}${printExpected(expected)}\n` +
|
|
418
|
+
`Received: ${printReceived(allResults)}`,
|
|
419
|
+
};
|
|
499
420
|
}
|
|
500
421
|
|
|
501
422
|
/**
|
|
502
|
-
*
|
|
503
|
-
*
|
|
504
|
-
*
|
|
423
|
+
* Matcher to verify that a mock function's last return value matches the expected value
|
|
424
|
+
* @param {Function} receivedMethod - The mock function to check
|
|
425
|
+
* @param {any} expected - The expected return value
|
|
426
|
+
* @returns {Object} - An object with pass and message properties
|
|
427
|
+
* @see https://jestjs.io/docs/expect#tohavelastreturnedwithvalue
|
|
505
428
|
*/
|
|
506
429
|
function toHaveLastReturnedWith(receivedMethod, expected) {
|
|
507
430
|
const { matcherName, options, receivedText } = matcherFactory(
|
|
@@ -509,39 +432,42 @@ function toHaveLastReturnedWith(receivedMethod, expected) {
|
|
|
509
432
|
this
|
|
510
433
|
);
|
|
511
434
|
|
|
512
|
-
|
|
513
|
-
const lastCall =
|
|
514
|
-
receivedMethod.mock.calls[receivedMethod.mock.calls.length - 1];
|
|
515
|
-
const pass = lastCall.result === expected;
|
|
516
|
-
|
|
517
|
-
let message = `\n${matcherHint(
|
|
518
|
-
matcherName,
|
|
519
|
-
receivedText,
|
|
520
|
-
'expected',
|
|
521
|
-
options
|
|
522
|
-
)}\n\n`;
|
|
523
|
-
|
|
524
|
-
if (pass) {
|
|
525
|
-
message += `Expected: ${printExpected(
|
|
526
|
-
expected
|
|
527
|
-
)}\nReceived: ${printReceived(lastCall.result)}`;
|
|
528
|
-
} else {
|
|
529
|
-
message += `Expected: ${printExpected(
|
|
530
|
-
expected
|
|
531
|
-
)}\nReceived: ${printReceived(lastCall.result)}`;
|
|
532
|
-
}
|
|
435
|
+
ensureReceivedIsNodeMock(receivedMethod, matcherName, options);
|
|
533
436
|
|
|
437
|
+
const calls = receivedMethod.mock.calls;
|
|
438
|
+
if (calls.length === 0) {
|
|
534
439
|
return {
|
|
535
|
-
pass,
|
|
536
|
-
message: () =>
|
|
440
|
+
pass: false,
|
|
441
|
+
message: () =>
|
|
442
|
+
`\n${matcherHint(matcherName, receivedText, 'expected', options)}\n\nExpected: ${printExpected(expected)}\nBut the function was not called`,
|
|
537
443
|
};
|
|
538
444
|
}
|
|
445
|
+
|
|
446
|
+
const lastCall = calls[calls.length - 1];
|
|
447
|
+
let pass = false;
|
|
448
|
+
try {
|
|
449
|
+
expect(lastCall.result).toEqual(expected);
|
|
450
|
+
pass = true;
|
|
451
|
+
} catch (_) {
|
|
452
|
+
pass = false;
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
return {
|
|
456
|
+
pass,
|
|
457
|
+
message: () =>
|
|
458
|
+
`\n${matcherHint(matcherName, receivedText, 'expected', options)}\n\n` +
|
|
459
|
+
`Expected: ${pass ? 'not ' : ''}${printExpected(expected)}\n` +
|
|
460
|
+
`Received: ${printReceived(lastCall.result)}`,
|
|
461
|
+
};
|
|
539
462
|
}
|
|
540
463
|
|
|
541
464
|
/**
|
|
542
|
-
*
|
|
543
|
-
*
|
|
544
|
-
*
|
|
465
|
+
* Matcher to verify that a mock function's nth return value matches the expected value
|
|
466
|
+
* @param {Function} receivedMethod - The mock function to check
|
|
467
|
+
* @param {number} nthCall - The call number to check (1-indexed)
|
|
468
|
+
* @param {any} expected - The expected return value
|
|
469
|
+
* @returns {Object} - An object with pass and message properties
|
|
470
|
+
* @see https://jestjs.io/docs/expect#tohaventhreturnedwithnthcall-value
|
|
545
471
|
*/
|
|
546
472
|
function toHaveNthReturnedWith(receivedMethod, nthCall, expected) {
|
|
547
473
|
const { matcherName, options, receivedText } = matcherFactory(
|
|
@@ -549,32 +475,37 @@ function toHaveNthReturnedWith(receivedMethod, nthCall, expected) {
|
|
|
549
475
|
this
|
|
550
476
|
);
|
|
551
477
|
|
|
552
|
-
|
|
553
|
-
const nthCallResult = receivedMethod.mock.calls[nthCall - 1].result;
|
|
554
|
-
const pass = nthCallResult === expected;
|
|
555
|
-
|
|
556
|
-
let message = `\n${matcherHint(
|
|
557
|
-
matcherName,
|
|
558
|
-
receivedText,
|
|
559
|
-
'expected',
|
|
560
|
-
options
|
|
561
|
-
)}\n\n`;
|
|
562
|
-
|
|
563
|
-
if (pass) {
|
|
564
|
-
message += `Expected: ${printExpected(
|
|
565
|
-
expected
|
|
566
|
-
)}\nReceived: ${printReceived(nthCallResult)}`;
|
|
567
|
-
} else {
|
|
568
|
-
message += `Expected: ${printExpected(
|
|
569
|
-
expected
|
|
570
|
-
)}\nReceived: ${printReceived(nthCallResult)}`;
|
|
571
|
-
}
|
|
478
|
+
ensureReceivedIsNodeMock(receivedMethod, matcherName, options);
|
|
572
479
|
|
|
480
|
+
const calls = receivedMethod.mock.calls;
|
|
481
|
+
if (nthCall < 1 || nthCall > calls.length) {
|
|
573
482
|
return {
|
|
574
|
-
pass,
|
|
575
|
-
message: () =>
|
|
483
|
+
pass: false,
|
|
484
|
+
message: () =>
|
|
485
|
+
`\n${matcherHint(matcherName, receivedText, 'expected', options)}\n\n` +
|
|
486
|
+
`n: ${nthCall}\n` +
|
|
487
|
+
`Expected: ${printExpected(expected)}\n` +
|
|
488
|
+
`But the function was ${calls.length === 0 ? 'not called' : `only called ${calls.length} time(s)`}`,
|
|
576
489
|
};
|
|
577
490
|
}
|
|
491
|
+
|
|
492
|
+
const nthCallResult = calls[nthCall - 1].result;
|
|
493
|
+
let pass = false;
|
|
494
|
+
try {
|
|
495
|
+
expect(nthCallResult).toEqual(expected);
|
|
496
|
+
pass = true;
|
|
497
|
+
} catch (_) {
|
|
498
|
+
pass = false;
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
return {
|
|
502
|
+
pass,
|
|
503
|
+
message: () =>
|
|
504
|
+
`\n${matcherHint(matcherName, receivedText, 'expected', options)}\n\n` +
|
|
505
|
+
`n: ${nthCall}\n` +
|
|
506
|
+
`Expected: ${pass ? 'not ' : ''}${printExpected(expected)}\n` +
|
|
507
|
+
`Received: ${printReceived(nthCallResult)}`,
|
|
508
|
+
};
|
|
578
509
|
}
|
|
579
510
|
|
|
580
511
|
export {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "expect-matcher-node-mock",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.3",
|
|
4
4
|
"description": "Jest-like expect matchers for native Node.js test runner mock objects. Provides toHaveBeenCalled, toHaveBeenCalledWith, toHaveReturned and more.",
|
|
5
5
|
"main": "lib/index.mjs",
|
|
6
6
|
"type": "module",
|
|
@@ -39,19 +39,18 @@
|
|
|
39
39
|
"license": "MIT",
|
|
40
40
|
"author": "Crysa Drak <cd@l33t.cz>",
|
|
41
41
|
"scripts": {
|
|
42
|
-
"lint": "
|
|
42
|
+
"lint": "biome check .",
|
|
43
|
+
"lint:fix": "biome check --write .",
|
|
44
|
+
"format": "biome format --write .",
|
|
43
45
|
"test": "node --test --test-reporter=spec"
|
|
44
46
|
},
|
|
45
47
|
"devDependencies": {
|
|
46
|
-
"
|
|
47
|
-
"eslint-config-prettier": "^8.5.0",
|
|
48
|
-
"eslint-plugin-import": "^2.27.5",
|
|
49
|
-
"eslint-plugin-prettier": "^4.2.1",
|
|
50
|
-
"prettier": "^2.8.4",
|
|
48
|
+
"@biomejs/biome": "^1.9.4",
|
|
51
49
|
"strip-ansi": "7.1.0"
|
|
52
50
|
},
|
|
53
|
-
"
|
|
54
|
-
"
|
|
55
|
-
"
|
|
51
|
+
"peerDependencies": {
|
|
52
|
+
"chalk": ">=4.0.0",
|
|
53
|
+
"expect": ">=29.0.0",
|
|
54
|
+
"jest-matcher-utils": ">=29.0.0"
|
|
56
55
|
}
|
|
57
56
|
}
|