expect-matcher-node-mock 1.0.0 → 1.1.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
@@ -21,6 +21,18 @@ https://jestjs.io/docs/expect#tohavebeenlastcalledwitharg1-arg2-
21
21
  ### toHaveBeenNthCalledWith
22
22
  https://jestjs.io/docs/expect#tohavebeennthcalledwithnthcall-arg1-arg2-
23
23
 
24
- ### TODO
25
- add all toHaveReturnedXX methods
24
+ ### toHaveReturned
25
+ alias `toReturn`
26
+ https://jestjs.io/docs/expect#tohavereturned
26
27
 
28
+ ### toHaveReturnedTimes
29
+ https://jestjs.io/docs/expect#tohavereturnedtimesnumber
30
+
31
+ ### toHaveReturnedWith
32
+ https://jestjs.io/docs/expect#tohavereturnedwithvalue
33
+
34
+ ### toHaveLastReturnedWith
35
+ https://jestjs.io/docs/expect#tohavelastreturnedwithvalue
36
+
37
+ ### toHaveNthReturnedWith
38
+ https://jestjs.io/docs/expect#tohaventhreturnedwithnthcall-value
@@ -5,7 +5,7 @@ import { expect } from 'expect';
5
5
  import '../index.mjs';
6
6
 
7
7
  describe('mockMethodMatchers', () => {
8
- it('toHaveBeenCalled', () => {
8
+ it('toHaveBeenCalled - should test pass and not pass', () => {
9
9
  const method = mock.fn();
10
10
  const notCalledMethod = mock.fn();
11
11
 
@@ -15,7 +15,7 @@ describe('mockMethodMatchers', () => {
15
15
  expect(notCalledMethod).not.toHaveBeenCalled();
16
16
  });
17
17
 
18
- it('toHaveBeenCalledTimes', () => {
18
+ it('toHaveBeenCalledTimes - should test pass and not pass', () => {
19
19
  const method = mock.fn();
20
20
  const notCalledMethod = mock.fn();
21
21
 
@@ -26,7 +26,7 @@ describe('mockMethodMatchers', () => {
26
26
  expect(notCalledMethod).not.toHaveBeenCalledTimes(1);
27
27
  });
28
28
 
29
- it('toHaveBeenCalledWith', () => {
29
+ it('toHaveBeenCalledWith - should test pass and not pass', () => {
30
30
  const method = mock.fn();
31
31
 
32
32
  method('foo', 'bar');
@@ -35,7 +35,7 @@ describe('mockMethodMatchers', () => {
35
35
  expect(method).not.toHaveBeenCalledWith('bar', 'foo');
36
36
  });
37
37
 
38
- it('toHaveBeenLastCalledWith', () => {
38
+ it('toHaveBeenLastCalledWith - should test pass and not pass', () => {
39
39
  const method = mock.fn();
40
40
 
41
41
  method('foo');
@@ -45,7 +45,7 @@ describe('mockMethodMatchers', () => {
45
45
  expect(method).not.toHaveBeenLastCalledWith('foo');
46
46
  });
47
47
 
48
- it('toHaveBeenNthCalledWith', () => {
48
+ it('toHaveBeenNthCalledWith - should test pass and not pass', () => {
49
49
  const method = mock.fn();
50
50
 
51
51
  method('foo');
@@ -55,4 +55,115 @@ describe('mockMethodMatchers', () => {
55
55
  expect(method).toHaveBeenNthCalledWith(2, 'bar');
56
56
  expect(method).not.toHaveBeenNthCalledWith(1, 'bar');
57
57
  });
58
+
59
+ it('toHaveReturned - should test pass and not pass', () => {
60
+ const method = mock.fn();
61
+ const notCalledMethod = mock.fn();
62
+
63
+ method();
64
+
65
+ expect(method).toHaveReturned();
66
+ expect(notCalledMethod).not.toHaveReturned();
67
+ });
68
+
69
+ it('toHaveReturned - should not pass when mock method thorws an error', () => {
70
+ const method = mock.fn(() => {
71
+ throw new Error();
72
+ });
73
+
74
+ expect(() => {
75
+ method();
76
+ }).toThrow();
77
+
78
+ expect(method).not.toHaveReturned();
79
+ });
80
+
81
+ it('toHaveReturnedTimes - should test pass and not pass', () => {
82
+ const method = mock.fn();
83
+ const notCalledMethod = mock.fn();
84
+
85
+ method();
86
+ method();
87
+
88
+ expect(method).toHaveReturnedTimes(2);
89
+ expect(notCalledMethod).not.toHaveReturnedTimes(1);
90
+ });
91
+
92
+ it('toHaveReturnedTimes - should not pass when mock method thorws an error', () => {
93
+ const method = mock.fn(() => {
94
+ throw new Error();
95
+ });
96
+
97
+ expect(() => {
98
+ method();
99
+ }).toThrow();
100
+
101
+ expect(method).not.toHaveReturnedTimes(1);
102
+ });
103
+
104
+ it('toHaveReturnedWith - should test pass and not pass', () => {
105
+ const method = mock.fn(arg => arg);
106
+
107
+ method('foo', 'bar');
108
+
109
+ expect(method).toHaveReturnedWith('foo', 'bar');
110
+ expect(method).not.toHaveReturnedWith('bar', 'foo');
111
+ });
112
+
113
+ it('toHaveReturnedWith - should not pass when mock method thorws an error', () => {
114
+ const method = mock.fn(() => {
115
+ throw new Error();
116
+ });
117
+
118
+ expect(() => {
119
+ method();
120
+ }).toThrow();
121
+
122
+ expect(method).not.toHaveReturnedWith('foo');
123
+ });
124
+
125
+ it('toHaveLastReturnedWith - should test pass and not pass', () => {
126
+ const method = mock.fn(arg => arg);
127
+
128
+ method('foo');
129
+ method('bar');
130
+
131
+ expect(method).toHaveLastReturnedWith('bar');
132
+ expect(method).not.toHaveLastReturnedWith('foo');
133
+ });
134
+
135
+ it('toHaveLastReturnedWith - should not pass when mock method thorws an error', () => {
136
+ const method = mock.fn(() => {
137
+ throw new Error();
138
+ });
139
+
140
+ expect(() => {
141
+ method();
142
+ }).toThrow();
143
+
144
+ expect(method).not.toHaveLastReturnedWith('foo');
145
+ });
146
+
147
+ it('toHaveNthReturnedWith - should test pass and not pass', () => {
148
+ const method = mock.fn(arg => arg);
149
+
150
+ method('foo');
151
+ method('bar');
152
+
153
+ expect(method).toHaveNthReturnedWith(1, 'foo');
154
+ expect(method).toHaveNthReturnedWith(2, 'bar');
155
+ expect(method).not.toHaveNthReturnedWith(1, 'bar');
156
+ });
157
+
158
+ it('toHaveNthReturnedWith - should not pass when mock method thorws an error', () => {
159
+ const method = mock.fn(() => {
160
+ throw new Error();
161
+ });
162
+
163
+ expect(() => {
164
+ method();
165
+ }).toThrow();
166
+
167
+ expect(method).not.toHaveNthReturnedWith(1, 'foo');
168
+ });
58
169
  });
@@ -0,0 +1,276 @@
1
+ import { describe, it, mock } from 'node:test';
2
+
3
+ import { expect } from 'expect';
4
+
5
+ import {
6
+ toHaveBeenCalled,
7
+ toHaveBeenCalledTimes,
8
+ toHaveBeenCalledWith,
9
+ toHaveBeenLastCalledWith,
10
+ toHaveBeenNthCalledWith,
11
+ toReturn,
12
+ toHaveReturned,
13
+ toHaveReturnedTimes,
14
+ toHaveReturnedWith,
15
+ toHaveLastReturnedWith,
16
+ toHaveNthReturnedWith,
17
+ } from '../mockMethodMatchers.mjs';
18
+
19
+ const stripAnsi = str =>
20
+ str.replace(
21
+ /[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/g,
22
+ ''
23
+ );
24
+
25
+ describe('mockMethodMatchers return snapshots', () => {
26
+ describe('toHaveBeenCalled', () => {
27
+ it('fail', () => {
28
+ const options = {
29
+ isNot: false,
30
+ promise: false,
31
+ toHaveBeenCalled,
32
+ };
33
+
34
+ const method = mock.fn();
35
+
36
+ const result = options.toHaveBeenCalled(method);
37
+ const message = stripAnsi(result.message());
38
+
39
+ expect(result).toEqual({ message: expect.any(Function), pass: false });
40
+ expect(message).toStrictEqual(
41
+ expect.stringContaining('expect(mock.fn()).false.toHaveBeenCalled()')
42
+ );
43
+ expect(message).toStrictEqual(
44
+ expect.stringContaining('Expected number of calls: >= 1')
45
+ );
46
+ expect(message).toStrictEqual(
47
+ expect.stringContaining('Received number of calls: 0')
48
+ );
49
+ });
50
+
51
+ it('not pass', () => {
52
+ const options = {
53
+ isNot: true,
54
+ promise: false,
55
+ toHaveBeenCalled,
56
+ };
57
+ const method = mock.fn();
58
+
59
+ const result = options.toHaveBeenCalled(method);
60
+ const message = stripAnsi(result.message());
61
+
62
+ expect(result).toEqual({ message: expect.any(Function), pass: false });
63
+ expect(message).toStrictEqual(
64
+ expect.stringContaining(
65
+ 'expect(mock.fn()).false.not.toHaveBeenCalled()'
66
+ )
67
+ );
68
+ expect(message).toStrictEqual(
69
+ expect.stringContaining('Expected number of calls: >= 1')
70
+ );
71
+ expect(message).toStrictEqual(
72
+ expect.stringContaining('Received number of calls: 0')
73
+ );
74
+ });
75
+ });
76
+
77
+ describe('toHaveBeenCalledTimes', () => {
78
+ it('fail', () => {
79
+ const options = {
80
+ isNot: false,
81
+ promise: false,
82
+ toHaveBeenCalledTimes,
83
+ };
84
+
85
+ const method = mock.fn();
86
+
87
+ const result = options.toHaveBeenCalledTimes(method, 1);
88
+ const message = stripAnsi(result.message());
89
+
90
+ expect(result).toEqual({ message: expect.any(Function), pass: false });
91
+ expect(message).toStrictEqual(
92
+ expect.stringContaining(
93
+ 'expect(mock.fn()).false.toHaveBeenCalledTimes(expected)'
94
+ )
95
+ );
96
+ expect(message).toStrictEqual(
97
+ expect.stringContaining('Expected number of calls: 1')
98
+ );
99
+ expect(message).toStrictEqual(
100
+ expect.stringContaining('Received number of calls: 0')
101
+ );
102
+ });
103
+
104
+ it('not pass', () => {
105
+ const options = {
106
+ isNot: true,
107
+ promise: false,
108
+ toHaveBeenCalledTimes,
109
+ };
110
+ const method = mock.fn();
111
+
112
+ const result = options.toHaveBeenCalledTimes(method, 1);
113
+ const message = stripAnsi(result.message());
114
+
115
+ expect(result).toEqual({ message: expect.any(Function), pass: false });
116
+ expect(message).toStrictEqual(
117
+ expect.stringContaining(
118
+ 'expect(mock.fn()).false.not.toHaveBeenCalledTimes(expected)'
119
+ )
120
+ );
121
+ expect(message).toStrictEqual(
122
+ expect.stringContaining('Expected number of calls: 1')
123
+ );
124
+ expect(message).toStrictEqual(
125
+ expect.stringContaining('Received number of calls: 0')
126
+ );
127
+ });
128
+ });
129
+
130
+ describe('toHaveBeenCalledWith', () => {
131
+ it('fail', () => {
132
+ const options = {
133
+ isNot: false,
134
+ promise: false,
135
+ toHaveBeenCalledWith,
136
+ };
137
+
138
+ const method = mock.fn();
139
+
140
+ const result = options.toHaveBeenCalledWith(method, 1);
141
+ const message = stripAnsi(result.message());
142
+
143
+ expect(result).toEqual({ message: expect.any(Function), pass: false });
144
+ expect(message).toStrictEqual(
145
+ expect.stringContaining(
146
+ 'expect(mock.fn()).false.toHaveBeenCalledWith(...expected)'
147
+ )
148
+ );
149
+ expect(message).toStrictEqual(expect.stringContaining('Expected: 1'));
150
+ expect(message).toStrictEqual(
151
+ expect.stringContaining('Number of calls: 0')
152
+ );
153
+ });
154
+
155
+ it('not pass', () => {
156
+ const options = {
157
+ isNot: true,
158
+ promise: false,
159
+ toHaveBeenCalledWith,
160
+ };
161
+ const method = mock.fn();
162
+
163
+ const result = options.toHaveBeenCalledWith(method, 1);
164
+ const message = stripAnsi(result.message());
165
+
166
+ expect(result).toEqual({ message: expect.any(Function), pass: false });
167
+ expect(message).toStrictEqual(
168
+ expect.stringContaining(
169
+ 'expect(mock.fn()).false.not.toHaveBeenCalledWith(...expected)'
170
+ )
171
+ );
172
+ expect(message).toStrictEqual(expect.stringContaining('Expected: 1'));
173
+ expect(message).toStrictEqual(
174
+ expect.stringContaining('Number of calls: 0')
175
+ );
176
+ });
177
+ });
178
+
179
+ describe('toHaveBeenLastCalledWith', () => {
180
+ it('fail', () => {
181
+ const options = {
182
+ isNot: false,
183
+ promise: false,
184
+ toHaveBeenLastCalledWith,
185
+ };
186
+
187
+ const method = mock.fn();
188
+
189
+ const result = options.toHaveBeenLastCalledWith(method, 1);
190
+ const message = stripAnsi(result.message());
191
+
192
+ expect(result).toEqual({ message: expect.any(Function), pass: false });
193
+ expect(message).toStrictEqual(
194
+ expect.stringContaining(
195
+ 'expect(mock.fn()).false.toHaveBeenLastCalledWith(...expected)'
196
+ )
197
+ );
198
+ expect(message).toStrictEqual(expect.stringContaining('Expected: 1'));
199
+ expect(message).toStrictEqual(
200
+ expect.stringContaining('Number of calls: 0')
201
+ );
202
+ });
203
+
204
+ it('not pass', () => {
205
+ const options = {
206
+ isNot: true,
207
+ promise: false,
208
+ toHaveBeenLastCalledWith,
209
+ };
210
+ const method = mock.fn();
211
+
212
+ const result = options.toHaveBeenLastCalledWith(method, 1);
213
+ const message = stripAnsi(result.message());
214
+
215
+ expect(result).toEqual({ message: expect.any(Function), pass: false });
216
+ expect(message).toStrictEqual(
217
+ expect.stringContaining(
218
+ 'expect(mock.fn()).false.not.toHaveBeenLastCalledWith(...expected)'
219
+ )
220
+ );
221
+ expect(message).toStrictEqual(expect.stringContaining('Expected: 1'));
222
+ expect(message).toStrictEqual(
223
+ expect.stringContaining('Number of calls: 0')
224
+ );
225
+ });
226
+ });
227
+
228
+ describe('toHaveBeenNthCalledWith', () => {
229
+ it('fail', () => {
230
+ const options = {
231
+ isNot: false,
232
+ promise: false,
233
+ toHaveBeenNthCalledWith,
234
+ };
235
+
236
+ const method = mock.fn();
237
+
238
+ const result = options.toHaveBeenNthCalledWith(method, 1, 1);
239
+ const message = stripAnsi(result.message());
240
+
241
+ expect(result).toEqual({ message: expect.any(Function), pass: false });
242
+ expect(message).toStrictEqual(
243
+ expect.stringContaining(
244
+ 'expect(mock.fn()).false.toHaveBeenNthCalledWith(...expected)'
245
+ )
246
+ );
247
+ expect(message).toStrictEqual(expect.stringContaining('Expected: 1'));
248
+ expect(message).toStrictEqual(
249
+ expect.stringContaining('Number of calls: 0')
250
+ );
251
+ });
252
+
253
+ it('not pass', () => {
254
+ const options = {
255
+ isNot: true,
256
+ promise: false,
257
+ toHaveBeenNthCalledWith,
258
+ };
259
+ const method = mock.fn();
260
+
261
+ const result = options.toHaveBeenNthCalledWith(method, 1, 1);
262
+ const message = stripAnsi(result.message());
263
+
264
+ expect(result).toEqual({ message: expect.any(Function), pass: false });
265
+ expect(message).toStrictEqual(
266
+ expect.stringContaining(
267
+ 'expect(mock.fn()).false.not.toHaveBeenNthCalledWith(...expected)'
268
+ )
269
+ );
270
+ expect(message).toStrictEqual(expect.stringContaining('Expected: 1'));
271
+ expect(message).toStrictEqual(
272
+ expect.stringContaining('Number of calls: 0')
273
+ );
274
+ });
275
+ });
276
+ });
package/lib/index.mjs CHANGED
@@ -6,6 +6,12 @@ import {
6
6
  toHaveBeenCalledWith,
7
7
  toHaveBeenLastCalledWith,
8
8
  toHaveBeenNthCalledWith,
9
+ toReturn,
10
+ toHaveReturned,
11
+ toHaveReturnedTimes,
12
+ toHaveReturnedWith,
13
+ toHaveLastReturnedWith,
14
+ toHaveNthReturnedWith,
9
15
  } from './mockMethodMatchers.mjs';
10
16
 
11
17
  expect.extend({
@@ -14,4 +20,10 @@ expect.extend({
14
20
  toHaveBeenCalledWith,
15
21
  toHaveBeenLastCalledWith,
16
22
  toHaveBeenNthCalledWith,
23
+ toReturn,
24
+ toHaveReturned,
25
+ toHaveReturnedTimes,
26
+ toHaveReturnedWith,
27
+ toHaveLastReturnedWith,
28
+ toHaveNthReturnedWith,
17
29
  });
@@ -1,21 +1,389 @@
1
+ import chalk from 'chalk';
1
2
  import { expect } from 'expect';
2
- import { matcherHint, printExpected, printReceived } from 'jest-matcher-utils';
3
+ import {
4
+ matcherErrorMessage,
5
+ matcherHint,
6
+ printExpected,
7
+ printReceived,
8
+ } from 'jest-matcher-utils';
9
+
10
+ export const EXPECTED_COLOR = chalk.green;
11
+ export const RECEIVED_COLOR = chalk.red;
12
+ export const INVERTED_COLOR = chalk.inverse;
13
+ export const BOLD_WEIGHT = chalk.bold;
14
+ export const DIM_COLOR = chalk.dim;
15
+
16
+ /**
17
+ * 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}
23
+ */
24
+ function ensureReceivedIsNodeMock(received, matcherName, options = {}) {
25
+ if (typeof received !== 'function') {
26
+ throw new TypeError(
27
+ matcherErrorMessage(
28
+ matcherHint(matcherName, typeof received, 'function', options),
29
+ `${RECEIVED_COLOR('received')} value must be a function`
30
+ )
31
+ );
32
+ }
33
+
34
+ return typeof received.mock === 'object';
35
+ }
36
+
37
+ /**
38
+ * Factory function to create a matcher object
39
+ * @param {string} matcherName
40
+ * @param {Object} options
41
+ * @param {boolean} options.isNot
42
+ * @param {boolean} options.promise
43
+ * @returns {Object}
44
+ */
45
+ function matcherFactory(matcherName, { isNot, promise } = {}) {
46
+ return {
47
+ matcherName,
48
+ options: {
49
+ comment: `${matcherName} of Node.js mock.fn()`,
50
+ isNot,
51
+ promise,
52
+ },
53
+ receivedText: 'mock.fn()',
54
+ };
55
+ }
3
56
 
4
57
  /**
5
58
  * toHaveBeenCalled
59
+ *
60
+ * https://jestjs.io/docs/expect#tohavebeencalled
61
+ */
62
+ function toHaveBeenCalled(receivedMethod, ...args) {
63
+ const { matcherName, options, receivedText } = matcherFactory(
64
+ 'toHaveBeenCalled',
65
+ this
66
+ );
67
+
68
+ if (ensureReceivedIsNodeMock(receivedMethod, matcherName, options)) {
69
+ let message = `\n${matcherHint(
70
+ matcherName,
71
+ receivedText,
72
+ '',
73
+ options
74
+ )}\n\n`;
75
+ let pass = false;
76
+
77
+ if (args && args[0]) {
78
+ message += `Matcher error: this matcher must not have an expected argument
79
+ \nExpected has type: ${typeof args[0]}\nExpected has value: ${EXPECTED_COLOR(
80
+ args[0]
81
+ )}\n`;
82
+ } else {
83
+ pass = receivedMethod.mock.calls.length > 0;
84
+ if (pass) {
85
+ message += `Expected number of calls: ${EXPECTED_COLOR(
86
+ '0'
87
+ )}\nReceived number of calls: ${RECEIVED_COLOR(
88
+ receivedMethod.mock.calls.length
89
+ )}\n`;
90
+ } else {
91
+ message += `Expected number of calls: >= ${EXPECTED_COLOR(
92
+ '1'
93
+ )}\nReceived number of calls: ${RECEIVED_COLOR('0')}\n`;
94
+ }
95
+ }
96
+
97
+ return {
98
+ pass,
99
+ message: () => message,
100
+ };
101
+ }
102
+
103
+ return expect(receivedMethod).toHaveBeenCalled();
104
+ }
105
+
106
+ /**
107
+ * toHaveBeenCalledTimes
108
+ *
109
+ * https://jestjs.io/docs/expect#tohavebeencalledtimesnumber
110
+ */
111
+ function toHaveBeenCalledTimes(receivedMethod, expected) {
112
+ const { matcherName, options, receivedText } = matcherFactory(
113
+ 'toHaveBeenCalledTimes',
114
+ this
115
+ );
116
+ const received = receivedMethod.mock.calls.length;
117
+
118
+ if (ensureReceivedIsNodeMock(receivedMethod, matcherName, options)) {
119
+ let message = `\n${matcherHint(
120
+ matcherName,
121
+ receivedText,
122
+ 'expected',
123
+ options
124
+ )}\n\n`;
125
+ const pass = received === expected;
126
+
127
+ if (pass) {
128
+ message += `Expected number of calls: not ${EXPECTED_COLOR(received)}\n`;
129
+ } else {
130
+ message += `Expected number of calls: ${EXPECTED_COLOR(
131
+ expected
132
+ )}\nReceived number of calls: ${RECEIVED_COLOR(received)}\n`;
133
+ }
134
+
135
+ return {
136
+ pass,
137
+ message: () => message,
138
+ };
139
+ }
140
+
141
+ return expect(receivedMethod).toHaveBeenCalledTimes(expected);
142
+ }
143
+
144
+ /**
145
+ * toHaveBeenCalledWith
146
+ *
147
+ * https://jestjs.io/docs/expect#tohavebeencalledwitharg1-arg2-
148
+ */
149
+ function toHaveBeenCalledWith(receivedMethod, ...args) {
150
+ const { matcherName, options, receivedText } = matcherFactory(
151
+ 'toHaveBeenCalledWith',
152
+ this
153
+ );
154
+
155
+ if (ensureReceivedIsNodeMock(receivedMethod, matcherName, options)) {
156
+ const argsCount = args.length;
157
+ const receivedArgs = [];
158
+ let pass = false;
159
+ let message = '';
160
+
161
+ if (!receivedMethod.mock.calls.length) {
162
+ pass = false;
163
+ message = `Expected: `;
164
+ if (argsCount === 0) {
165
+ message += `called with 0 arguments`;
166
+ } else {
167
+ message += `${args.map(arg => printExpected(arg)).join(', ')}`;
168
+ }
169
+ } else {
170
+ pass = receivedMethod.mock.calls.some(call => {
171
+ receivedArgs.push(call.arguments);
172
+ return (
173
+ argsCount &&
174
+ args.every((arg, index) => {
175
+ try {
176
+ expect(call.arguments[index]).toEqual(arg);
177
+ return true;
178
+ } catch (_) {
179
+ return false;
180
+ }
181
+ })
182
+ );
183
+ });
184
+
185
+ message = `Expected: ${pass ? 'not ' : ''}`;
186
+
187
+ if (argsCount === 0) {
188
+ message += `called with 0 arguments`;
189
+ } else {
190
+ message += `${args.map(arg => printExpected(arg)).join(', ')}`;
191
+ }
192
+
193
+ message += `\n\nReceived\n${receivedArgs.reduce(
194
+ (receivedText, args, index) =>
195
+ (receivedText +=
196
+ args.length === 0
197
+ ? '\t' + index + ': called with 0 arguments\n'
198
+ : '\t' +
199
+ index +
200
+ ': ' +
201
+ args.map(arg => printReceived(arg)).join(', ') +
202
+ '\n'),
203
+ ''
204
+ )}`;
205
+ }
206
+
207
+ return {
208
+ pass,
209
+ message: () =>
210
+ `\n${matcherHint(
211
+ matcherName,
212
+ receivedText,
213
+ '...expected',
214
+ options
215
+ )}\n\n${message}\n\nNumber of calls: ${RECEIVED_COLOR(
216
+ receivedMethod.mock.calls.length
217
+ )}\n`,
218
+ };
219
+ }
220
+
221
+ return expect(receivedMethod).toHaveBeenCalledWith(...args);
222
+ }
223
+
224
+ /**
225
+ * toHaveBeenLastCalledWith
226
+ *
227
+ * https://jestjs.io/docs/expect#tohavebeenlastcalledwitharg1-arg2-
228
+ */
229
+ function toHaveBeenLastCalledWith(receivedMethod, ...args) {
230
+ const { matcherName, options, receivedText } = matcherFactory(
231
+ 'toHaveBeenLastCalledWith',
232
+ this
233
+ );
234
+
235
+ if (ensureReceivedIsNodeMock(receivedMethod, matcherName, options)) {
236
+ const argsCount = args.length;
237
+ const receivedArgs = [];
238
+ let pass = false;
239
+ let message = '';
240
+ const callsCount = receivedMethod.mock.calls.length;
241
+
242
+ if (!callsCount) {
243
+ pass = false;
244
+ message = `Expected: `;
245
+ if (argsCount === 0) {
246
+ message += `called with 0 arguments`;
247
+ } else {
248
+ message += `${args.map(arg => printExpected(arg)).join(', ')}`;
249
+ }
250
+ } else {
251
+ const lastCall = receivedMethod.mock.calls[callsCount - 1];
252
+ receivedArgs.push(lastCall.arguments);
253
+ pass =
254
+ argsCount &&
255
+ args.every((arg, index) => {
256
+ try {
257
+ expect(lastCall.arguments[index]).toEqual(arg);
258
+ return true;
259
+ } catch (_) {
260
+ return false;
261
+ }
262
+ });
263
+
264
+ message = `Expected: ${pass ? 'not ' : ''}`;
265
+
266
+ if (argsCount === 0) {
267
+ message += `called with 0 arguments`;
268
+ } else {
269
+ message += `${args.map(arg => printExpected(arg)).join(', ')}`;
270
+ }
271
+
272
+ message += `\n\n\nReceived: ${receivedArgs.map(args =>
273
+ args.map(arg => printReceived(arg)).join(', ')
274
+ )}`;
275
+ }
276
+
277
+ return {
278
+ pass,
279
+ message: () =>
280
+ `${matcherHint(
281
+ matcherName,
282
+ receivedText,
283
+ '...expected',
284
+ options
285
+ )}\n\n${message}\n\nNumber of calls: ${RECEIVED_COLOR(
286
+ receivedMethod.mock.calls.length
287
+ )}\n`,
288
+ };
289
+ }
290
+
291
+ return expect(receivedMethod).toHaveBeenLastCalledWith(...args);
292
+ }
293
+
294
+ /**
295
+ * toHaveBeenNthCalledWith
296
+ *
297
+ * https://jestjs.io/docs/expect#tohavebeennthcalledwithnthcall-arg1-arg2-
6
298
  */
7
- function toHaveBeenCalled(method) {
8
- expect(typeof method).toBe('function');
299
+ function toHaveBeenNthCalledWith(receivedMethod, nthCallIndex, ...args) {
300
+ const { matcherName, options, receivedText } = matcherFactory(
301
+ 'toHaveBeenNthCalledWith',
302
+ this
303
+ );
304
+
305
+ if (ensureReceivedIsNodeMock(receivedMethod, matcherName, options)) {
306
+ const argsCount = args.length;
307
+ const receivedArgs = [];
308
+ let pass = false;
309
+ let message = `n: ${nthCallIndex}\n`;
310
+ const callsCount = receivedMethod.mock.calls.length;
311
+
312
+ if (!callsCount || nthCallIndex > callsCount) {
313
+ pass = false;
314
+ message += `Expected: `;
315
+ if (argsCount === 0) {
316
+ message += `called with 0 arguments`;
317
+ } else {
318
+ message += `${args.map(arg => printExpected(arg)).join(', ')}`;
319
+ }
320
+ } else {
321
+ const nthCall = receivedMethod.mock.calls[nthCallIndex - 1];
322
+ receivedArgs.push(nthCall.arguments);
323
+ pass =
324
+ argsCount &&
325
+ args.every((arg, index) => {
326
+ try {
327
+ expect(nthCall.arguments[index]).toEqual(arg);
328
+ return true;
329
+ } catch (_) {
330
+ return false;
331
+ }
332
+ });
333
+
334
+ message += `Expected: ${pass ? 'not ' : ''}`;
335
+
336
+ if (argsCount === 0) {
337
+ message += `called with 0 arguments`;
338
+ } else {
339
+ message += `${args.map(arg => printExpected(arg)).join(', ')}`;
340
+ }
341
+
342
+ message += `\nReceived: ${
343
+ receivedArgs.length
344
+ ? receivedArgs.map(args =>
345
+ args.map(arg => printReceived(arg)).join(', ')
346
+ )
347
+ : 'called with 0 arguments'
348
+ }`;
349
+ }
350
+
351
+ return {
352
+ pass,
353
+ message: () =>
354
+ `${matcherHint(
355
+ matcherName,
356
+ receivedText,
357
+ '...expected',
358
+ options
359
+ )}\n\n${message}\n\nNumber of calls: ${RECEIVED_COLOR(
360
+ receivedMethod.mock.calls.length
361
+ )}\n`,
362
+ };
363
+ }
364
+
365
+ return expect(receivedMethod).toHaveBeenNthCalledWith(nthCallIndex, ...args);
366
+ }
367
+
368
+ /**
369
+ * toHaveReturned
370
+ *
371
+ * https://jestjs.io/docs/expect#tohavereturned
372
+ */
373
+ function toHaveReturned(receivedMethod) {
374
+ expect(typeof receivedMethod).toBe('function');
9
375
 
10
376
  // detect native node test runner mock
11
- if (typeof method.mock === 'object') {
12
- const matcherName = 'toHaveBeenCalled';
377
+ if (typeof receivedMethod.mock === 'object') {
378
+ const matcherName = 'toHaveReturned';
13
379
  const options = {
14
380
  isNot: this.isNot,
15
381
  promise: this.promise,
16
382
  };
17
383
 
18
- const pass = method.mock.calls.length > 0;
384
+ const pass = receivedMethod.mock.calls.some(
385
+ call => call.error === undefined
386
+ );
19
387
 
20
388
  if (pass) {
21
389
  return {
@@ -26,38 +394,58 @@ function toHaveBeenCalled(method) {
26
394
  undefined,
27
395
  undefined,
28
396
  options
29
- )}\nexpected ${method.name} not to be called`,
397
+ )}\nExpected: ${printExpected(
398
+ 'not to return an error'
399
+ )}\nReceived: ${printReceived('returned without error')}`,
400
+ };
401
+ } else {
402
+ return {
403
+ pass,
404
+ message: () =>
405
+ `${matcherHint(
406
+ matcherName,
407
+ undefined,
408
+ undefined,
409
+ options
410
+ )}\nExpected: ${printExpected(
411
+ 'not to return an error'
412
+ )}\nReceived: ${printReceived('returned with error')}`,
30
413
  };
31
414
  }
32
-
33
- return {
34
- pass,
35
- message: () =>
36
- `${matcherHint(matcherName, undefined, undefined, options)}\nexpected ${
37
- method.name
38
- } to be called`,
39
- };
40
415
  }
41
416
 
42
- return expect(method).toHaveBeenCalled();
417
+ return expect(receivedMethod).toHaveReturned();
43
418
  }
44
419
 
45
420
  /**
46
- * toHaveBeenCalledTimes
421
+ * toReturn
422
+ *
423
+ * https://jestjs.io/docs/expect#tohavereturned
424
+ */
425
+ function toReturn(receivedMethod) {
426
+ return toHaveReturned(receivedMethod);
427
+ }
428
+
429
+ /**
430
+ * toHaveReturnedTimes
431
+ *
432
+ * https://jestjs.io/docs/expect#tohavereturnedtimesnumber
47
433
  */
48
- function toHaveBeenCalledTimes(method, expected) {
49
- expect(typeof method).toBe('function');
434
+ function toHaveReturnedTimes(receivedMethod, times) {
435
+ expect(typeof receivedMethod).toBe('function');
50
436
 
51
- // detect native node test runßßner mock
52
- if (typeof method.mock === 'object') {
53
- const matcherName = 'toHaveBeenCalledTimes';
437
+ // detect native node test runner mock
438
+ if (typeof receivedMethod.mock === 'object') {
439
+ const matcherName = 'toHaveReturnedTimes';
54
440
  const options = {
55
441
  isNot: this.isNot,
56
442
  promise: this.promise,
57
443
  };
58
- const received = method.mock.calls.length;
59
444
 
60
- const pass = received === expected;
445
+ const noErrorCalls = receivedMethod.mock.calls.filter(
446
+ call => call.error === undefined
447
+ );
448
+ const pass = noErrorCalls.length === times;
61
449
 
62
450
  if (pass) {
63
451
  return {
@@ -68,8 +456,8 @@ function toHaveBeenCalledTimes(method, expected) {
68
456
  undefined,
69
457
  undefined,
70
458
  options
71
- )}\nExpected: ${printExpected(expected)}\nReceived: ${printReceived(
72
- received
459
+ )}\nExpected: ${printExpected(times)}\nReceived: ${printReceived(
460
+ receivedMethod.mock.calls.length
73
461
  )}`,
74
462
  };
75
463
  }
@@ -82,36 +470,34 @@ function toHaveBeenCalledTimes(method, expected) {
82
470
  undefined,
83
471
  undefined,
84
472
  options
85
- )}\nExpected: ${printExpected(expected)}\nReceived: ${printReceived(
86
- received
473
+ )}\nExpected: ${printExpected(times)}\nReceived: ${printReceived(
474
+ receivedMethod.mock.calls.length
87
475
  )}`,
88
476
  };
89
477
  }
90
478
 
91
- return expect(method).toHaveBeenCalledTimes(expected);
479
+ return expect(receivedMethod).toHaveReturnedTimes(times);
92
480
  }
93
481
 
94
482
  /**
95
- * toHaveBeenCalledWith
483
+ * toHaveReturnedWith
484
+ *
485
+ * https://jestjs.io/docs/expect#tohavereturnedwithvalue
96
486
  */
97
- function toHaveBeenCalledWith(method, ...args) {
98
- expect(typeof method).toBe('function');
487
+ function toHaveReturnedWith(receivedMethod, expected) {
488
+ expect(typeof receivedMethod).toBe('function');
99
489
 
100
490
  // detect native node test runner mock
101
- if (typeof method.mock === 'object') {
102
- expect(method.mock.calls.length).toBeGreaterThan(0);
103
-
104
- const matcherName = 'toHaveBeenCalledWith';
491
+ if (typeof receivedMethod.mock === 'object') {
492
+ const matcherName = 'toHaveReturnedWith';
105
493
  const options = {
106
494
  isNot: this.isNot,
107
495
  promise: this.promise,
108
496
  };
109
- const receivedArgs = [];
110
497
 
111
- const pass = method.mock.calls.some(call => {
112
- receivedArgs.push(call.arguments);
113
- return args.every((arg, index) => call.arguments[index] === arg);
114
- });
498
+ const pass = receivedMethod.mock.calls.some(
499
+ call => call.result === expected
500
+ );
115
501
 
116
502
  if (pass) {
117
503
  return {
@@ -122,8 +508,8 @@ function toHaveBeenCalledWith(method, ...args) {
122
508
  undefined,
123
509
  undefined,
124
510
  options
125
- )}\nExpected: ${printExpected(...args)}\nReceived: ${receivedArgs.map(
126
- args => args.map(arg => printReceived(arg)).join(', ')
511
+ )}\nExpected: ${printExpected(expected)}\nReceived: ${printReceived(
512
+ receivedMethod.mock.calls.map(call => call.result)
127
513
  )}`,
128
514
  };
129
515
  }
@@ -136,33 +522,34 @@ function toHaveBeenCalledWith(method, ...args) {
136
522
  undefined,
137
523
  undefined,
138
524
  options
139
- )}\nExpected: ${printExpected(...args)}\nReceived: ${receivedArgs.map(
140
- args => args.map(arg => printReceived(arg)).join(', ')
525
+ )}\nExpected: ${printExpected(expected)}\nReceived: ${printReceived(
526
+ receivedMethod.mock.calls.map(call => call.result)
141
527
  )}`,
142
528
  };
143
529
  }
144
530
 
145
- return expect(method).toHaveBeenCalledWith(...args);
531
+ return expect(receivedMethod).toHaveReturnedWith(expected);
146
532
  }
147
533
 
148
534
  /**
149
- * toHaveBeenLastCalledWith
535
+ * toHaveLastReturnedWith
536
+ *
537
+ * https://jestjs.io/docs/expect#tohavelastreturnedwithvalue
150
538
  */
151
- function toHaveBeenLastCalledWith(method, ...args) {
152
- expect(typeof method).toBe('function');
539
+ function toHaveLastReturnedWith(receivedMethod, expected) {
540
+ expect(typeof receivedMethod).toBe('function');
153
541
 
154
542
  // detect native node test runner mock
155
- if (typeof method.mock === 'object') {
156
- expect(method.mock.calls.length).toBeGreaterThan(0);
157
-
158
- const matcherName = 'toHaveBeenLastCalledWith';
543
+ if (typeof receivedMethod.mock === 'object') {
544
+ const matcherName = 'toHaveLastReturnedWith';
159
545
  const options = {
160
546
  isNot: this.isNot,
161
547
  promise: this.promise,
162
548
  };
163
- const lastCall = method.mock.calls[method.mock.calls.length - 1];
164
549
 
165
- const pass = args.every((arg, index) => lastCall.arguments[index] === arg);
550
+ const lastCall =
551
+ receivedMethod.mock.calls[receivedMethod.mock.calls.length - 1];
552
+ const pass = lastCall.result === expected;
166
553
 
167
554
  if (pass) {
168
555
  return {
@@ -173,9 +560,9 @@ function toHaveBeenLastCalledWith(method, ...args) {
173
560
  undefined,
174
561
  undefined,
175
562
  options
176
- )}\nExpected: ${printExpected(
177
- ...args
178
- )}\nReceived: ${lastCall.arguments.map(arg => printReceived(arg))}`,
563
+ )}\nExpected: ${printExpected(expected)}\nReceived: ${printReceived(
564
+ lastCall.result
565
+ )}`,
179
566
  };
180
567
  }
181
568
 
@@ -187,33 +574,33 @@ function toHaveBeenLastCalledWith(method, ...args) {
187
574
  undefined,
188
575
  undefined,
189
576
  options
190
- )}\nExpected: ${printExpected(
191
- ...args
192
- )}\nReceived: ${lastCall.arguments.map(arg => printReceived(arg))}`,
577
+ )}\nExpected: ${printExpected(expected)}\nReceived: ${printReceived(
578
+ lastCall.result
579
+ )}`,
193
580
  };
194
581
  }
195
582
 
196
- return expect(method).toHaveBeenLastCalledWith(...args);
583
+ return expect(receivedMethod).toHaveLastReturnedWith(expected);
197
584
  }
198
585
 
199
586
  /**
200
- * toHaveBeenNthCalledWith
587
+ * toHaveNthReturnedWith
588
+ *
589
+ * https://jestjs.io/docs/expect#tohaventhreturnedwithnthcall-value
201
590
  */
202
- function toHaveBeenNthCalledWith(method, nthCall, ...args) {
203
- expect(typeof method).toBe('function');
591
+ function toHaveNthReturnedWith(receivedMethod, nthCall, expected) {
592
+ expect(typeof receivedMethod).toBe('function');
204
593
 
205
594
  // detect native node test runner mock
206
- if (typeof method.mock === 'object') {
207
- expect(method.mock.calls.length).toBeGreaterThan(nthCall - 1);
208
-
209
- const matcherName = 'toHaveBeenNthCalledWith';
595
+ if (typeof receivedMethod.mock === 'object') {
596
+ const matcherName = 'toHaveNthReturnedWith';
210
597
  const options = {
211
598
  isNot: this.isNot,
212
599
  promise: this.promise,
213
600
  };
214
- const lastCall = method.mock.calls[nthCall - 1];
215
601
 
216
- const pass = args.every((arg, index) => lastCall.arguments[index] === arg);
602
+ const nthCallResult = receivedMethod.mock.calls[nthCall - 1].result;
603
+ const pass = nthCallResult === expected;
217
604
 
218
605
  if (pass) {
219
606
  return {
@@ -224,9 +611,9 @@ function toHaveBeenNthCalledWith(method, nthCall, ...args) {
224
611
  undefined,
225
612
  undefined,
226
613
  options
227
- )}\nExpected: ${printExpected(
228
- ...args
229
- )}\nReceived: ${lastCall.arguments.map(arg => printReceived(arg))}`,
614
+ )}\nExpected: ${printExpected(expected)}\nReceived: ${printReceived(
615
+ nthCallResult
616
+ )}`,
230
617
  };
231
618
  }
232
619
 
@@ -238,13 +625,13 @@ function toHaveBeenNthCalledWith(method, nthCall, ...args) {
238
625
  undefined,
239
626
  undefined,
240
627
  options
241
- )}\nExpected: ${printExpected(
242
- ...args
243
- )}\nReceived: ${lastCall.arguments.map(arg => printReceived(arg))}`,
628
+ )}\nExpected: ${printExpected(expected)}\nReceived: ${printReceived(
629
+ nthCallResult
630
+ )}`,
244
631
  };
245
632
  }
246
633
 
247
- return expect(method).toHaveBeenNthCalledWith(nthCall, ...args);
634
+ return expect(receivedMethod).toHaveNthReturnedWith(nthCall, expected);
248
635
  }
249
636
 
250
637
  export {
@@ -253,4 +640,10 @@ export {
253
640
  toHaveBeenCalledWith,
254
641
  toHaveBeenLastCalledWith,
255
642
  toHaveBeenNthCalledWith,
643
+ toReturn,
644
+ toHaveReturned,
645
+ toHaveReturnedTimes,
646
+ toHaveReturnedWith,
647
+ toHaveLastReturnedWith,
648
+ toHaveNthReturnedWith,
256
649
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "expect-matcher-node-mock",
3
- "version": "1.0.0",
3
+ "version": "1.1.0",
4
4
  "description": "Jest matcher for Node.js mock objects",
5
5
  "main": "lib/index.mjs",
6
6
  "bugs": {