bupkis 0.1.2 → 0.3.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.
Files changed (198) hide show
  1. package/CHANGELOG.md +28 -0
  2. package/README.md +16 -16
  3. package/dist/commonjs/assertion/assertion-async.d.ts +2 -1
  4. package/dist/commonjs/assertion/assertion-async.d.ts.map +1 -1
  5. package/dist/commonjs/assertion/assertion-async.js +84 -2
  6. package/dist/commonjs/assertion/assertion-async.js.map +1 -1
  7. package/dist/commonjs/assertion/assertion-sync.d.ts +1 -1
  8. package/dist/commonjs/assertion/assertion-sync.d.ts.map +1 -1
  9. package/dist/commonjs/assertion/assertion-sync.js +5 -1
  10. package/dist/commonjs/assertion/assertion-sync.js.map +1 -1
  11. package/dist/commonjs/assertion/assertion-types.d.ts +39 -84
  12. package/dist/commonjs/assertion/assertion-types.d.ts.map +1 -1
  13. package/dist/commonjs/assertion/assertion.d.ts +1 -1
  14. package/dist/commonjs/assertion/assertion.d.ts.map +1 -1
  15. package/dist/commonjs/assertion/assertion.js +1 -14
  16. package/dist/commonjs/assertion/assertion.js.map +1 -1
  17. package/dist/commonjs/assertion/create.d.ts +5 -33
  18. package/dist/commonjs/assertion/create.d.ts.map +1 -1
  19. package/dist/commonjs/assertion/create.js +17 -6
  20. package/dist/commonjs/assertion/create.js.map +1 -1
  21. package/dist/commonjs/assertion/impl/async.d.ts +122 -21
  22. package/dist/commonjs/assertion/impl/async.d.ts.map +1 -1
  23. package/dist/commonjs/assertion/impl/async.js +114 -90
  24. package/dist/commonjs/assertion/impl/async.js.map +1 -1
  25. package/dist/commonjs/assertion/impl/callback.d.ts +104 -0
  26. package/dist/commonjs/assertion/impl/callback.d.ts.map +1 -0
  27. package/dist/commonjs/assertion/impl/callback.js +694 -0
  28. package/dist/commonjs/assertion/impl/callback.js.map +1 -0
  29. package/dist/commonjs/assertion/impl/index.d.ts +1 -1
  30. package/dist/commonjs/assertion/impl/index.d.ts.map +1 -1
  31. package/dist/commonjs/assertion/impl/index.js.map +1 -1
  32. package/dist/commonjs/assertion/impl/sync-esoteric.js +1 -1
  33. package/dist/commonjs/assertion/impl/sync-esoteric.js.map +1 -1
  34. package/dist/commonjs/assertion/impl/sync-parametric.d.ts +37 -34
  35. package/dist/commonjs/assertion/impl/sync-parametric.d.ts.map +1 -1
  36. package/dist/commonjs/assertion/impl/sync-parametric.js +32 -47
  37. package/dist/commonjs/assertion/impl/sync-parametric.js.map +1 -1
  38. package/dist/commonjs/assertion/impl/sync.d.ts +105 -58
  39. package/dist/commonjs/assertion/impl/sync.d.ts.map +1 -1
  40. package/dist/commonjs/assertion/impl/sync.js +4 -1
  41. package/dist/commonjs/assertion/impl/sync.js.map +1 -1
  42. package/dist/commonjs/bootstrap.d.ts +199 -85
  43. package/dist/commonjs/bootstrap.d.ts.map +1 -1
  44. package/dist/commonjs/bootstrap.js +19 -10
  45. package/dist/commonjs/bootstrap.js.map +1 -1
  46. package/dist/commonjs/constant.js +7 -1
  47. package/dist/commonjs/constant.js.map +1 -1
  48. package/dist/commonjs/error.d.ts +32 -5
  49. package/dist/commonjs/error.d.ts.map +1 -1
  50. package/dist/commonjs/error.js +60 -5
  51. package/dist/commonjs/error.js.map +1 -1
  52. package/dist/commonjs/expect.d.ts +130 -3
  53. package/dist/commonjs/expect.d.ts.map +1 -1
  54. package/dist/commonjs/expect.js +116 -1
  55. package/dist/commonjs/expect.js.map +1 -1
  56. package/dist/commonjs/guards.d.ts +45 -20
  57. package/dist/commonjs/guards.d.ts.map +1 -1
  58. package/dist/commonjs/guards.js +56 -40
  59. package/dist/commonjs/guards.js.map +1 -1
  60. package/dist/commonjs/index.d.ts +241 -86
  61. package/dist/commonjs/index.d.ts.map +1 -1
  62. package/dist/commonjs/index.js +44 -42
  63. package/dist/commonjs/index.js.map +1 -1
  64. package/dist/commonjs/metadata.d.ts +1 -27
  65. package/dist/commonjs/metadata.d.ts.map +1 -1
  66. package/dist/commonjs/metadata.js +16 -15
  67. package/dist/commonjs/metadata.js.map +1 -1
  68. package/dist/commonjs/schema.d.ts +76 -33
  69. package/dist/commonjs/schema.d.ts.map +1 -1
  70. package/dist/commonjs/schema.js +77 -34
  71. package/dist/commonjs/schema.js.map +1 -1
  72. package/dist/commonjs/types.d.ts +480 -39
  73. package/dist/commonjs/types.d.ts.map +1 -1
  74. package/dist/commonjs/types.js +12 -2
  75. package/dist/commonjs/types.js.map +1 -1
  76. package/dist/commonjs/util.d.ts +72 -49
  77. package/dist/commonjs/util.d.ts.map +1 -1
  78. package/dist/commonjs/util.js +175 -155
  79. package/dist/commonjs/util.js.map +1 -1
  80. package/dist/commonjs/value-to-schema.d.ts +122 -0
  81. package/dist/commonjs/value-to-schema.d.ts.map +1 -0
  82. package/dist/commonjs/value-to-schema.js +309 -0
  83. package/dist/commonjs/value-to-schema.js.map +1 -0
  84. package/dist/esm/assertion/assertion-async.d.ts +2 -1
  85. package/dist/esm/assertion/assertion-async.d.ts.map +1 -1
  86. package/dist/esm/assertion/assertion-async.js +85 -3
  87. package/dist/esm/assertion/assertion-async.js.map +1 -1
  88. package/dist/esm/assertion/assertion-sync.d.ts +1 -1
  89. package/dist/esm/assertion/assertion-sync.d.ts.map +1 -1
  90. package/dist/esm/assertion/assertion-sync.js +6 -2
  91. package/dist/esm/assertion/assertion-sync.js.map +1 -1
  92. package/dist/esm/assertion/assertion-types.d.ts +39 -84
  93. package/dist/esm/assertion/assertion-types.d.ts.map +1 -1
  94. package/dist/esm/assertion/assertion.d.ts +1 -1
  95. package/dist/esm/assertion/assertion.d.ts.map +1 -1
  96. package/dist/esm/assertion/assertion.js +1 -14
  97. package/dist/esm/assertion/assertion.js.map +1 -1
  98. package/dist/esm/assertion/create.d.ts +5 -33
  99. package/dist/esm/assertion/create.d.ts.map +1 -1
  100. package/dist/esm/assertion/create.js +14 -4
  101. package/dist/esm/assertion/create.js.map +1 -1
  102. package/dist/esm/assertion/impl/async.d.ts +122 -21
  103. package/dist/esm/assertion/impl/async.d.ts.map +1 -1
  104. package/dist/esm/assertion/impl/async.js +113 -89
  105. package/dist/esm/assertion/impl/async.js.map +1 -1
  106. package/dist/esm/assertion/impl/callback.d.ts +104 -0
  107. package/dist/esm/assertion/impl/callback.d.ts.map +1 -0
  108. package/dist/esm/assertion/impl/callback.js +691 -0
  109. package/dist/esm/assertion/impl/callback.js.map +1 -0
  110. package/dist/esm/assertion/impl/index.d.ts +1 -1
  111. package/dist/esm/assertion/impl/index.d.ts.map +1 -1
  112. package/dist/esm/assertion/impl/index.js +1 -1
  113. package/dist/esm/assertion/impl/index.js.map +1 -1
  114. package/dist/esm/assertion/impl/sync-esoteric.js +2 -2
  115. package/dist/esm/assertion/impl/sync-esoteric.js.map +1 -1
  116. package/dist/esm/assertion/impl/sync-parametric.d.ts +37 -34
  117. package/dist/esm/assertion/impl/sync-parametric.d.ts.map +1 -1
  118. package/dist/esm/assertion/impl/sync-parametric.js +32 -47
  119. package/dist/esm/assertion/impl/sync-parametric.js.map +1 -1
  120. package/dist/esm/assertion/impl/sync.d.ts +105 -58
  121. package/dist/esm/assertion/impl/sync.d.ts.map +1 -1
  122. package/dist/esm/assertion/impl/sync.js +3 -1
  123. package/dist/esm/assertion/impl/sync.js.map +1 -1
  124. package/dist/esm/bootstrap.d.ts +199 -85
  125. package/dist/esm/bootstrap.d.ts.map +1 -1
  126. package/dist/esm/bootstrap.js +19 -10
  127. package/dist/esm/bootstrap.js.map +1 -1
  128. package/dist/esm/constant.js +6 -0
  129. package/dist/esm/constant.js.map +1 -1
  130. package/dist/esm/error.d.ts +32 -5
  131. package/dist/esm/error.d.ts.map +1 -1
  132. package/dist/esm/error.js +59 -5
  133. package/dist/esm/error.js.map +1 -1
  134. package/dist/esm/expect.d.ts +130 -3
  135. package/dist/esm/expect.d.ts.map +1 -1
  136. package/dist/esm/expect.js +117 -2
  137. package/dist/esm/expect.js.map +1 -1
  138. package/dist/esm/guards.d.ts +45 -20
  139. package/dist/esm/guards.d.ts.map +1 -1
  140. package/dist/esm/guards.js +48 -31
  141. package/dist/esm/guards.js.map +1 -1
  142. package/dist/esm/index.d.ts +241 -86
  143. package/dist/esm/index.d.ts.map +1 -1
  144. package/dist/esm/index.js +46 -7
  145. package/dist/esm/index.js.map +1 -1
  146. package/dist/esm/metadata.d.ts +1 -27
  147. package/dist/esm/metadata.d.ts.map +1 -1
  148. package/dist/esm/metadata.js +2 -1
  149. package/dist/esm/metadata.js.map +1 -1
  150. package/dist/esm/schema.d.ts +76 -33
  151. package/dist/esm/schema.d.ts.map +1 -1
  152. package/dist/esm/schema.js +77 -34
  153. package/dist/esm/schema.js.map +1 -1
  154. package/dist/esm/types.d.ts +480 -39
  155. package/dist/esm/types.d.ts.map +1 -1
  156. package/dist/esm/types.js +12 -2
  157. package/dist/esm/types.js.map +1 -1
  158. package/dist/esm/util.d.ts +72 -49
  159. package/dist/esm/util.d.ts.map +1 -1
  160. package/dist/esm/util.js +159 -153
  161. package/dist/esm/util.js.map +1 -1
  162. package/dist/esm/value-to-schema.d.ts +122 -0
  163. package/dist/esm/value-to-schema.d.ts.map +1 -0
  164. package/dist/esm/value-to-schema.js +305 -0
  165. package/dist/esm/value-to-schema.js.map +1 -0
  166. package/package.json +94 -17
  167. package/src/assertion/assertion-async.ts +113 -3
  168. package/src/assertion/assertion-sync.ts +5 -2
  169. package/src/assertion/assertion-types.ts +52 -45
  170. package/src/assertion/assertion.ts +2 -17
  171. package/src/assertion/create.ts +16 -65
  172. package/src/assertion/impl/async.ts +132 -92
  173. package/src/assertion/impl/callback.ts +882 -0
  174. package/src/assertion/impl/index.ts +1 -1
  175. package/src/assertion/impl/sync-esoteric.ts +2 -2
  176. package/src/assertion/impl/sync-parametric.ts +41 -49
  177. package/src/assertion/impl/sync.ts +3 -0
  178. package/src/bootstrap.ts +21 -11
  179. package/src/constant.ts +8 -0
  180. package/src/error.ts +75 -4
  181. package/src/expect.ts +275 -20
  182. package/src/guards.ts +74 -69
  183. package/src/index.ts +72 -11
  184. package/src/metadata.ts +3 -4
  185. package/src/schema.ts +80 -36
  186. package/src/types.ts +625 -72
  187. package/src/util.ts +174 -222
  188. package/src/value-to-schema.ts +464 -0
  189. package/dist/commonjs/api.d.ts +0 -93
  190. package/dist/commonjs/api.d.ts.map +0 -1
  191. package/dist/commonjs/api.js +0 -8
  192. package/dist/commonjs/api.js.map +0 -1
  193. package/dist/esm/api.d.ts +0 -93
  194. package/dist/esm/api.d.ts.map +0 -1
  195. package/dist/esm/api.js +0 -7
  196. package/dist/esm/api.js.map +0 -1
  197. package/src/api.ts +0 -149
  198. package/src/schema.md +0 -15
@@ -0,0 +1,691 @@
1
+ /**
2
+ * Callback-based assertion implementations.
3
+ *
4
+ * For callback invocation, error handling, and value validation in both
5
+ * synchronous and asynchronous contexts.
6
+ *
7
+ * @packageDocumentation
8
+ */
9
+ import { inspect } from 'node:util';
10
+ import { z } from 'zod/v4';
11
+ import { isA, isNonNullObject, isString } from '../../guards.js';
12
+ import { ClassSchema, FunctionSchema } from '../../schema.js';
13
+ import { valueToSchema, valueToSchemaOptionsForDeepEqual, valueToSchemaOptionsForSatisfies, } from '../../value-to-schema.js';
14
+ import { createAssertion, createAsyncAssertion } from '../create.js';
15
+ /**
16
+ * Creates a standardized error object for when a callback or nodeback is not
17
+ * called.
18
+ *
19
+ * @param type - The type of callback ('callback' or 'nodeback')
20
+ * @returns Error object with consistent structure for sync assertions
21
+ */
22
+ /* c8 ignore next */
23
+ const createNotCalledError = (type) => ({
24
+ actual: 'not called',
25
+ expected: `${type} to be called`,
26
+ message: `Expected ${type} to be called, but it was not called`,
27
+ });
28
+ /**
29
+ * Creates a standardized error object for when a callback or nodeback is not
30
+ * called in async contexts. Uses consistent field naming for async assertions.
31
+ *
32
+ * @param type - The type of callback ('callback' or 'nodeback')
33
+ * @returns Error object with consistent structure for async assertions
34
+ */
35
+ /* c8 ignore next */
36
+ const createAsyncNotCalledError = (type) => ({
37
+ actual: `${type} not called`,
38
+ expected: `${type} to be called`,
39
+ message: `Expected ${type} to be called, but it was not`,
40
+ });
41
+ /**
42
+ * Creates error objects for nodeback error state mismatches in sync contexts.
43
+ * Handles cases where an error is expected but not present, or vice versa.
44
+ *
45
+ * @param hasError - Whether the nodeback was called with an error
46
+ * @param expectError - Whether an error was expected
47
+ * @param error - The actual error value (if any)
48
+ * @returns Error object if there's a mismatch, undefined if the state matches
49
+ * expectations
50
+ */
51
+ const createErrorMismatchError = (hasError, expectError, error) => {
52
+ if (hasError && !expectError) {
53
+ return {
54
+ actual: 'called with error',
55
+ expected: 'called without error',
56
+ message: `Expected nodeback to be called without error, but it was called with error: ${inspect(error, { depth: 2 })}`,
57
+ };
58
+ }
59
+ if (!hasError && expectError) {
60
+ return {
61
+ actual: 'called without error',
62
+ expected: 'called with error',
63
+ message: 'Expected nodeback to be called with an error, but it was called without error',
64
+ };
65
+ }
66
+ return undefined;
67
+ };
68
+ /**
69
+ * Creates error objects for nodeback error state mismatches in async contexts.
70
+ * Handles cases where an error is expected but not present, or vice versa. Uses
71
+ * consistent field naming and messaging for async assertions.
72
+ *
73
+ * @param hasError - Whether the nodeback was called with an error
74
+ * @param expectError - Whether an error was expected
75
+ * @param error - The actual error value (if any)
76
+ * @returns Error object if there's a mismatch, undefined if the state matches
77
+ * expectations
78
+ */
79
+ const createAsyncErrorMismatchError = (hasError, expectError, error) => {
80
+ if (hasError && !expectError) {
81
+ return {
82
+ actual: 'called with error',
83
+ expected: 'called without error',
84
+ message: `Expected nodeback to be called without error, but it was called with error: ${inspect(error, { depth: 2 })}`,
85
+ };
86
+ }
87
+ if (!hasError && expectError) {
88
+ return {
89
+ actual: 'called without error',
90
+ expected: 'called with error',
91
+ message: 'Expected nodeback to be called with an error, but it was called without an error',
92
+ };
93
+ }
94
+ return undefined;
95
+ };
96
+ /**
97
+ * Creates a standardized error object for exact value comparison failures. Used
98
+ * when a callback/nodeback is called with a value that doesn't match the
99
+ * expected value using Object.is() strict equality.
100
+ *
101
+ * @param actual - The actual value the callback was called with
102
+ * @param expected - The expected value
103
+ * @param callbackType - The type of callback for error messaging
104
+ * @returns Error object with formatted comparison message
105
+ */
106
+ const createValueMismatchError = (actual, expected, callbackType) => ({
107
+ actual,
108
+ expected,
109
+ message: `Expected ${callbackType} to be called with exactly ${inspect(expected, { depth: 2 })}, but it was called with ${inspect(actual, { depth: 2 })}`,
110
+ });
111
+ /**
112
+ * Creates a Zod schema for validating error parameters in callback assertions.
113
+ * Handles string literals, RegExp patterns, and object structures for error
114
+ * matching.
115
+ *
116
+ * @param param - The error parameter to create a schema for
117
+ * @returns Zod schema that can validate the error against the parameter
118
+ * @throws TypeError if the parameter type is not supported
119
+ */
120
+ const createErrorSchema = (param) => {
121
+ if (isString(param)) {
122
+ return z
123
+ .looseObject({
124
+ message: z.coerce.string().pipe(z.literal(param)),
125
+ })
126
+ .or(z.coerce.string().pipe(z.literal(param)));
127
+ }
128
+ if (isA(param, RegExp)) {
129
+ return z
130
+ .looseObject({
131
+ message: z.coerce.string().regex(param),
132
+ })
133
+ .or(z.coerce.string().regex(param));
134
+ }
135
+ if (isNonNullObject(param)) {
136
+ return valueToSchema(param, valueToSchemaOptionsForDeepEqual);
137
+ }
138
+ throw new TypeError(`Invalid parameter schema: ${inspect(param, { depth: 2 })}`);
139
+ };
140
+ /**
141
+ * Validates a value against a parameter using valueToSchema with specified
142
+ * options. Centralizes the common pattern of schema creation and validation
143
+ * used across many callback assertions.
144
+ *
145
+ * @param value - The value to validate
146
+ * @param param - The parameter to validate against
147
+ * @param options - Options to pass to valueToSchema
148
+ * @returns Undefined if validation succeeds, ZodError if validation fails
149
+ */
150
+ const validateValue = (value, param, options = {}) => {
151
+ const schema = valueToSchema(param, options);
152
+ const result = schema.safeParse(value);
153
+ return result.success ? undefined : result.error;
154
+ };
155
+ /**
156
+ * Traps the invocation of a single-parameter callback function for synchronous
157
+ * testing. Executes the provided function with a callback and captures whether
158
+ * it was called, what arguments it received, and any errors thrown during
159
+ * execution.
160
+ *
161
+ * @param fn - The function to execute that should call the provided callback
162
+ * @returns Object containing invocation details: args, called, error, and value
163
+ */
164
+ const trapCallbackInvocation = (fn) => {
165
+ let called = false;
166
+ let error;
167
+ let value;
168
+ let args = [];
169
+ const callback = (...cbArgs) => {
170
+ called = true;
171
+ args = cbArgs;
172
+ if (cbArgs.length >= 1) {
173
+ value = cbArgs[0];
174
+ }
175
+ };
176
+ try {
177
+ fn(callback);
178
+ }
179
+ catch (thrownError) {
180
+ error = thrownError;
181
+ }
182
+ return { args, called, error, value };
183
+ };
184
+ /**
185
+ * Traps the invocation of a nodeback (error-first callback) function for
186
+ * synchronous testing. Executes the provided function with a nodeback and
187
+ * captures whether it was called, what arguments it received, and any errors
188
+ * thrown during execution.
189
+ *
190
+ * @param fn - The function to execute that should call the provided nodeback
191
+ * @returns Object containing invocation details: args, called, error, and value
192
+ */
193
+ const trapNodebackInvocation = (fn) => {
194
+ let called = false;
195
+ let error;
196
+ let value;
197
+ let args = [];
198
+ const nodeback = (err, val) => {
199
+ called = true;
200
+ args = [err, val];
201
+ error = err;
202
+ value = val;
203
+ };
204
+ try {
205
+ fn(nodeback);
206
+ }
207
+ catch (thrownError) {
208
+ error = thrownError;
209
+ }
210
+ return { args, called, error, value };
211
+ };
212
+ /**
213
+ * Traps the invocation of a single-parameter callback function for asynchronous
214
+ * testing. Returns a Promise that resolves with invocation details once the
215
+ * callback is called or an error occurs. Uses a Proxy to catch errors during
216
+ * function execution.
217
+ *
218
+ * @param fn - The function to execute that should call the provided callback
219
+ * @returns Promise resolving to object with invocation details: args, called,
220
+ * error, and value
221
+ */
222
+ const trapAsyncCallbackInvocation = async (fn) => {
223
+ return new Promise((resolve, _reject) => {
224
+ let called = false;
225
+ let error;
226
+ let value;
227
+ let args = [];
228
+ const callback = (...cbArgs) => {
229
+ called = true;
230
+ args = cbArgs;
231
+ if (cbArgs.length >= 1) {
232
+ value = cbArgs[0];
233
+ }
234
+ resolve({ args, called, error, value });
235
+ };
236
+ const proxiedFn = new Proxy(fn, {
237
+ apply(target, thisArg, argumentsList) {
238
+ try {
239
+ return Reflect.apply(target, thisArg, argumentsList);
240
+ }
241
+ catch (thrownError) {
242
+ error = thrownError;
243
+ resolve({ args, called, error, value });
244
+ }
245
+ },
246
+ });
247
+ try {
248
+ proxiedFn(callback);
249
+ }
250
+ catch (thrownError) {
251
+ error = thrownError;
252
+ resolve({ args, called, error, value });
253
+ }
254
+ });
255
+ };
256
+ /**
257
+ * Traps the invocation of a nodeback (error-first callback) function for
258
+ * asynchronous testing. Returns a Promise that resolves with invocation details
259
+ * once the nodeback is called or an error occurs. Uses a Proxy to catch errors
260
+ * during function execution. Always resolves (never rejects) to allow assertion
261
+ * logic to handle error conditions.
262
+ *
263
+ * @param fn - The function to execute that should call the provided nodeback
264
+ * @returns Promise resolving to object with invocation details: args, called,
265
+ * error, and value
266
+ */
267
+ const trapAsyncNodebackInvocation = async (fn) => {
268
+ return new Promise((resolve, _reject) => {
269
+ let called = false;
270
+ let error;
271
+ let value;
272
+ let args = [];
273
+ const nodeback = (err, val) => {
274
+ called = true;
275
+ args = [err, val];
276
+ error = err;
277
+ value = val;
278
+ // Always resolve with the result data, don't reject on nodeback errors
279
+ // The assertion logic will check if error is truthy
280
+ resolve({ args, called, error, value });
281
+ };
282
+ const proxiedFn = new Proxy(fn, {
283
+ apply(target, thisArg, argumentsList) {
284
+ try {
285
+ return Reflect.apply(target, thisArg, argumentsList);
286
+ }
287
+ catch (thrownError) {
288
+ error = thrownError;
289
+ resolve({ args, called, error, value });
290
+ }
291
+ },
292
+ });
293
+ try {
294
+ proxiedFn(nodeback);
295
+ }
296
+ catch (thrownError) {
297
+ error = thrownError;
298
+ resolve({ args, called, error, value });
299
+ }
300
+ });
301
+ };
302
+ export const CallbackSyncAssertions = [
303
+ // Basic callback invocation - synchronous
304
+ createAssertion([FunctionSchema, ['to call callback', 'to invoke callback']], (subject) => {
305
+ const { called } = trapCallbackInvocation(subject);
306
+ return called;
307
+ }),
308
+ createAssertion([FunctionSchema, ['to call nodeback', 'to invoke nodeback']], (subject) => {
309
+ const { called } = trapNodebackInvocation(subject);
310
+ return called;
311
+ }),
312
+ // Callback with value - deep equality check
313
+ createAssertion([
314
+ FunctionSchema,
315
+ ['to call callback with', 'to invoke callback with'],
316
+ z.unknown(),
317
+ ], (subject, param) => {
318
+ const { called, value } = trapCallbackInvocation(subject);
319
+ /* c8 ignore next */
320
+ if (!called) {
321
+ return createNotCalledError('callback');
322
+ }
323
+ return validateValue(value, param, valueToSchemaOptionsForDeepEqual);
324
+ }),
325
+ // Callback with exact value - strict equality check
326
+ createAssertion([
327
+ FunctionSchema,
328
+ [
329
+ 'to call callback with exactly',
330
+ 'to call callback with exact value',
331
+ 'to invoke callback with exactly',
332
+ 'to invoke callback with exact value',
333
+ ],
334
+ z.unknown(),
335
+ ], (subject, expected) => {
336
+ const { called, value } = trapCallbackInvocation(subject);
337
+ /* c8 ignore next */
338
+ if (!called) {
339
+ return createNotCalledError('callback');
340
+ }
341
+ if (!Object.is(value, expected)) {
342
+ return createValueMismatchError(value, expected, 'callback');
343
+ }
344
+ }),
345
+ // Nodeback with value - deep equality check
346
+ createAssertion([
347
+ FunctionSchema,
348
+ ['to call nodeback with', 'to invoke nodeback with'],
349
+ z.unknown(),
350
+ ], (subject, param) => {
351
+ const { called, error, value } = trapNodebackInvocation(subject);
352
+ /* c8 ignore next */
353
+ if (!called) {
354
+ return createNotCalledError('nodeback');
355
+ }
356
+ const errorResult = createErrorMismatchError(!!error, false, error);
357
+ if (errorResult) {
358
+ return errorResult;
359
+ }
360
+ return validateValue(value, param, valueToSchemaOptionsForDeepEqual);
361
+ }),
362
+ // Nodeback with exact value - strict equality check
363
+ createAssertion([
364
+ FunctionSchema,
365
+ [
366
+ 'to call nodeback with exactly',
367
+ 'to call nodeback with exact value',
368
+ 'to invoke nodeback with exactly',
369
+ 'to invoke nodeback with exact value',
370
+ ],
371
+ z.unknown(),
372
+ ], (subject, expected) => {
373
+ const { called, error, value } = trapNodebackInvocation(subject);
374
+ /* c8 ignore next */
375
+ if (!called) {
376
+ return createNotCalledError('nodeback');
377
+ }
378
+ const errorResult = createErrorMismatchError(!!error, false, error);
379
+ if (errorResult) {
380
+ return errorResult;
381
+ }
382
+ if (!Object.is(value, expected)) {
383
+ return createValueMismatchError(value, expected, 'nodeback');
384
+ }
385
+ }),
386
+ // Nodeback with error - synchronous
387
+ createAssertion([
388
+ FunctionSchema,
389
+ ['to call nodeback with error', 'to invoke nodeback with error'],
390
+ ], (subject) => {
391
+ const { called, error } = trapNodebackInvocation(subject);
392
+ /* c8 ignore next */
393
+ if (!called) {
394
+ return createNotCalledError('nodeback');
395
+ }
396
+ return createErrorMismatchError(!!error, true, error);
397
+ }),
398
+ // Nodeback with specific error class - synchronous
399
+ createAssertion([
400
+ FunctionSchema,
401
+ [
402
+ 'to call nodeback with a',
403
+ 'to call nodeback with an',
404
+ 'to invoke nodeback with a',
405
+ 'to invoke nodeback with an',
406
+ ],
407
+ ClassSchema,
408
+ ], (subject, ctor) => {
409
+ const { called, error } = trapNodebackInvocation(subject);
410
+ /* c8 ignore next */
411
+ if (!called) {
412
+ return createNotCalledError('nodeback');
413
+ }
414
+ const errorResult = createErrorMismatchError(!!error, true, error);
415
+ if (errorResult) {
416
+ return errorResult;
417
+ }
418
+ if (!isA(error, ctor)) {
419
+ return {
420
+ actual: error,
421
+ expected: `instance of ${ctor.name}`,
422
+ message: `Expected nodeback to be called with an instance of ${ctor.name}, but it was called with ${inspect(error, { depth: 2 })}`,
423
+ };
424
+ }
425
+ }),
426
+ // Nodeback with specific error pattern - synchronous
427
+ createAssertion([
428
+ FunctionSchema,
429
+ ['to call nodeback with error', 'to invoke nodeback with error'],
430
+ z.union([z.string(), z.instanceof(RegExp), z.looseObject({})]),
431
+ ], (subject, param) => {
432
+ const { called, error } = trapNodebackInvocation(subject);
433
+ /* c8 ignore next */
434
+ if (!called) {
435
+ return createNotCalledError('nodeback');
436
+ }
437
+ const errorResult = createErrorMismatchError(!!error, true, error);
438
+ if (errorResult) {
439
+ return errorResult;
440
+ }
441
+ const schema = createErrorSchema(param);
442
+ const result = schema.safeParse(error);
443
+ if (!result.success) {
444
+ return result.error;
445
+ }
446
+ }),
447
+ // Callback satisfying pattern - partial matching
448
+ createAssertion([
449
+ FunctionSchema,
450
+ [
451
+ 'to call callback with value satisfying',
452
+ 'to invoke callback with value satisfying',
453
+ ],
454
+ z.union([z.string(), z.instanceof(RegExp), z.looseObject({})]),
455
+ ], (subject, param) => {
456
+ const { called, value } = trapCallbackInvocation(subject);
457
+ /* c8 ignore next */
458
+ if (!called) {
459
+ return createNotCalledError('callback');
460
+ }
461
+ return validateValue(value, param, valueToSchemaOptionsForSatisfies);
462
+ }),
463
+ // Nodeback satisfying pattern - partial matching
464
+ createAssertion([
465
+ FunctionSchema,
466
+ [
467
+ 'to call nodeback with value satisfying',
468
+ 'to invoke nodeback with value satisfying',
469
+ ],
470
+ z.union([z.string(), z.instanceof(RegExp), z.looseObject({})]),
471
+ ], (subject, param) => {
472
+ const { called, error, value } = trapNodebackInvocation(subject);
473
+ /* c8 ignore next */
474
+ if (!called) {
475
+ return createNotCalledError('nodeback');
476
+ }
477
+ const errorResult = createErrorMismatchError(!!error, false, error);
478
+ if (errorResult) {
479
+ return errorResult;
480
+ }
481
+ return validateValue(value, param, valueToSchemaOptionsForSatisfies);
482
+ }),
483
+ ];
484
+ export const CallbackAsyncAssertions = [
485
+ // Async versions
486
+ createAsyncAssertion([
487
+ FunctionSchema,
488
+ ['to eventually call callback', 'to eventually invoke callback'],
489
+ ], async (subject) => {
490
+ const { called } = await trapAsyncCallbackInvocation(subject);
491
+ /* c8 ignore next */
492
+ if (!called) {
493
+ return {
494
+ actual: 'callback not called',
495
+ expected: 'callback to be called',
496
+ message: `Expected callback to be called, but it was not`,
497
+ };
498
+ }
499
+ }),
500
+ createAsyncAssertion([
501
+ FunctionSchema,
502
+ ['to eventually call nodeback', 'to eventually invoke nodeback'],
503
+ ], async (subject) => {
504
+ const { called } = await trapAsyncNodebackInvocation(subject);
505
+ /* c8 ignore next */
506
+ if (!called) {
507
+ return {
508
+ actual: 'nodeback not called',
509
+ expected: 'nodeback to be called',
510
+ message: `Expected nodeback to be called, but it was not`,
511
+ };
512
+ }
513
+ }),
514
+ // Async callback with value - deep equality check
515
+ createAsyncAssertion([
516
+ FunctionSchema,
517
+ [
518
+ 'to eventually call callback with',
519
+ 'to eventually invoke callback with',
520
+ ],
521
+ z.unknown(),
522
+ ], async (subject, param) => {
523
+ const { called, value } = await trapAsyncCallbackInvocation(subject);
524
+ /* c8 ignore next */
525
+ if (!called) {
526
+ return createAsyncNotCalledError('callback');
527
+ }
528
+ return validateValue(value, param, valueToSchemaOptionsForDeepEqual);
529
+ }),
530
+ // Async callback with exact value - strict equality check
531
+ createAsyncAssertion([
532
+ FunctionSchema,
533
+ [
534
+ 'to eventually call callback with exactly',
535
+ 'to eventually call callback with exact value',
536
+ 'to eventually invoke callback with exactly',
537
+ 'to eventually invoke callback with exact value',
538
+ ],
539
+ z.unknown(),
540
+ ], async (subject, expected) => {
541
+ const { called, value } = await trapAsyncCallbackInvocation(subject);
542
+ /* c8 ignore next */
543
+ if (!called) {
544
+ return createAsyncNotCalledError('callback');
545
+ }
546
+ return Object.is(value, expected);
547
+ }),
548
+ // Async nodeback with value - deep equality check
549
+ createAsyncAssertion([
550
+ FunctionSchema,
551
+ [
552
+ 'to eventually call nodeback with',
553
+ 'to eventually invoke nodeback with',
554
+ ],
555
+ z.unknown(),
556
+ ], async (subject, param) => {
557
+ const { called, error, value } = await trapAsyncNodebackInvocation(subject);
558
+ /* c8 ignore next */
559
+ if (!called) {
560
+ return createAsyncNotCalledError('nodeback');
561
+ }
562
+ const errorResult = createAsyncErrorMismatchError(!!error, false, error);
563
+ if (errorResult) {
564
+ return errorResult;
565
+ }
566
+ return validateValue(value, param, valueToSchemaOptionsForDeepEqual);
567
+ }),
568
+ // Async nodeback with exact value - strict equality check
569
+ createAsyncAssertion([
570
+ FunctionSchema,
571
+ [
572
+ 'to eventually call nodeback with exactly',
573
+ 'to eventually call nodeback with exact value',
574
+ 'to eventually invoke nodeback with exactly',
575
+ 'to eventually invoke nodeback with exact value',
576
+ ],
577
+ z.unknown(),
578
+ ], async (subject, expected) => {
579
+ const { called, error, value } = await trapAsyncNodebackInvocation(subject);
580
+ /* c8 ignore next */
581
+ if (!called) {
582
+ return createAsyncNotCalledError('nodeback');
583
+ }
584
+ const errorResult = createAsyncErrorMismatchError(!!error, false, error);
585
+ if (errorResult) {
586
+ return errorResult;
587
+ }
588
+ return Object.is(value, expected);
589
+ }),
590
+ createAsyncAssertion([
591
+ FunctionSchema,
592
+ [
593
+ 'to eventually call nodeback with error',
594
+ 'to eventually invoke nodeback with error',
595
+ ],
596
+ ], async (subject) => {
597
+ const { called, error } = await trapAsyncNodebackInvocation(subject);
598
+ /* c8 ignore next */
599
+ if (!called) {
600
+ return createAsyncNotCalledError('nodeback');
601
+ }
602
+ return createAsyncErrorMismatchError(!!error, true, error);
603
+ }),
604
+ createAsyncAssertion([
605
+ FunctionSchema,
606
+ [
607
+ 'to eventually call nodeback with a',
608
+ 'to eventually call nodeback with an',
609
+ 'to eventually invoke nodeback with a',
610
+ 'to eventually invoke nodeback with an',
611
+ ],
612
+ ClassSchema,
613
+ ], async (subject, ctor) => {
614
+ const { called, error } = await trapAsyncNodebackInvocation(subject);
615
+ /* c8 ignore next */
616
+ if (!called) {
617
+ return createAsyncNotCalledError('nodeback');
618
+ }
619
+ const errorResult = createAsyncErrorMismatchError(!!error, true, error);
620
+ if (errorResult) {
621
+ return errorResult;
622
+ }
623
+ if (!isA(error, ctor)) {
624
+ return {
625
+ actual: error,
626
+ expected: `instance of ${ctor.name}`,
627
+ message: `Expected nodeback to be called with an instance of ${ctor.name}, but it was called with ${inspect(error, { depth: 2 })}`,
628
+ };
629
+ }
630
+ }),
631
+ createAsyncAssertion([
632
+ FunctionSchema,
633
+ [
634
+ 'to eventually call nodeback with error',
635
+ 'to eventually invoke nodeback with error',
636
+ ],
637
+ z.union([z.string(), z.instanceof(RegExp), z.looseObject({})]),
638
+ ], async (subject, param) => {
639
+ const { called, error } = await trapAsyncNodebackInvocation(subject);
640
+ /* c8 ignore next */
641
+ if (!called) {
642
+ return createAsyncNotCalledError('nodeback');
643
+ }
644
+ const errorResult = createAsyncErrorMismatchError(!!error, true, error);
645
+ if (errorResult) {
646
+ return errorResult;
647
+ }
648
+ const schema = createErrorSchema(param);
649
+ const result = schema.safeParse(error);
650
+ if (!result.success) {
651
+ return result.error;
652
+ }
653
+ }),
654
+ // Async callback satisfying pattern - partial matching
655
+ createAsyncAssertion([
656
+ FunctionSchema,
657
+ [
658
+ 'to eventually call callback with value satisfying',
659
+ 'to eventually invoke callback with value satisfying',
660
+ ],
661
+ z.union([z.string(), z.instanceof(RegExp), z.looseObject({})]),
662
+ ], async (subject, param) => {
663
+ const { called, value } = await trapAsyncCallbackInvocation(subject);
664
+ /* c8 ignore next */
665
+ if (!called) {
666
+ return createAsyncNotCalledError('callback');
667
+ }
668
+ return validateValue(value, param, valueToSchemaOptionsForSatisfies);
669
+ }),
670
+ // Async nodeback satisfying pattern - partial matching
671
+ createAsyncAssertion([
672
+ FunctionSchema,
673
+ [
674
+ 'to eventually call nodeback with value satisfying',
675
+ 'to eventually invoke nodeback with value satisfying',
676
+ ],
677
+ z.union([z.string(), z.instanceof(RegExp), z.looseObject({})]),
678
+ ], async (subject, param) => {
679
+ const { called, error, value } = await trapAsyncNodebackInvocation(subject);
680
+ /* c8 ignore next */
681
+ if (!called) {
682
+ return createAsyncNotCalledError('nodeback');
683
+ }
684
+ const errorResult = createAsyncErrorMismatchError(!!error, false, error);
685
+ if (errorResult) {
686
+ return errorResult;
687
+ }
688
+ return validateValue(value, param, valueToSchemaOptionsForSatisfies);
689
+ }),
690
+ ];
691
+ //# sourceMappingURL=callback.js.map