bupkis 0.18.3 → 1.0.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 (388) hide show
  1. package/CHANGELOG.md +21 -0
  2. package/README.md +1 -1
  3. package/dist/assertion/assertion-async.cjs +268 -0
  4. package/dist/assertion/assertion-async.cjs.map +1 -0
  5. package/dist/assertion/assertion-async.d.cts +40 -0
  6. package/dist/assertion/assertion-async.d.cts.map +1 -0
  7. package/dist/assertion/assertion-async.d.ts +40 -0
  8. package/dist/assertion/assertion-async.d.ts.map +1 -0
  9. package/dist/assertion/assertion-async.js +259 -0
  10. package/dist/assertion/assertion-async.js.map +1 -0
  11. package/dist/assertion/assertion-standard-schema-async.cjs +132 -0
  12. package/dist/assertion/assertion-standard-schema-async.cjs.map +1 -0
  13. package/dist/assertion/assertion-standard-schema-async.d.cts +52 -0
  14. package/dist/assertion/assertion-standard-schema-async.d.cts.map +1 -0
  15. package/dist/assertion/assertion-standard-schema-async.d.ts +52 -0
  16. package/dist/assertion/assertion-standard-schema-async.d.ts.map +1 -0
  17. package/dist/assertion/assertion-standard-schema-async.js +128 -0
  18. package/dist/assertion/assertion-standard-schema-async.js.map +1 -0
  19. package/dist/assertion/assertion-standard-schema-sync.cjs +141 -0
  20. package/dist/assertion/assertion-standard-schema-sync.cjs.map +1 -0
  21. package/dist/assertion/assertion-standard-schema-sync.d.cts +52 -0
  22. package/dist/assertion/assertion-standard-schema-sync.d.cts.map +1 -0
  23. package/dist/assertion/assertion-standard-schema-sync.d.ts +52 -0
  24. package/dist/assertion/assertion-standard-schema-sync.d.ts.map +1 -0
  25. package/dist/assertion/assertion-standard-schema-sync.js +137 -0
  26. package/dist/assertion/assertion-standard-schema-sync.js.map +1 -0
  27. package/dist/assertion/assertion-sync.cjs +281 -0
  28. package/dist/assertion/assertion-sync.cjs.map +1 -0
  29. package/dist/assertion/assertion-sync.d.cts +60 -0
  30. package/dist/assertion/assertion-sync.d.cts.map +1 -0
  31. package/dist/assertion/assertion-sync.d.ts +60 -0
  32. package/dist/assertion/assertion-sync.d.ts.map +1 -0
  33. package/dist/assertion/assertion-sync.js +275 -0
  34. package/dist/assertion/assertion-sync.js.map +1 -0
  35. package/dist/assertion/assertion-types.cjs +20 -0
  36. package/dist/assertion/assertion-types.cjs.map +1 -0
  37. package/dist/assertion/assertion-types.d.cts +1086 -0
  38. package/dist/assertion/assertion-types.d.cts.map +1 -0
  39. package/dist/assertion/assertion-types.d.ts +1086 -0
  40. package/dist/assertion/assertion-types.d.ts.map +1 -0
  41. package/dist/assertion/assertion-types.js +19 -0
  42. package/dist/assertion/assertion-types.js.map +1 -0
  43. package/dist/assertion/assertion.cjs +382 -0
  44. package/dist/assertion/assertion.cjs.map +1 -0
  45. package/dist/assertion/assertion.d.cts +109 -0
  46. package/dist/assertion/assertion.d.cts.map +1 -0
  47. package/dist/assertion/assertion.d.ts +109 -0
  48. package/dist/assertion/assertion.d.ts.map +1 -0
  49. package/dist/assertion/assertion.js +375 -0
  50. package/dist/assertion/assertion.js.map +1 -0
  51. package/dist/assertion/create.cjs +148 -0
  52. package/dist/assertion/create.cjs.map +1 -0
  53. package/dist/assertion/create.d.cts +85 -0
  54. package/dist/assertion/create.d.cts.map +1 -0
  55. package/dist/assertion/create.d.ts +85 -0
  56. package/dist/assertion/create.d.ts.map +1 -0
  57. package/dist/assertion/create.js +143 -0
  58. package/dist/assertion/create.js.map +1 -0
  59. package/dist/assertion/format-assertion-failure.cjs +63 -0
  60. package/dist/assertion/format-assertion-failure.cjs.map +1 -0
  61. package/dist/assertion/format-assertion-failure.d.cts +21 -0
  62. package/dist/assertion/format-assertion-failure.d.cts.map +1 -0
  63. package/dist/assertion/format-assertion-failure.d.ts +21 -0
  64. package/dist/assertion/format-assertion-failure.d.ts.map +1 -0
  65. package/dist/assertion/format-assertion-failure.js +59 -0
  66. package/dist/assertion/format-assertion-failure.js.map +1 -0
  67. package/dist/assertion/impl/assertion-util.cjs +68 -0
  68. package/dist/assertion/impl/assertion-util.cjs.map +1 -0
  69. package/dist/assertion/impl/assertion-util.d.cts +36 -0
  70. package/dist/assertion/impl/assertion-util.d.cts.map +1 -0
  71. package/dist/assertion/impl/assertion-util.d.ts +36 -0
  72. package/dist/assertion/impl/assertion-util.d.ts.map +1 -0
  73. package/dist/assertion/impl/assertion-util.js +62 -0
  74. package/dist/assertion/impl/assertion-util.js.map +1 -0
  75. package/dist/assertion/impl/async-iterable.cjs +627 -0
  76. package/dist/assertion/impl/async-iterable.cjs.map +1 -0
  77. package/dist/assertion/impl/async-iterable.d.cts +406 -0
  78. package/dist/assertion/impl/async-iterable.d.cts.map +1 -0
  79. package/dist/assertion/impl/async-iterable.d.ts +406 -0
  80. package/dist/assertion/impl/async-iterable.d.ts.map +1 -0
  81. package/dist/assertion/impl/async-iterable.js +624 -0
  82. package/dist/assertion/impl/async-iterable.js.map +1 -0
  83. package/dist/assertion/impl/async-parametric.cjs +412 -0
  84. package/dist/assertion/impl/async-parametric.cjs.map +1 -0
  85. package/dist/assertion/impl/async-parametric.d.cts +278 -0
  86. package/dist/assertion/impl/async-parametric.d.cts.map +1 -0
  87. package/dist/assertion/impl/async-parametric.d.ts +278 -0
  88. package/dist/assertion/impl/async-parametric.d.ts.map +1 -0
  89. package/dist/assertion/impl/async-parametric.js +409 -0
  90. package/dist/assertion/impl/async-parametric.js.map +1 -0
  91. package/dist/assertion/impl/async.cjs +56 -0
  92. package/dist/assertion/impl/async.cjs.map +1 -0
  93. package/dist/assertion/impl/async.d.cts +179 -0
  94. package/dist/assertion/impl/async.d.cts.map +1 -0
  95. package/dist/assertion/impl/async.d.ts +179 -0
  96. package/dist/assertion/impl/async.d.ts.map +1 -0
  97. package/dist/assertion/impl/async.js +39 -0
  98. package/dist/assertion/impl/async.js.map +1 -0
  99. package/dist/assertion/impl/index.cjs +37 -0
  100. package/dist/assertion/impl/index.cjs.map +1 -0
  101. package/dist/assertion/impl/index.d.cts +21 -0
  102. package/dist/assertion/impl/index.d.cts.map +1 -0
  103. package/dist/assertion/impl/index.d.ts +21 -0
  104. package/dist/assertion/impl/index.d.ts.map +1 -0
  105. package/dist/assertion/impl/index.js +21 -0
  106. package/dist/assertion/impl/index.js.map +1 -0
  107. package/dist/assertion/impl/iteration-util.cjs +297 -0
  108. package/dist/assertion/impl/iteration-util.cjs.map +1 -0
  109. package/dist/assertion/impl/iteration-util.d.cts +12 -0
  110. package/dist/assertion/impl/iteration-util.d.cts.map +1 -0
  111. package/dist/assertion/impl/iteration-util.d.ts +12 -0
  112. package/dist/assertion/impl/iteration-util.d.ts.map +1 -0
  113. package/dist/assertion/impl/iteration-util.js +282 -0
  114. package/dist/assertion/impl/iteration-util.js.map +1 -0
  115. package/dist/assertion/impl/snapshot.cjs +276 -0
  116. package/dist/assertion/impl/snapshot.cjs.map +1 -0
  117. package/dist/assertion/impl/snapshot.d.cts +278 -0
  118. package/dist/assertion/impl/snapshot.d.cts.map +1 -0
  119. package/dist/assertion/impl/snapshot.d.ts +278 -0
  120. package/dist/assertion/impl/snapshot.d.ts.map +1 -0
  121. package/dist/assertion/impl/snapshot.js +273 -0
  122. package/dist/assertion/impl/snapshot.js.map +1 -0
  123. package/dist/assertion/impl/sync-basic.cjs +553 -0
  124. package/dist/assertion/impl/sync-basic.cjs.map +1 -0
  125. package/dist/assertion/impl/sync-basic.d.cts +528 -0
  126. package/dist/assertion/impl/sync-basic.d.cts.map +1 -0
  127. package/dist/assertion/impl/sync-basic.d.ts +528 -0
  128. package/dist/assertion/impl/sync-basic.d.ts.map +1 -0
  129. package/dist/assertion/impl/sync-basic.js +550 -0
  130. package/dist/assertion/impl/sync-basic.js.map +1 -0
  131. package/dist/assertion/impl/sync-collection.cjs +1424 -0
  132. package/dist/assertion/impl/sync-collection.cjs.map +1 -0
  133. package/dist/assertion/impl/sync-collection.d.cts +922 -0
  134. package/dist/assertion/impl/sync-collection.d.cts.map +1 -0
  135. package/dist/assertion/impl/sync-collection.d.ts +922 -0
  136. package/dist/assertion/impl/sync-collection.d.ts.map +1 -0
  137. package/dist/assertion/impl/sync-collection.js +1418 -0
  138. package/dist/assertion/impl/sync-collection.js.map +1 -0
  139. package/dist/assertion/impl/sync-date.cjs +341 -0
  140. package/dist/assertion/impl/sync-date.cjs.map +1 -0
  141. package/dist/assertion/impl/sync-date.d.cts +209 -0
  142. package/dist/assertion/impl/sync-date.d.cts.map +1 -0
  143. package/dist/assertion/impl/sync-date.d.ts +209 -0
  144. package/dist/assertion/impl/sync-date.d.ts.map +1 -0
  145. package/dist/assertion/impl/sync-date.js +338 -0
  146. package/dist/assertion/impl/sync-date.js.map +1 -0
  147. package/dist/assertion/impl/sync-esoteric.cjs +214 -0
  148. package/dist/assertion/impl/sync-esoteric.cjs.map +1 -0
  149. package/dist/assertion/impl/sync-esoteric.d.cts +191 -0
  150. package/dist/assertion/impl/sync-esoteric.d.cts.map +1 -0
  151. package/dist/assertion/impl/sync-esoteric.d.ts +191 -0
  152. package/dist/assertion/impl/sync-esoteric.d.ts.map +1 -0
  153. package/dist/assertion/impl/sync-esoteric.js +211 -0
  154. package/dist/assertion/impl/sync-esoteric.js.map +1 -0
  155. package/dist/assertion/impl/sync-iterable.cjs +512 -0
  156. package/dist/assertion/impl/sync-iterable.cjs.map +1 -0
  157. package/dist/assertion/impl/sync-iterable.d.cts +334 -0
  158. package/dist/assertion/impl/sync-iterable.d.cts.map +1 -0
  159. package/dist/assertion/impl/sync-iterable.d.ts +334 -0
  160. package/dist/assertion/impl/sync-iterable.d.ts.map +1 -0
  161. package/dist/assertion/impl/sync-iterable.js +509 -0
  162. package/dist/assertion/impl/sync-iterable.js.map +1 -0
  163. package/dist/assertion/impl/sync-parametric.cjs +805 -0
  164. package/dist/assertion/impl/sync-parametric.cjs.map +1 -0
  165. package/dist/assertion/impl/sync-parametric.d.cts +560 -0
  166. package/dist/assertion/impl/sync-parametric.d.cts.map +1 -0
  167. package/dist/assertion/impl/sync-parametric.d.ts +560 -0
  168. package/dist/assertion/impl/sync-parametric.d.ts.map +1 -0
  169. package/dist/assertion/impl/sync-parametric.js +802 -0
  170. package/dist/assertion/impl/sync-parametric.js.map +1 -0
  171. package/dist/assertion/impl/sync.cjs +229 -0
  172. package/dist/assertion/impl/sync.cjs.map +1 -0
  173. package/dist/assertion/impl/sync.d.cts +536 -0
  174. package/dist/assertion/impl/sync.d.cts.map +1 -0
  175. package/dist/assertion/impl/sync.d.ts +536 -0
  176. package/dist/assertion/impl/sync.d.ts.map +1 -0
  177. package/dist/assertion/impl/sync.js +212 -0
  178. package/dist/assertion/impl/sync.js.map +1 -0
  179. package/dist/assertion/index.cjs +38 -0
  180. package/dist/assertion/index.cjs.map +1 -0
  181. package/dist/assertion/index.d.cts +18 -0
  182. package/dist/assertion/index.d.cts.map +1 -0
  183. package/dist/assertion/index.d.ts +18 -0
  184. package/dist/assertion/index.d.ts.map +1 -0
  185. package/dist/assertion/index.js +17 -0
  186. package/dist/assertion/index.js.map +1 -0
  187. package/dist/assertion/slotify.cjs +165 -0
  188. package/dist/assertion/slotify.cjs.map +1 -0
  189. package/dist/assertion/slotify.d.cts +11 -0
  190. package/dist/assertion/slotify.d.cts.map +1 -0
  191. package/dist/assertion/slotify.d.ts +11 -0
  192. package/dist/assertion/slotify.d.ts.map +1 -0
  193. package/dist/assertion/slotify.js +161 -0
  194. package/dist/assertion/slotify.js.map +1 -0
  195. package/dist/bootstrap.cjs +43 -0
  196. package/dist/bootstrap.cjs.map +1 -0
  197. package/dist/bootstrap.d.cts +27 -0
  198. package/dist/bootstrap.d.cts.map +1 -0
  199. package/dist/bootstrap.d.ts +27 -0
  200. package/dist/bootstrap.d.ts.map +1 -0
  201. package/dist/bootstrap.js +40 -0
  202. package/dist/bootstrap.js.map +1 -0
  203. package/dist/constant.cjs +82 -0
  204. package/dist/constant.cjs.map +1 -0
  205. package/dist/constant.d.cts +69 -0
  206. package/dist/constant.d.cts.map +1 -0
  207. package/dist/constant.d.ts +69 -0
  208. package/dist/constant.d.ts.map +1 -0
  209. package/dist/constant.js +79 -0
  210. package/dist/constant.js.map +1 -0
  211. package/dist/diff.cjs +340 -0
  212. package/dist/diff.cjs.map +1 -0
  213. package/dist/diff.d.cts +51 -0
  214. package/dist/diff.d.cts.map +1 -0
  215. package/dist/diff.d.ts +51 -0
  216. package/dist/diff.d.ts.map +1 -0
  217. package/dist/diff.js +334 -0
  218. package/dist/diff.js.map +1 -0
  219. package/dist/error.cjs +194 -0
  220. package/dist/error.cjs.map +1 -0
  221. package/dist/error.d.cts +212 -0
  222. package/dist/error.d.cts.map +1 -0
  223. package/dist/error.d.ts +212 -0
  224. package/dist/error.d.ts.map +1 -0
  225. package/dist/error.js +181 -0
  226. package/dist/error.js.map +1 -0
  227. package/dist/expect.cjs +587 -0
  228. package/dist/expect.cjs.map +1 -0
  229. package/dist/expect.d.cts +138 -0
  230. package/dist/expect.d.cts.map +1 -0
  231. package/dist/expect.d.ts +138 -0
  232. package/dist/expect.d.ts.map +1 -0
  233. package/dist/expect.js +582 -0
  234. package/dist/expect.js.map +1 -0
  235. package/dist/guards.cjs +291 -0
  236. package/dist/guards.cjs.map +1 -0
  237. package/dist/guards.d.cts +225 -0
  238. package/dist/guards.d.cts.map +1 -0
  239. package/dist/guards.d.ts +225 -0
  240. package/dist/guards.d.ts.map +1 -0
  241. package/dist/guards.js +273 -0
  242. package/dist/guards.js.map +1 -0
  243. package/dist/index.cjs +111 -0
  244. package/dist/index.cjs.map +1 -0
  245. package/dist/index.d.cts +460 -0
  246. package/dist/index.d.cts.map +1 -0
  247. package/dist/index.d.ts +460 -0
  248. package/dist/index.d.ts.map +1 -0
  249. package/dist/index.js +71 -0
  250. package/dist/index.js.map +1 -0
  251. package/dist/internal-schema.cjs +234 -0
  252. package/dist/internal-schema.cjs.map +1 -0
  253. package/dist/internal-schema.d.cts +8 -0
  254. package/dist/internal-schema.d.cts.map +1 -0
  255. package/dist/internal-schema.d.ts +8 -0
  256. package/dist/internal-schema.d.ts.map +1 -0
  257. package/dist/internal-schema.js +229 -0
  258. package/dist/internal-schema.js.map +1 -0
  259. package/dist/metadata.cjs +57 -0
  260. package/dist/metadata.cjs.map +1 -0
  261. package/dist/metadata.d.cts +27 -0
  262. package/dist/metadata.d.cts.map +1 -0
  263. package/dist/metadata.d.ts +27 -0
  264. package/dist/metadata.d.ts.map +1 -0
  265. package/dist/metadata.js +54 -0
  266. package/dist/metadata.js.map +1 -0
  267. package/dist/schema.cjs +1522 -0
  268. package/dist/schema.cjs.map +1 -0
  269. package/dist/schema.d.cts +1196 -0
  270. package/dist/schema.d.cts.map +1 -0
  271. package/dist/schema.d.ts +1196 -0
  272. package/dist/schema.d.ts.map +1 -0
  273. package/dist/schema.js +1516 -0
  274. package/dist/schema.js.map +1 -0
  275. package/dist/snapshot/adapter.cjs +29 -0
  276. package/dist/snapshot/adapter.cjs.map +1 -0
  277. package/dist/snapshot/adapter.d.cts +258 -0
  278. package/dist/snapshot/adapter.d.cts.map +1 -0
  279. package/dist/snapshot/adapter.d.ts +258 -0
  280. package/dist/snapshot/adapter.d.ts.map +1 -0
  281. package/dist/snapshot/adapter.js +25 -0
  282. package/dist/snapshot/adapter.js.map +1 -0
  283. package/dist/snapshot/adapters/fallback.cjs +452 -0
  284. package/dist/snapshot/adapters/fallback.cjs.map +1 -0
  285. package/dist/snapshot/adapters/fallback.d.cts +185 -0
  286. package/dist/snapshot/adapters/fallback.d.cts.map +1 -0
  287. package/dist/snapshot/adapters/fallback.d.ts +185 -0
  288. package/dist/snapshot/adapters/fallback.d.ts.map +1 -0
  289. package/dist/snapshot/adapters/fallback.js +445 -0
  290. package/dist/snapshot/adapters/fallback.js.map +1 -0
  291. package/dist/snapshot/adapters/node-test.cjs +297 -0
  292. package/dist/snapshot/adapters/node-test.cjs.map +1 -0
  293. package/dist/snapshot/adapters/node-test.d.cts +131 -0
  294. package/dist/snapshot/adapters/node-test.d.cts.map +1 -0
  295. package/dist/snapshot/adapters/node-test.d.ts +131 -0
  296. package/dist/snapshot/adapters/node-test.d.ts.map +1 -0
  297. package/dist/snapshot/adapters/node-test.js +293 -0
  298. package/dist/snapshot/adapters/node-test.js.map +1 -0
  299. package/dist/snapshot/index.cjs +61 -0
  300. package/dist/snapshot/index.cjs.map +1 -0
  301. package/dist/snapshot/index.d.cts +40 -0
  302. package/dist/snapshot/index.d.cts.map +1 -0
  303. package/dist/snapshot/index.d.ts +40 -0
  304. package/dist/snapshot/index.d.ts.map +1 -0
  305. package/dist/snapshot/index.js +44 -0
  306. package/dist/snapshot/index.js.map +1 -0
  307. package/dist/snapshot/node-version.cjs +49 -0
  308. package/dist/snapshot/node-version.cjs.map +1 -0
  309. package/dist/snapshot/node-version.d.cts +34 -0
  310. package/dist/snapshot/node-version.d.cts.map +1 -0
  311. package/dist/snapshot/node-version.d.ts +34 -0
  312. package/dist/snapshot/node-version.d.ts.map +1 -0
  313. package/dist/snapshot/node-version.js +44 -0
  314. package/dist/snapshot/node-version.js.map +1 -0
  315. package/dist/snapshot/select-adapter.cjs +170 -0
  316. package/dist/snapshot/select-adapter.cjs.map +1 -0
  317. package/dist/snapshot/select-adapter.d.cts +128 -0
  318. package/dist/snapshot/select-adapter.d.cts.map +1 -0
  319. package/dist/snapshot/select-adapter.d.ts +128 -0
  320. package/dist/snapshot/select-adapter.d.ts.map +1 -0
  321. package/dist/snapshot/select-adapter.js +164 -0
  322. package/dist/snapshot/select-adapter.js.map +1 -0
  323. package/dist/snapshot/serializer.cjs +245 -0
  324. package/dist/snapshot/serializer.cjs.map +1 -0
  325. package/dist/snapshot/serializer.d.cts +126 -0
  326. package/dist/snapshot/serializer.d.cts.map +1 -0
  327. package/dist/snapshot/serializer.d.ts +126 -0
  328. package/dist/snapshot/serializer.d.ts.map +1 -0
  329. package/dist/snapshot/serializer.js +237 -0
  330. package/dist/snapshot/serializer.js.map +1 -0
  331. package/dist/standard-schema.cjs +13 -0
  332. package/dist/standard-schema.cjs.map +1 -0
  333. package/dist/standard-schema.d.cts +192 -0
  334. package/dist/standard-schema.d.cts.map +1 -0
  335. package/dist/standard-schema.d.ts +192 -0
  336. package/dist/standard-schema.d.ts.map +1 -0
  337. package/dist/standard-schema.js +12 -0
  338. package/dist/standard-schema.js.map +1 -0
  339. package/dist/types.cjs +22 -0
  340. package/dist/types.cjs.map +1 -0
  341. package/dist/types.d.cts +756 -0
  342. package/dist/types.d.cts.map +1 -0
  343. package/dist/types.d.ts +756 -0
  344. package/dist/types.d.ts.map +1 -0
  345. package/dist/types.js +21 -0
  346. package/dist/types.js.map +1 -0
  347. package/dist/use.cjs +240 -0
  348. package/dist/use.cjs.map +1 -0
  349. package/dist/use.d.cts +8 -0
  350. package/dist/use.d.cts.map +1 -0
  351. package/dist/use.d.ts +8 -0
  352. package/dist/use.d.ts.map +1 -0
  353. package/dist/use.js +236 -0
  354. package/dist/use.js.map +1 -0
  355. package/dist/util.cjs +255 -0
  356. package/dist/util.cjs.map +1 -0
  357. package/dist/util.d.cts +141 -0
  358. package/dist/util.d.cts.map +1 -0
  359. package/dist/util.d.ts +141 -0
  360. package/dist/util.d.ts.map +1 -0
  361. package/dist/util.js +234 -0
  362. package/dist/util.js.map +1 -0
  363. package/dist/value-to-schema.cjs +537 -0
  364. package/dist/value-to-schema.cjs.map +1 -0
  365. package/dist/value-to-schema.d.cts +144 -0
  366. package/dist/value-to-schema.d.cts.map +1 -0
  367. package/dist/value-to-schema.d.ts +144 -0
  368. package/dist/value-to-schema.d.ts.map +1 -0
  369. package/dist/value-to-schema.js +533 -0
  370. package/dist/value-to-schema.js.map +1 -0
  371. package/package.json +22 -19
  372. package/src/assertion/assertion-types.ts +4 -8
  373. package/src/assertion/assertion.ts +1 -1
  374. package/src/assertion/format-assertion-failure.ts +2 -0
  375. package/src/assertion/impl/assertion-util.ts +1 -2
  376. package/src/assertion/impl/iteration-util.ts +1 -3
  377. package/src/assertion/impl/sync-collection.ts +633 -7
  378. package/src/assertion/impl/sync.ts +27 -0
  379. package/src/error.ts +13 -22
  380. package/src/guards.ts +8 -14
  381. package/src/internal-schema.ts +4 -8
  382. package/src/metadata.ts +1 -2
  383. package/src/snapshot/adapter.ts +2 -3
  384. package/src/snapshot/adapters/fallback.ts +2 -3
  385. package/src/snapshot/adapters/node-test.ts +14 -20
  386. package/src/snapshot/select-adapter.ts +3 -3
  387. package/src/snapshot/serializer.ts +2 -3
  388. package/src/types.ts +2 -162
@@ -0,0 +1,1418 @@
1
+ // do not remove; otherwise zshy will not resolve the .d.ts file; it must be referenced directly
2
+ // eslint-disable-next-line @typescript-eslint/triple-slash-reference
3
+ /// <reference path="./shims.d.ts" />
4
+ /**
5
+ * Collection-based assertions for arrays, objects, Maps, and Sets.
6
+ *
7
+ * These assertions handle operations like containment, size checking, and
8
+ * set-theoretic operations for various collection types including native
9
+ * JavaScript collections and WeakMap/WeakSet.
10
+ *
11
+ * @packageDocumentation
12
+ * @groupDescription Collection Assertions
13
+ * Assertions for arrays, objects, Maps, Sets, and collection operations.
14
+ *
15
+ * @showGroup
16
+ */
17
+ import { inspect } from 'node:util';
18
+ import setDifference from 'set.prototype.difference';
19
+ import setIntersection from 'set.prototype.intersection';
20
+ import isDisjointFrom from 'set.prototype.isdisjointfrom';
21
+ import isSubsetOf from 'set.prototype.issubsetof';
22
+ import isSupersetOf from 'set.prototype.issupersetof';
23
+ import symmetricDifference from 'set.prototype.symmetricdifference';
24
+ import setUnion from 'set.prototype.union';
25
+ import { z } from 'zod';
26
+ import { isWeakKey } from "../../guards.js";
27
+ import { AnyMapSchema, AnySetSchema, KeypathSchema, MapSchema, NonCollectionObjectSchema, NonNegativeIntegerSchema, PropertyKeySchema, SetSchema, UnknownArraySchema, UnknownRecordSchema, UnknownSchema, } from "../../schema.js";
28
+ import { has } from "../../util.js";
29
+ import { valueToSchema, valueToSchemaOptionsForDeepEqual, valueToSchemaOptionsForSatisfies, } from "../../value-to-schema.js";
30
+ import { createAssertion } from "../create.js";
31
+ const { hasOwn, keys } = Object;
32
+ /**
33
+ * Asserts that a Map or WeakMap contains a specific key. For WeakMap, the key
34
+ * must be an object.
35
+ *
36
+ * @example
37
+ *
38
+ * ```ts
39
+ * const map = new Map([['key', 'value']]);
40
+ * expect(map, 'to contain', 'key'); // passes
41
+ *
42
+ * const obj = {};
43
+ * const weakMap = new WeakMap([[obj, 'value']]);
44
+ * expect(weakMap, 'to contain', obj); // passes
45
+ * expect(weakMap, 'to contain', 'string'); // fails (not an object)
46
+ * ```
47
+ *
48
+ * @group Collection Assertions
49
+ * @bupkisAnchor map-to-contain-any
50
+ * @bupkisAssertionCategory collections
51
+ */
52
+ export const mapContainsAssertion = createAssertion([AnyMapSchema, ['to contain', 'to include'], UnknownSchema], (subject, key) => {
53
+ // WeakMap.has only works with object or symbol keys
54
+ let hasKey;
55
+ if (subject instanceof WeakMap) {
56
+ if (!isWeakKey(key)) {
57
+ return {
58
+ message: `WeakMap keys must be objects or symbols, got ${typeof key}`,
59
+ };
60
+ }
61
+ hasKey = subject.has(key);
62
+ }
63
+ else {
64
+ hasKey = subject.has(key);
65
+ }
66
+ if (!hasKey) {
67
+ return {
68
+ message: `Expected ${subject.constructor.name} to contain key`,
69
+ };
70
+ }
71
+ });
72
+ /**
73
+ * Asserts that a Map has a specific size.
74
+ *
75
+ * @example
76
+ *
77
+ * ```ts
78
+ * const map = new Map([
79
+ * ['a', 1],
80
+ * ['b', 2],
81
+ * ]);
82
+ * expect(map, 'to have size', 2); // passes
83
+ * expect(map, 'to have size', 3); // fails
84
+ * ```
85
+ *
86
+ * @group Collection Assertions
87
+ * @bupkisAnchor map-to-have-size-nonnegative-integer
88
+ * @bupkisAssertionCategory collections
89
+ */
90
+ export const mapSizeAssertion = createAssertion([MapSchema, 'to have size', NonNegativeIntegerSchema], (_subject, expectedSize) => z.map(z.unknown(), z.unknown()).refine((map) => map.size === expectedSize, {
91
+ error: `Expected Map to have size ${expectedSize}`,
92
+ }));
93
+ /**
94
+ * Asserts that a Map is empty.
95
+ *
96
+ * @example
97
+ *
98
+ * ```ts
99
+ * expect(new Map(), 'to be empty'); // passes
100
+ * expect(new Map([['key', 'value']]), 'to be empty'); // fails
101
+ * ```
102
+ *
103
+ * @group Collection Assertions
104
+ * @bupkisAnchor map-to-be-empty
105
+ * @bupkisAssertionCategory collections
106
+ */
107
+ export const emptyMapAssertion = createAssertion([MapSchema, 'to be empty'], MapSchema.refine((map) => map.size === 0, {
108
+ error: 'Expected Map to be empty',
109
+ }));
110
+ /**
111
+ * Asserts that a Set or WeakSet contains a specific value. For WeakSet, the
112
+ * value must be an object.
113
+ *
114
+ * @example
115
+ *
116
+ * ```ts
117
+ * const set = new Set(['a', 'b']);
118
+ * expect(set, 'to contain', 'a'); // passes
119
+ *
120
+ * const obj = {};
121
+ * const weakSet = new WeakSet([obj]);
122
+ * expect(weakSet, 'to contain', obj); // passes
123
+ * expect(weakSet, 'to contain', 'string'); // fails (not an object)
124
+ * ```
125
+ *
126
+ * @group Collection Assertions
127
+ * @bupkisAnchor set-to-contain-any
128
+ * @bupkisAssertionCategory collections
129
+ */
130
+ export const setContainsAssertion = createAssertion([AnySetSchema, ['to contain', 'to include'], UnknownSchema], (subject, value) => {
131
+ // WeakSet.has only works with object or symbol values
132
+ if (subject instanceof WeakSet && !isWeakKey(value)) {
133
+ return {
134
+ message: `WeakSet values must be objects or symbols, got ${typeof value}`,
135
+ };
136
+ }
137
+ // At this point, if it's a WeakSet, we know value is a WeakKey
138
+ const hasValue = subject instanceof WeakSet
139
+ ? subject.has(value)
140
+ : subject.has(value);
141
+ if (!hasValue) {
142
+ return {
143
+ message: `Expected ${subject.constructor.name} to contain value`,
144
+ };
145
+ }
146
+ });
147
+ /**
148
+ * Asserts that a Set has a specific size.
149
+ *
150
+ * @example
151
+ *
152
+ * ```ts
153
+ * const set = new Set(['a', 'b']);
154
+ * expect(set, 'to have size', 2); // passes
155
+ * expect(set, 'to have size', 3); // fails
156
+ * ```
157
+ *
158
+ * @group Collection Assertions
159
+ * @bupkisAnchor set-to-have-size-nonnegative-integer
160
+ * @bupkisAssertionCategory collections
161
+ */
162
+ export const setSizeAssertion = createAssertion([SetSchema, 'to have size', NonNegativeIntegerSchema], (_subject, expectedSize) => z
163
+ .set(z.unknown())
164
+ .min(expectedSize, { error: `Expected Set to have size ${expectedSize}` })
165
+ .max(expectedSize, {
166
+ error: `Expected Set to have size ${expectedSize}`,
167
+ }));
168
+ /**
169
+ * Asserts that a Set is empty.
170
+ *
171
+ * @example
172
+ *
173
+ * ```ts
174
+ * expect(new Set(), 'to be empty'); // passes
175
+ * expect(new Set(['value']), 'to be empty'); // fails
176
+ * ```
177
+ *
178
+ * @group Collection Assertions
179
+ * @bupkisAnchor set-to-be-empty
180
+ * @bupkisAssertionCategory collections
181
+ */
182
+ export const emptySetAssertion = createAssertion([SetSchema, 'to be empty'], SetSchema.refine(({ size }) => size === 0, {
183
+ error: 'Expected Set to be empty',
184
+ }));
185
+ /**
186
+ * Asserts that an array contains a specific value.
187
+ *
188
+ * @example
189
+ *
190
+ * ```ts
191
+ * expect([1, 2, 3], 'to contain', 2); // passes
192
+ * expect([1, 2, 3], 'to contain', 4); // fails
193
+ * ```
194
+ *
195
+ * @group Collection Assertions
196
+ * @bupkisAnchor array-to-contain-any
197
+ * @bupkisAssertionCategory collections
198
+ */
199
+ export const arrayContainsAssertion = createAssertion([UnknownArraySchema, ['to contain', 'to include'], UnknownSchema], (subject, value) => {
200
+ if (!subject.includes(value)) {
201
+ return {
202
+ message: `Expected array to contain value`,
203
+ };
204
+ }
205
+ });
206
+ /**
207
+ * Asserts that an array contains an item that satisfies a given shape or
208
+ * pattern. Uses partial matching semantics - the item only needs to match the
209
+ * specified properties.
210
+ *
211
+ * @example
212
+ *
213
+ * ```ts
214
+ * expect([{ a: 1, b: 2 }, { c: 3 }], 'to have item satisfying', { a: 1 }); // passes
215
+ * expect([{ a: 1 }, { b: 2 }], 'to have an item satisfying', { c: 3 }); // fails
216
+ * expect([1, 2, 3], 'to contain item satisfying', 2); // passes (exact match)
217
+ * ```
218
+ *
219
+ * @group Collection Assertions
220
+ * @bupkisAnchor array-to-have-item-satisfying
221
+ * @bupkisAssertionCategory collections
222
+ */
223
+ export const arrayItemSatisfiesAssertion = createAssertion([
224
+ UnknownArraySchema,
225
+ [
226
+ 'to have item satisfying',
227
+ 'to have an item satisfying',
228
+ 'to contain item satisfying',
229
+ ],
230
+ UnknownSchema,
231
+ ], (subject, shape) => {
232
+ const schema = valueToSchema(shape, valueToSchemaOptionsForSatisfies);
233
+ for (const item of subject) {
234
+ const result = schema.safeParse(item);
235
+ if (result.success) {
236
+ return;
237
+ }
238
+ }
239
+ return {
240
+ message: `Expected array to contain an item satisfying the given shape`,
241
+ };
242
+ });
243
+ /**
244
+ * Asserts that an array has a specific size.
245
+ *
246
+ * @example
247
+ *
248
+ * ```ts
249
+ * expect([1, 2, 3], 'to have length', 3); // passes
250
+ * expect([1, 2, 3], 'to have size', 2); // fails
251
+ * ```
252
+ *
253
+ * @group Collection Assertions
254
+ * @bupkisAnchor array-to-have-size-nonnegative-integer
255
+ * @bupkisAssertionCategory collections
256
+ */
257
+ export const arraySizeAssertion = createAssertion([
258
+ UnknownArraySchema,
259
+ ['to have length', 'to have size'],
260
+ NonNegativeIntegerSchema,
261
+ ], (_subject, expectedSize) => UnknownArraySchema.min(expectedSize, {
262
+ error: `Expected array to have size ${expectedSize}}`,
263
+ }).max(expectedSize, {
264
+ error: `Expected array to have size ${expectedSize}}`,
265
+ }));
266
+ /**
267
+ * Asserts that an array is non-empty.
268
+ *
269
+ * @example
270
+ *
271
+ * ```ts
272
+ * expect([1, 2, 3], 'to be non-empty'); // passes
273
+ * expect([], 'to be non-empty'); // fails
274
+ * ```
275
+ *
276
+ * @group Collection Assertions
277
+ * @bupkisAnchor array-not-to-be-empty
278
+ * @bupkisAssertionCategory collections
279
+ */
280
+ export const nonEmptyArrayAssertion = createAssertion([UnknownArraySchema, 'to be non-empty'], UnknownArraySchema.min(1, { error: 'Expected array to be non-empty' }));
281
+ /**
282
+ * Asserts that an object has specific keys/properties.
283
+ *
284
+ * @example
285
+ *
286
+ * ```ts
287
+ * expect({ a: 1, b: 2 }, 'to have keys', 'a', 'b'); // passes
288
+ * expect({ a: 1 }, 'to have keys', 'a', 'b'); // fails
289
+ * ```
290
+ *
291
+ * @group Collection Assertions
292
+ * @bupkisAnchor object-to-have-keys-array
293
+ * @bupkisAssertionCategory object
294
+ */
295
+ // TODO support keypaths, maybe.
296
+ // TODO support `undefined` values (will require moving away from Zod schema)
297
+ export const objectKeysAssertion = createAssertion([
298
+ NonCollectionObjectSchema,
299
+ [
300
+ 'to have keys',
301
+ 'to have properties',
302
+ 'to have props',
303
+ 'to contain keys',
304
+ 'to contain properties',
305
+ 'to contain props',
306
+ 'to include keys',
307
+ 'to include properties',
308
+ 'to include props',
309
+ ],
310
+ z.array(PropertyKeySchema).nonempty(),
311
+ ], (_subject, keys) => NonCollectionObjectSchema.superRefine((subject, ctx) => {
312
+ // iterate thru keys and add an issue for each missing
313
+ for (const k of keys) {
314
+ if (!hasOwn(subject, k)) {
315
+ ctx.addIssue({
316
+ code: 'custom',
317
+ input: subject,
318
+ message: `Expected object to contain key "${String(k)}"`,
319
+ params: { bupkisType: 'missing_key' },
320
+ });
321
+ }
322
+ }
323
+ }));
324
+ /**
325
+ * Asserts that an object has a property at the specified keypath using dot or
326
+ * bracket notation. Uses the `has()` function to traverse nested properties and
327
+ * supports complex keypaths like 'foo.bar[0]["baz"]'.
328
+ *
329
+ * This assertion supports:
330
+ *
331
+ * - Dot notation: 'prop.nested'
332
+ * - Bracket notation with numbers: 'arr[0]'
333
+ * - Bracket notation with quoted strings: 'obj["key"]' or "obj['key']"
334
+ * - Mixed notation: 'data.items[1].name'
335
+ *
336
+ * @example
337
+ *
338
+ * ```ts
339
+ * const obj = {
340
+ * foo: { bar: [{ baz: 'value' }] },
341
+ * 'kebab-case': 'works',
342
+ * };
343
+ *
344
+ * expect(obj, 'to have key', 'foo.bar'); // passes
345
+ * expect(obj, 'to have property', 'foo.bar[0].baz'); // passes
346
+ * expect(obj, 'to have prop', 'foo["kebab-case"]'); // passes
347
+ * expect(obj, 'to have key', 'nonexistent.path'); // fails
348
+ * ```
349
+ *
350
+ * @group Collection Assertions
351
+ * @bupkisAnchor object-to-have-key-string-number-symbol
352
+ * @bupkisAssertionCategory object
353
+ */
354
+ export const objectKeyAssertion = createAssertion([
355
+ NonCollectionObjectSchema,
356
+ [
357
+ 'to have key',
358
+ 'to have property',
359
+ 'to have prop',
360
+ 'to contain key',
361
+ 'to contain property',
362
+ 'to contain prop',
363
+ 'to include key',
364
+ 'to include property',
365
+ 'to include prop',
366
+ ],
367
+ KeypathSchema,
368
+ ], (subject, keypath) => {
369
+ const result = has(subject, keypath);
370
+ if (!result) {
371
+ return {
372
+ actual: 'no such keypath',
373
+ expect: `to have keypath ${keypath}`,
374
+ message: `Expected object to contain keypath ${keypath}`,
375
+ };
376
+ }
377
+ });
378
+ /**
379
+ * Asserts that an object has an exact property key without keypath traversal.
380
+ * This assertion checks for direct properties on the object and supports
381
+ * symbols and keys that would conflict with bracket/dot notation.
382
+ *
383
+ * Unlike `objectKeyAssertion`, this does not use the `has()` function and
384
+ * therefore:
385
+ *
386
+ * - Does not support keypath traversal (no dots or brackets)
387
+ * - Can check for symbol keys
388
+ * - Can check for keys containing dots, brackets, or other special characters
389
+ * - Only checks direct properties (no nested access)
390
+ *
391
+ * @example
392
+ *
393
+ * ```ts
394
+ * const sym = Symbol('test');
395
+ * const obj = {
396
+ * simple: 'value',
397
+ * 'key.with.dots': 'direct property',
398
+ * 'key[with]brackets': 'another direct property',
399
+ * [sym]: 'symbol value',
400
+ * };
401
+ *
402
+ * expect(obj, 'to have exact key', 'simple'); // passes
403
+ * expect(obj, 'to have exact property', 'key.with.dots'); // passes (literal key)
404
+ * expect(obj, 'to have exact prop', 'key[with]brackets'); // passes (literal key)
405
+ * expect(obj, 'to have exact key', sym); // passes (symbol key)
406
+ *
407
+ * // These would fail because they're not direct properties:
408
+ * expect(obj, 'to have exact key', 'nested.path'); // fails (no keypath traversal)
409
+ * ```
410
+ *
411
+ * @group Collection Assertions
412
+ * @bupkisAnchor object-to-have-only-keys-array
413
+ * @bupkisAssertionCategory object
414
+ */
415
+ export const objectExactKeyAssertion = createAssertion([
416
+ NonCollectionObjectSchema,
417
+ ['to have exact key', 'to have exact property', 'to have exact prop'],
418
+ PropertyKeySchema,
419
+ ], (_, key) => NonCollectionObjectSchema.transform((v) => ({ ...v })).refine((value) => hasOwn(value, key), { error: `Expected object to have own exact key "${String(key)}"` }));
420
+ /**
421
+ * Asserts that an object has a specific number of keys.
422
+ *
423
+ * @example
424
+ *
425
+ * ```ts
426
+ * expect({ a: 1, b: 2 }, 'to have size', 2); // passes
427
+ * expect({ a: 1 }, 'to have size', 2); // fails
428
+ * ```
429
+ *
430
+ * @group Collection Assertions
431
+ * @bupkisAnchor unknown-to-be-an-object
432
+ * @bupkisAssertionCategory object
433
+ */
434
+ export const objectSizeAssertion = createAssertion([UnknownRecordSchema, 'to have size', NonNegativeIntegerSchema], (subject, expectedSize) => {
435
+ const actual = keys(subject).length;
436
+ if (actual !== expectedSize) {
437
+ return {
438
+ actual,
439
+ expected: expectedSize,
440
+ message: `Expected object to have ${expectedSize} keys, but it has ${actual} keys`,
441
+ };
442
+ }
443
+ });
444
+ /**
445
+ * Asserts that two Sets are equal (same elements, order-independent).
446
+ *
447
+ * @example
448
+ *
449
+ * ```ts
450
+ * expect(new Set([1, 2]), 'to equal', new Set([2, 1])); // passes
451
+ * expect(new Set([1, 2]), 'to equal', new Set([1, 3])); // fails
452
+ * ```
453
+ *
454
+ * @group Collection Assertions
455
+ * @bupkisAnchor set-to-equal-set
456
+ * @bupkisAssertionCategory collections
457
+ */
458
+ export const setEqualityAssertion = createAssertion([SetSchema, 'to equal', SetSchema], (actual, expected) => actual.size === expected.size && isSubsetOf(actual, expected));
459
+ /**
460
+ * Asserts that one Set is a subset of another.
461
+ *
462
+ * @example
463
+ *
464
+ * ```ts
465
+ * expect(new Set([1, 2]), 'to be a subset of', new Set([1, 2, 3])); // passes
466
+ * expect(new Set([1, 4]), 'to be a subset of', new Set([1, 2, 3])); // fails
467
+ * ```
468
+ *
469
+ * @group Collection Assertions
470
+ * @bupkisAnchor set-to-be-a-subset-of-set
471
+ * @bupkisAssertionCategory collections
472
+ */
473
+ export const setSubsetAssertion = createAssertion([SetSchema, 'to be a subset of', SetSchema], (subset, superset) => isSubsetOf(subset, superset));
474
+ /**
475
+ * Asserts that one Set is a superset of another.
476
+ *
477
+ * @example
478
+ *
479
+ * ```ts
480
+ * expect(new Set([1, 2, 3]), 'to be a superset of', new Set([1, 2])); // passes
481
+ * expect(new Set([1, 2]), 'to be a superset of', new Set([1, 2, 3])); // fails
482
+ * ```
483
+ *
484
+ * @group Collection Assertions
485
+ * @bupkisAnchor set-to-be-a-superset-of-set
486
+ * @bupkisAssertionCategory collections
487
+ */
488
+ export const setSupersetAssertion = createAssertion([SetSchema, 'to be a superset of', SetSchema], (superset, subset) => isSupersetOf(superset, subset));
489
+ /**
490
+ * Asserts that two Sets intersect (have common elements).
491
+ *
492
+ * @example
493
+ *
494
+ * ```ts
495
+ * expect(new Set([1, 2]), 'to intersect with', new Set([2, 3])); // passes
496
+ * expect(new Set([1, 2]), 'to intersect with', new Set([3, 4])); // fails
497
+ * ```
498
+ *
499
+ * @group Collection Assertions
500
+ * @bupkisAnchor set-to-have-intersection-with-set-satisfying-any
501
+ * @bupkisAssertionCategory collections
502
+ */
503
+ export const setIntersectionAssertion = createAssertion([SetSchema, 'to intersect with', SetSchema], (setA, setB) => !isDisjointFrom(setA, setB));
504
+ /**
505
+ * Asserts that two Sets are disjoint (have no common elements).
506
+ *
507
+ * @example
508
+ *
509
+ * ```ts
510
+ * expect(new Set([1, 2]), 'to be disjoint from', new Set([3, 4])); // passes
511
+ * expect(new Set([1, 2]), 'to be disjoint from', new Set([2, 3])); // fails
512
+ * ```
513
+ *
514
+ * @group Collection Assertions
515
+ * @bupkisAnchor set-to-be-disjoint-from-set
516
+ * @bupkisAssertionCategory collections
517
+ */
518
+ export const setDisjointAssertion = createAssertion([SetSchema, 'to be disjoint from', SetSchema], (setA, setB) => isDisjointFrom(setA, setB));
519
+ /**
520
+ * Asserts that the union of two Sets equals a third Set.
521
+ *
522
+ * @example
523
+ *
524
+ * ```ts
525
+ * expect(
526
+ * new Set([1, 2]),
527
+ * 'to have union',
528
+ * new Set([3]),
529
+ * 'equal to',
530
+ * new Set([1, 2, 3]),
531
+ * ); // passes
532
+ * ```
533
+ *
534
+ * @group Collection Assertions
535
+ * @bupkisAnchor set-union-with-set-to-equal-set
536
+ * @bupkisAssertionCategory collections
537
+ */
538
+ export const setUnionEqualityAssertion = createAssertion([SetSchema, 'to have union', SetSchema, 'equal to', SetSchema], (setA, setB, expected) => {
539
+ const result = setUnion(setA, setB);
540
+ return (result.size === expected.size &&
541
+ isSubsetOf(result, expected) &&
542
+ isSubsetOf(expected, result));
543
+ });
544
+ /**
545
+ * Asserts that the intersection of two Sets equals a third Set.
546
+ *
547
+ * @example
548
+ *
549
+ * ```ts
550
+ * expect(
551
+ * new Set([1, 2, 3]),
552
+ * 'to have intersection',
553
+ * new Set([2, 3, 4]),
554
+ * 'equal to',
555
+ * new Set([2, 3]),
556
+ * ); // passes
557
+ * ```
558
+ *
559
+ * @group Collection Assertions
560
+ * @bupkisAnchor set-intersection-with-set-to-equal-set
561
+ * @bupkisAssertionCategory collections
562
+ */
563
+ export const setIntersectionEqualityAssertion = createAssertion([SetSchema, 'to have intersection', SetSchema, 'equal to', SetSchema], (setA, setB, expected) => {
564
+ const result = setIntersection(setA, setB);
565
+ return (result.size === expected.size &&
566
+ isSubsetOf(result, expected) &&
567
+ isSubsetOf(expected, result));
568
+ });
569
+ /**
570
+ * Asserts that the difference between two Sets equals a third Set.
571
+ *
572
+ * @example
573
+ *
574
+ * ```ts
575
+ * expect(
576
+ * new Set([1, 2, 3]),
577
+ * 'to have difference',
578
+ * new Set([2, 4]),
579
+ * 'equal to',
580
+ * new Set([1, 3]),
581
+ * ); // passes
582
+ * ```
583
+ *
584
+ * @group Collection Assertions
585
+ * @bupkisAnchor set-difference-with-set-to-equal-set
586
+ * @bupkisAssertionCategory collections
587
+ */
588
+ export const setDifferenceEqualityAssertion = createAssertion([SetSchema, 'to have difference', SetSchema, 'equal to', SetSchema], (setA, setB, expected) => {
589
+ const result = setDifference(setA, setB);
590
+ return (result.size === expected.size &&
591
+ isSubsetOf(result, expected) &&
592
+ isSubsetOf(expected, result));
593
+ });
594
+ /**
595
+ * Asserts that the symmetric difference between two Sets equals a third Set.
596
+ *
597
+ * @example
598
+ *
599
+ * ```ts
600
+ * expect(
601
+ * new Set([1, 2]),
602
+ * 'to have symmetric difference',
603
+ * new Set([2, 3]),
604
+ * 'equal to',
605
+ * new Set([1, 3]),
606
+ * ); // passes
607
+ * ```
608
+ *
609
+ * @group Collection Assertions
610
+ * @bupkisAnchor set-symmetric-difference-with-set-to-equal-set
611
+ * @bupkisAssertionCategory collections
612
+ */
613
+ export const setSymmetricDifferenceEqualityAssertion = createAssertion([SetSchema, 'to have symmetric difference', SetSchema, 'equal to', SetSchema], (setA, setB, expected) => {
614
+ const result = symmetricDifference(setA, setB);
615
+ return (result.size === expected.size &&
616
+ isSubsetOf(result, expected) &&
617
+ isSubsetOf(expected, result));
618
+ });
619
+ /**
620
+ * Asserts that a Map has a specific key.
621
+ *
622
+ * @example
623
+ *
624
+ * ```ts
625
+ * const map = new Map([['key', 'value']]);
626
+ * expect(map, 'to have key', 'key'); // passes
627
+ * expect(map, 'to have key', 'missing'); // fails
628
+ * ```
629
+ *
630
+ * @group Collection Assertions
631
+ * @bupkisAnchor map-to-have-key-any
632
+ * @bupkisAssertionCategory collections
633
+ */
634
+ export const mapKeyAssertion = createAssertion([MapSchema, 'to have key', UnknownSchema], (map, key) => {
635
+ if (!map.has(key)) {
636
+ return {
637
+ actual: [...map.keys()],
638
+ expected: [...map.keys(), key],
639
+ message: 'Expected Map to have key',
640
+ };
641
+ }
642
+ });
643
+ /**
644
+ * Asserts that a Map contains a specific value.
645
+ *
646
+ * @example
647
+ *
648
+ * ```ts
649
+ * const map = new Map([['key', 'value']]);
650
+ * expect(map, 'to have value', 'value'); // passes
651
+ * expect(map, 'to have value', 'missing'); // fails
652
+ * ```
653
+ *
654
+ * @group Collection Assertions
655
+ * @bupkisAnchor map-to-have-value-any
656
+ * @bupkisAssertionCategory collections
657
+ */
658
+ export const mapValueAssertion = createAssertion([
659
+ MapSchema,
660
+ ['to have value', 'to contain value', 'to include value'],
661
+ UnknownSchema,
662
+ ], (map, value) => {
663
+ for (const mapValue of map.values()) {
664
+ if (mapValue === value) {
665
+ return;
666
+ }
667
+ }
668
+ return {
669
+ actual: [...map.values()],
670
+ expected: value,
671
+ message: `Expected Map to have value`,
672
+ };
673
+ });
674
+ /**
675
+ * Asserts that a Map has a specific key-value entry.
676
+ *
677
+ * @example
678
+ *
679
+ * ```ts
680
+ * const map = new Map([['key', 'value']]);
681
+ * expect(map, 'to have entry', ['key', 'value']); // passes
682
+ * expect(map, 'to have entry', ['key', 'wrong']); // fails
683
+ * ```
684
+ *
685
+ * @group Collection Assertions
686
+ * @bupkisAnchor map-to-have-entry-any-any
687
+ * @bupkisAssertionCategory collections
688
+ */
689
+ export const mapEntryAssertion = createAssertion([
690
+ AnyMapSchema,
691
+ [
692
+ 'to have entry',
693
+ 'to have key/value pair',
694
+ 'to contain entry',
695
+ 'to contain key/value pair',
696
+ 'to include entry',
697
+ 'to include key/value pair',
698
+ ],
699
+ z.tuple([UnknownSchema, UnknownSchema]),
700
+ ], (map, [key, value]) => {
701
+ // WeakMap operations only work with object or symbol keys
702
+ if (map instanceof WeakMap && !isWeakKey(key)) {
703
+ return {
704
+ message: `WeakMap keys must be objects or symbols, got ${typeof key}`,
705
+ };
706
+ }
707
+ // At this point, if it's a WeakMap, we know key is a WeakKey
708
+ const actualValue = map instanceof WeakMap ? map.get(key) : map.get(key);
709
+ if (actualValue === value) {
710
+ return;
711
+ }
712
+ const hasKey = map instanceof WeakMap ? map.has(key) : map.has(key);
713
+ return {
714
+ actual: hasKey ? [key, actualValue] : undefined,
715
+ expected: [key, value],
716
+ message: hasKey
717
+ ? `Expected ${map.constructor.name} entry [${String(key)}, ${String(actualValue)}] to equal [${String(key)}, ${String(value)}]`
718
+ : `Expected ${map.constructor.name} to have key ${String(key)}`,
719
+ };
720
+ });
721
+ /**
722
+ * Asserts that two Maps are equal (same key-value pairs, order-independent).
723
+ *
724
+ * @example
725
+ *
726
+ * ```ts
727
+ * const map1 = new Map([
728
+ * ['a', 1],
729
+ * ['b', 2],
730
+ * ]);
731
+ * const map2 = new Map([
732
+ * ['b', 2],
733
+ * ['a', 1],
734
+ * ]);
735
+ * expect(map1, 'to equal', map2); // passes
736
+ * ```
737
+ *
738
+ * @group Collection Assertions
739
+ * @bupkisAnchor map-to-equal-map
740
+ * @bupkisAssertionCategory collections
741
+ */
742
+ export const mapEqualityAssertion = createAssertion([MapSchema, 'to equal', MapSchema], (mapA, mapB) => {
743
+ if (mapA.size !== mapB.size) {
744
+ return {
745
+ actual: mapA.size,
746
+ expected: mapB.size,
747
+ message: `Expected Maps to have equal sizes, got ${mapA.size} and ${mapB.size}`,
748
+ };
749
+ }
750
+ for (const [key, value] of mapA) {
751
+ if (!mapB.has(key)) {
752
+ return {
753
+ message: `Expected second Map to contain key ${String(key)}`,
754
+ };
755
+ }
756
+ if (mapB.get(key) !== value) {
757
+ return {
758
+ actual: [key, mapB.get(key)],
759
+ expected: [key, value],
760
+ message: `Expected Maps to have equal value for key ${String(key)}`,
761
+ };
762
+ }
763
+ }
764
+ });
765
+ /**
766
+ * Asserts that a collection (Map or Set) has a size greater than a threshold.
767
+ *
768
+ * @example
769
+ *
770
+ * ```ts
771
+ * expect(new Set([1, 2, 3]), 'to have size greater than', 2); // passes
772
+ * expect(new Set([1]), 'to have size greater than', 2); // fails
773
+ * ```
774
+ *
775
+ * @group Collection Assertions
776
+ * @bupkisAnchor collection-to-have-size-greater-than-nonnegative-integer
777
+ * @bupkisAssertionCategory collections
778
+ */
779
+ export const collectionSizeGreaterThanAssertion = createAssertion([
780
+ z.union([MapSchema, SetSchema]),
781
+ 'to have size greater than',
782
+ NonNegativeIntegerSchema,
783
+ ], (collection, minSize) => {
784
+ if (collection.size <= minSize) {
785
+ return {
786
+ actual: collection.size,
787
+ expected: minSize,
788
+ message: `Expected ${collection.constructor.name} to have size greater than ${minSize}, got ${collection.size}`,
789
+ };
790
+ }
791
+ });
792
+ /**
793
+ * Asserts that a collection (Map or Set) has a size less than a threshold.
794
+ *
795
+ * @example
796
+ *
797
+ * ```ts
798
+ * expect(new Set([1]), 'to have size less than', 2); // passes
799
+ * expect(new Set([1, 2, 3]), 'to have size less than', 2); // fails
800
+ * ```
801
+ *
802
+ * @group Collection Assertions
803
+ * @bupkisAnchor collection-to-have-size-less-than-nonnegative-integer
804
+ * @bupkisAssertionCategory collections
805
+ */
806
+ export const collectionSizeLessThanAssertion = createAssertion([
807
+ z.union([MapSchema, SetSchema]),
808
+ 'to have size less than',
809
+ NonNegativeIntegerSchema,
810
+ ], (collection, maxSize) => {
811
+ if (collection.size >= maxSize) {
812
+ return {
813
+ actual: collection.size,
814
+ expected: maxSize,
815
+ message: `Expected ${collection.constructor.name} to have size less than ${maxSize}, got ${collection.size}`,
816
+ };
817
+ }
818
+ });
819
+ /**
820
+ * Asserts that a collection (Map or Set) has a size within a specific range.
821
+ *
822
+ * @example
823
+ *
824
+ * ```ts
825
+ * expect(new Set([1, 2]), 'to have size between', [1, 3]); // passes
826
+ * expect(new Set([1, 2, 3, 4]), 'to have size between', [1, 3]); // fails
827
+ * ```
828
+ *
829
+ * @group Collection Assertions
830
+ * @bupkisAnchor collection-to-have-size-between-nonnegative-integer-and-nonnegative-integer
831
+ * @bupkisAssertionCategory collections
832
+ */
833
+ export const collectionSizeBetweenAssertion = createAssertion([
834
+ z.union([MapSchema, SetSchema]),
835
+ 'to have size between',
836
+ z.tuple([NonNegativeIntegerSchema, NonNegativeIntegerSchema]),
837
+ ], (collection, [min, max]) => {
838
+ const size = collection.size;
839
+ if (!(size >= min && size <= max)) {
840
+ return {
841
+ message: `Expected ${collection.constructor.name} to have size between ${min} and ${max}, got ${size}`,
842
+ };
843
+ }
844
+ });
845
+ // =============================================================================
846
+ // Collection value assertions (Map/Set/Array)
847
+ // =============================================================================
848
+ const CollectionSchema = z.union([MapSchema, SetSchema, UnknownArraySchema]);
849
+ /**
850
+ * Returns the iterable of values for a Map, Set, or Array.
851
+ *
852
+ * Map iterates its values (not entries), while Set and Array are directly
853
+ * iterable.
854
+ *
855
+ * @function
856
+ * @internal
857
+ */
858
+ const getCollectionValues = (collection) => {
859
+ if (collection instanceof Map) {
860
+ return collection.values();
861
+ }
862
+ return collection;
863
+ };
864
+ /**
865
+ * Asserts that ALL values in a Map, Set, or Array individually satisfy the
866
+ * expected shape.
867
+ *
868
+ * Uses partial/satisfy semantics — every value must match. Empty collections
869
+ * pass vacuously.
870
+ *
871
+ * @remarks
872
+ * For `Map`, values (not keys) are checked. Use `mapKeysSatisfyAssertion` to
873
+ * assert on Map keys instead.
874
+ * @example
875
+ *
876
+ * ```ts
877
+ * expect([{ a: 1 }, { a: 2, b: 3 }], 'to have values satisfying', {
878
+ * a: z.number(),
879
+ * }); // passes
880
+ * expect(new Set([1, 2, 3]), 'to have values satisfying', z.number()); // passes
881
+ * expect(new Map([['k', { x: 1 }]]), 'to have values satisfying', {
882
+ * x: z.number(),
883
+ * }); // passes
884
+ * ```
885
+ *
886
+ * @function
887
+ * @group Collection Assertions
888
+ * @bupkisAnchor collection-to-have-values-satisfying-any
889
+ * @bupkisAssertionCategory collections
890
+ */
891
+ export const collectionValuesSatisfyAssertion = createAssertion([
892
+ CollectionSchema,
893
+ ['to have values satisfying', 'to contain values satisfying'],
894
+ UnknownSchema,
895
+ ], (subject, expected) => {
896
+ const schema = valueToSchema(expected, valueToSchemaOptionsForSatisfies);
897
+ let index = 0;
898
+ for (const value of getCollectionValues(subject)) {
899
+ const result = schema.safeParse(value);
900
+ if (!result.success) {
901
+ return {
902
+ message: `Expected all values to satisfy ${inspect(expected)}, but value at index ${index} did not match: ${inspect(value)}`,
903
+ };
904
+ }
905
+ index++;
906
+ }
907
+ // Empty collections trivially satisfy (vacuous truth)
908
+ });
909
+ /**
910
+ * Asserts that ALL values in a Map, Set, or Array individually match with deep
911
+ * equality.
912
+ *
913
+ * Uses strict deep-equality semantics — every value must exactly match. Empty
914
+ * collections pass vacuously.
915
+ *
916
+ * @example
917
+ *
918
+ * ```ts
919
+ * expect([{ a: 1 }, { a: 1 }], 'to have values exhaustively satisfying', {
920
+ * a: 1,
921
+ * }); // passes
922
+ * expect([{ a: 1, b: 2 }], 'to have values exhaustively satisfying', {
923
+ * a: 1,
924
+ * }); // fails — extra property b
925
+ * ```
926
+ *
927
+ * @function
928
+ * @group Collection Assertions
929
+ * @bupkisAnchor collection-to-have-values-exhaustively-satisfying-any
930
+ * @bupkisAssertionCategory collections
931
+ */
932
+ export const collectionValuesExhaustivelySatisfyAssertion = createAssertion([CollectionSchema, 'to have values exhaustively satisfying', UnknownSchema], (subject, expected) => {
933
+ const schema = valueToSchema(expected, valueToSchemaOptionsForDeepEqual);
934
+ let index = 0;
935
+ for (const value of getCollectionValues(subject)) {
936
+ const result = schema.safeParse(value);
937
+ if (!result.success) {
938
+ return {
939
+ message: `Expected all values to exhaustively satisfy ${inspect(expected)}, but value at index ${index} did not match: ${inspect(value)}`,
940
+ };
941
+ }
942
+ index++;
943
+ }
944
+ });
945
+ /**
946
+ * Asserts that at least one value in a Map, Set, or Array satisfies the
947
+ * expected shape.
948
+ *
949
+ * Uses partial/satisfy semantics — any single matching value is sufficient.
950
+ * Fails on empty collections.
951
+ *
952
+ * @remarks
953
+ * For `Map`, values (not keys) are checked.
954
+ * @example
955
+ *
956
+ * ```ts
957
+ * expect([{ a: 1, b: 2 }, { c: 3 }], 'to have a value satisfying', {
958
+ * a: 1,
959
+ * }); // passes
960
+ * expect(new Set([1, 'two', 3]), 'to have a value satisfying', z.string()); // passes
961
+ * expect([1, 2, 3], 'to have value satisfying', 2); // passes
962
+ * ```
963
+ *
964
+ * @function
965
+ * @group Collection Assertions
966
+ * @bupkisAnchor collection-to-have-a-value-satisfying-any
967
+ * @bupkisAssertionCategory collections
968
+ */
969
+ export const collectionHasValueSatisfyingAssertion = createAssertion([
970
+ CollectionSchema,
971
+ [
972
+ 'to have a value satisfying',
973
+ 'to have value satisfying',
974
+ 'to contain a value satisfying',
975
+ ],
976
+ UnknownSchema,
977
+ ], (subject, expected) => {
978
+ const schema = valueToSchema(expected, valueToSchemaOptionsForSatisfies);
979
+ for (const value of getCollectionValues(subject)) {
980
+ if (schema.safeParse(value).success) {
981
+ return;
982
+ }
983
+ }
984
+ return {
985
+ message: `Expected collection to have a value satisfying ${inspect(expected)}, but none matched`,
986
+ };
987
+ });
988
+ /**
989
+ * Asserts that at least one value in a Map, Set, or Array exhaustively matches
990
+ * the expected value.
991
+ *
992
+ * Uses strict deep-equality semantics. Fails on empty collections.
993
+ *
994
+ * @example
995
+ *
996
+ * ```ts
997
+ * expect(
998
+ * [{ a: 1 }, { a: 1, b: 2 }],
999
+ * 'to have a value exhaustively satisfying',
1000
+ * {
1001
+ * a: 1,
1002
+ * },
1003
+ * ); // passes — first element matches exactly
1004
+ * expect([{ a: 1, b: 2 }], 'to have a value exhaustively satisfying', {
1005
+ * a: 1,
1006
+ * }); // fails — extra property b
1007
+ * ```
1008
+ *
1009
+ * @function
1010
+ * @group Collection Assertions
1011
+ * @bupkisAnchor collection-to-have-a-value-exhaustively-satisfying-any
1012
+ * @bupkisAssertionCategory collections
1013
+ */
1014
+ export const collectionHasValueExhaustivelySatisfyingAssertion = createAssertion([
1015
+ CollectionSchema,
1016
+ [
1017
+ 'to have a value exhaustively satisfying',
1018
+ 'to have value exhaustively satisfying',
1019
+ ],
1020
+ UnknownSchema,
1021
+ ], (subject, expected) => {
1022
+ const schema = valueToSchema(expected, valueToSchemaOptionsForDeepEqual);
1023
+ for (const value of getCollectionValues(subject)) {
1024
+ if (schema.safeParse(value).success) {
1025
+ return;
1026
+ }
1027
+ }
1028
+ return {
1029
+ message: `Expected collection to have a value exhaustively satisfying ${inspect(expected)}, but none matched`,
1030
+ };
1031
+ });
1032
+ // =============================================================================
1033
+ // Map key assertions
1034
+ // =============================================================================
1035
+ /**
1036
+ * Asserts that ALL keys in a Map individually satisfy the expected shape.
1037
+ *
1038
+ * Uses partial/satisfy semantics — every key must match. Empty Maps pass
1039
+ * vacuously.
1040
+ *
1041
+ * @example
1042
+ *
1043
+ * ```ts
1044
+ * const map = new Map([
1045
+ * ['foo', 1],
1046
+ * ['bar', 2],
1047
+ * ]);
1048
+ * expect(map, 'to have keys satisfying', z.string()); // passes
1049
+ * expect(map, 'to have props satisfying', z.string()); // alias — same assertion
1050
+ * expect(map, 'to have fields satisfying', z.string()); // alias
1051
+ * expect(map, 'to contain keys satisfying', /^[a-z]+$/); // alias
1052
+ * ```
1053
+ *
1054
+ * @function
1055
+ * @group Collection Assertions
1056
+ * @bupkisAnchor map-to-have-keys-satisfying-any
1057
+ * @bupkisAssertionCategory collections
1058
+ */
1059
+ export const mapKeysSatisfyAssertion = createAssertion([
1060
+ MapSchema,
1061
+ [
1062
+ 'to have keys satisfying',
1063
+ 'to have props satisfying',
1064
+ 'to have properties satisfying',
1065
+ 'to have fields satisfying',
1066
+ 'to contain keys satisfying',
1067
+ 'to contain props satisfying',
1068
+ 'to contain properties satisfying',
1069
+ 'to contain fields satisfying',
1070
+ ],
1071
+ UnknownSchema,
1072
+ ], (subject, expected) => {
1073
+ const schema = valueToSchema(expected, valueToSchemaOptionsForSatisfies);
1074
+ let index = 0;
1075
+ for (const key of subject.keys()) {
1076
+ const result = schema.safeParse(key);
1077
+ if (!result.success) {
1078
+ return {
1079
+ message: `Expected all Map keys to satisfy ${inspect(expected)}, but key at index ${index} did not match: ${inspect(key)}`,
1080
+ };
1081
+ }
1082
+ index++;
1083
+ }
1084
+ // Empty Maps trivially satisfy (vacuous truth)
1085
+ });
1086
+ /**
1087
+ * Asserts that ALL keys in a Map individually match with deep equality.
1088
+ *
1089
+ * Uses strict deep-equality semantics — every key must exactly match. Empty
1090
+ * Maps pass vacuously.
1091
+ *
1092
+ * @example
1093
+ *
1094
+ * ```ts
1095
+ * const map = new Map([
1096
+ * [{ id: 1 }, 'a'],
1097
+ * [{ id: 2 }, 'b'],
1098
+ * ]);
1099
+ * expect(map, 'to have keys exhaustively satisfying', { id: z.number() }); // fails — extra strict
1100
+ * expect(map, 'to have props exhaustively satisfying', { id: z.number() }); // alias
1101
+ * expect(map, 'to have fields exhaustively satisfying', {
1102
+ * id: z.number(),
1103
+ * }); // alias
1104
+ * ```
1105
+ *
1106
+ * @function
1107
+ * @group Collection Assertions
1108
+ * @bupkisAnchor map-to-have-keys-exhaustively-satisfying-any
1109
+ * @bupkisAssertionCategory collections
1110
+ */
1111
+ export const mapKeysExhaustivelySatisfyAssertion = createAssertion([
1112
+ MapSchema,
1113
+ [
1114
+ 'to have keys exhaustively satisfying',
1115
+ 'to have props exhaustively satisfying',
1116
+ 'to have properties exhaustively satisfying',
1117
+ 'to have fields exhaustively satisfying',
1118
+ ],
1119
+ UnknownSchema,
1120
+ ], (subject, expected) => {
1121
+ const schema = valueToSchema(expected, valueToSchemaOptionsForDeepEqual);
1122
+ let index = 0;
1123
+ for (const key of subject.keys()) {
1124
+ const result = schema.safeParse(key);
1125
+ if (!result.success) {
1126
+ return {
1127
+ message: `Expected all Map keys to exhaustively satisfy ${inspect(expected)}, but key at index ${index} did not match: ${inspect(key)}`,
1128
+ };
1129
+ }
1130
+ index++;
1131
+ }
1132
+ });
1133
+ /**
1134
+ * Asserts that at least one key in a Map satisfies the expected shape.
1135
+ *
1136
+ * Uses partial/satisfy semantics. Fails on empty Maps.
1137
+ *
1138
+ * @example
1139
+ *
1140
+ * ```ts
1141
+ * const map = new Map([
1142
+ * ['foo', 1],
1143
+ * [42, 2],
1144
+ * ]);
1145
+ * expect(map, 'to have a key satisfying', z.string()); // passes
1146
+ * expect(map, 'to have key satisfying', z.number()); // passes
1147
+ * expect(map, 'to have a prop satisfying', z.string()); // alias
1148
+ * expect(map, 'to have a field satisfying', z.number()); // alias
1149
+ * ```
1150
+ *
1151
+ * @function
1152
+ * @group Collection Assertions
1153
+ * @bupkisAnchor map-to-have-a-key-satisfying-any
1154
+ * @bupkisAssertionCategory collections
1155
+ */
1156
+ export const mapHasKeySatisfyingAssertion = createAssertion([
1157
+ MapSchema,
1158
+ [
1159
+ 'to have a key satisfying',
1160
+ 'to have key satisfying',
1161
+ 'to have a prop satisfying',
1162
+ 'to have prop satisfying',
1163
+ 'to have a property satisfying',
1164
+ 'to have property satisfying',
1165
+ 'to have a field satisfying',
1166
+ 'to have field satisfying',
1167
+ ],
1168
+ UnknownSchema,
1169
+ ], (subject, expected) => {
1170
+ const schema = valueToSchema(expected, valueToSchemaOptionsForSatisfies);
1171
+ for (const key of subject.keys()) {
1172
+ if (schema.safeParse(key).success) {
1173
+ return;
1174
+ }
1175
+ }
1176
+ return {
1177
+ message: `Expected Map to have a key satisfying ${inspect(expected)}, but none matched`,
1178
+ };
1179
+ });
1180
+ /**
1181
+ * Asserts that at least one key in a Map exhaustively matches the expected
1182
+ * value.
1183
+ *
1184
+ * Uses strict deep-equality semantics. Fails on empty Maps.
1185
+ *
1186
+ * @example
1187
+ *
1188
+ * ```ts
1189
+ * const map = new Map([
1190
+ * [{ id: 1 }, 'a'],
1191
+ * [{ id: 2 }, 'b'],
1192
+ * ]);
1193
+ * expect(map, 'to have a key exhaustively satisfying', { id: 1 }); // passes
1194
+ * expect(map, 'to have a prop exhaustively satisfying', { id: 1 }); // alias
1195
+ * expect(map, 'to have a field exhaustively satisfying', { id: 2 }); // alias
1196
+ * ```
1197
+ *
1198
+ * @function
1199
+ * @group Collection Assertions
1200
+ * @bupkisAnchor map-to-have-a-key-exhaustively-satisfying-any
1201
+ * @bupkisAssertionCategory collections
1202
+ */
1203
+ export const mapHasKeyExhaustivelySatisfyingAssertion = createAssertion([
1204
+ MapSchema,
1205
+ [
1206
+ 'to have a key exhaustively satisfying',
1207
+ 'to have key exhaustively satisfying',
1208
+ 'to have a prop exhaustively satisfying',
1209
+ 'to have prop exhaustively satisfying',
1210
+ 'to have a property exhaustively satisfying',
1211
+ 'to have property exhaustively satisfying',
1212
+ 'to have a field exhaustively satisfying',
1213
+ 'to have field exhaustively satisfying',
1214
+ ],
1215
+ UnknownSchema,
1216
+ ], (subject, expected) => {
1217
+ const schema = valueToSchema(expected, valueToSchemaOptionsForDeepEqual);
1218
+ for (const key of subject.keys()) {
1219
+ if (schema.safeParse(key).success) {
1220
+ return;
1221
+ }
1222
+ }
1223
+ return {
1224
+ message: `Expected Map to have a key exhaustively satisfying ${inspect(expected)}, but none matched`,
1225
+ };
1226
+ });
1227
+ // =============================================================================
1228
+ // Object key assertions
1229
+ // =============================================================================
1230
+ /**
1231
+ * Asserts that ALL own enumerable string keys of a non-collection object
1232
+ * individually satisfy the expected shape.
1233
+ *
1234
+ * Uses partial/satisfy semantics — every key must match. Empty objects pass
1235
+ * vacuously.
1236
+ *
1237
+ * @remarks
1238
+ * Only considers own enumerable string keys (equivalent to `Object.keys()`).
1239
+ * Symbol keys and non-enumerable keys are not checked.
1240
+ * @example
1241
+ *
1242
+ * ```ts
1243
+ * expect({ foo: 1, bar: 2 }, 'to have keys satisfying', z.string()); // passes
1244
+ * expect({ foo: 1, bar: 2 }, 'to have props satisfying', /^[a-z]+$/); // alias
1245
+ * expect({ foo: 1, bar: 2 }, 'to have fields satisfying', /^[a-z]+$/); // alias
1246
+ * expect({ FOO: 1 }, 'to have keys satisfying', /^[a-z]+$/); // fails
1247
+ * ```
1248
+ *
1249
+ * @function
1250
+ * @group Collection Assertions
1251
+ * @bupkisAnchor object-to-have-keys-satisfying-any
1252
+ * @bupkisAssertionCategory object
1253
+ */
1254
+ export const objectKeysSatisfyAssertion = createAssertion([
1255
+ NonCollectionObjectSchema,
1256
+ [
1257
+ 'to have keys satisfying',
1258
+ 'to have props satisfying',
1259
+ 'to have properties satisfying',
1260
+ 'to have fields satisfying',
1261
+ ],
1262
+ UnknownSchema,
1263
+ ], (subject, expected) => {
1264
+ const schema = valueToSchema(expected, valueToSchemaOptionsForSatisfies);
1265
+ for (const key of keys(subject)) {
1266
+ const result = schema.safeParse(key);
1267
+ if (!result.success) {
1268
+ return {
1269
+ message: `Expected all object keys to satisfy ${inspect(expected)}, but key ${inspect(key)} did not match`,
1270
+ };
1271
+ }
1272
+ }
1273
+ // Empty objects trivially satisfy (vacuous truth)
1274
+ });
1275
+ /**
1276
+ * Asserts that at least one own enumerable string key of a non-collection
1277
+ * object satisfies the expected shape.
1278
+ *
1279
+ * Uses partial/satisfy semantics. Fails on objects with no own enumerable
1280
+ * string keys.
1281
+ *
1282
+ * @remarks
1283
+ * Only considers own enumerable string keys (equivalent to `Object.keys()`).
1284
+ * Symbol keys and non-enumerable keys are not checked.
1285
+ * @example
1286
+ *
1287
+ * ```ts
1288
+ * expect({ foo: 1, BAR: 2 }, 'to have a key satisfying', /^[a-z]+$/); // passes
1289
+ * expect({ foo: 1 }, 'to have key satisfying', z.string()); // passes
1290
+ * expect({ foo: 1 }, 'to have a prop satisfying', z.string()); // alias
1291
+ * expect({ foo: 1 }, 'to have a field satisfying', z.string()); // alias
1292
+ * ```
1293
+ *
1294
+ * @function
1295
+ * @group Collection Assertions
1296
+ * @bupkisAnchor object-to-have-a-key-satisfying-any
1297
+ * @bupkisAssertionCategory object
1298
+ */
1299
+ export const objectHasKeySatisfyingAssertion = createAssertion([
1300
+ NonCollectionObjectSchema,
1301
+ [
1302
+ 'to have a key satisfying',
1303
+ 'to have key satisfying',
1304
+ 'to have a prop satisfying',
1305
+ 'to have prop satisfying',
1306
+ 'to have a property satisfying',
1307
+ 'to have property satisfying',
1308
+ 'to have a field satisfying',
1309
+ 'to have field satisfying',
1310
+ ],
1311
+ UnknownSchema,
1312
+ ], (subject, expected) => {
1313
+ const schema = valueToSchema(expected, valueToSchemaOptionsForSatisfies);
1314
+ for (const key of keys(subject)) {
1315
+ if (schema.safeParse(key).success) {
1316
+ return;
1317
+ }
1318
+ }
1319
+ return {
1320
+ message: `Expected object to have a key satisfying ${inspect(expected)}, but none matched`,
1321
+ };
1322
+ });
1323
+ /**
1324
+ * Asserts that ALL own enumerable string keys of a non-collection object match
1325
+ * a regular expression.
1326
+ *
1327
+ * Empty objects pass vacuously.
1328
+ *
1329
+ * @remarks
1330
+ * Only considers own enumerable string keys (equivalent to `Object.keys()`).
1331
+ * Symbol keys and non-enumerable keys are not checked.
1332
+ * @example
1333
+ *
1334
+ * ```ts
1335
+ * expect({ foo: 1, bar: 2 }, 'to have keys matching', /^[a-z]+$/); // passes
1336
+ * expect({ foo: 1, bar: 2 }, 'to have props matching', /^[a-z]+$/); // alias
1337
+ * expect({ foo: 1, bar: 2 }, 'to have fields matching', /^[a-z]+$/); // alias
1338
+ * expect({ foo: 1, Bar: 2 }, 'to have keys matching', /^[a-z]+$/); // fails
1339
+ * expect({}, 'to have keys matching', /anything/); // passes (vacuous)
1340
+ * ```
1341
+ *
1342
+ * @function
1343
+ * @group Collection Assertions
1344
+ * @bupkisAnchor object-to-have-keys-matching-regexp
1345
+ * @bupkisAssertionCategory object
1346
+ */
1347
+ export const objectKeysMatchAssertion = createAssertion([
1348
+ NonCollectionObjectSchema,
1349
+ [
1350
+ 'to have keys matching',
1351
+ 'to have props matching',
1352
+ 'to have properties matching',
1353
+ 'to have fields matching',
1354
+ ],
1355
+ z.instanceof(RegExp),
1356
+ ], (subject, pattern) => {
1357
+ for (const key of keys(subject)) {
1358
+ if (pattern.global || pattern.sticky) {
1359
+ pattern.lastIndex = 0;
1360
+ }
1361
+ if (!pattern.test(key)) {
1362
+ return {
1363
+ message: `Expected all object keys to match ${inspect(pattern)}, but key ${inspect(key)} did not match`,
1364
+ };
1365
+ }
1366
+ }
1367
+ });
1368
+ /**
1369
+ * Asserts that at least one own enumerable string key of a non-collection
1370
+ * object matches a regular expression.
1371
+ *
1372
+ * Fails on objects with no own enumerable string keys.
1373
+ *
1374
+ * @remarks
1375
+ * Only considers own enumerable string keys (equivalent to `Object.keys()`).
1376
+ * Symbol keys and non-enumerable keys are not checked.
1377
+ * @example
1378
+ *
1379
+ * ```ts
1380
+ * expect({ foo: 1, BAR: 2 }, 'to have a key matching', /^[a-z]+$/); // passes
1381
+ * expect({ foo: 1, BAR: 2 }, 'to have a prop matching', /^[a-z]+$/); // alias
1382
+ * expect({ foo: 1, BAR: 2 }, 'to have a field matching', /^[a-z]+$/); // alias
1383
+ * expect({ FOO: 1, BAR: 2 }, 'to have a key matching', /^[a-z]+$/); // fails
1384
+ * expect({ foo: 1 }, 'to have key matching', /foo/); // passes
1385
+ * ```
1386
+ *
1387
+ * @function
1388
+ * @group Collection Assertions
1389
+ * @bupkisAnchor object-to-have-a-key-matching-regexp
1390
+ * @bupkisAssertionCategory object
1391
+ */
1392
+ export const objectHasKeyMatchingAssertion = createAssertion([
1393
+ NonCollectionObjectSchema,
1394
+ [
1395
+ 'to have a key matching',
1396
+ 'to have key matching',
1397
+ 'to have a prop matching',
1398
+ 'to have prop matching',
1399
+ 'to have a property matching',
1400
+ 'to have property matching',
1401
+ 'to have a field matching',
1402
+ 'to have field matching',
1403
+ ],
1404
+ z.instanceof(RegExp),
1405
+ ], (subject, pattern) => {
1406
+ for (const key of keys(subject)) {
1407
+ if (pattern.global || pattern.sticky) {
1408
+ pattern.lastIndex = 0;
1409
+ }
1410
+ if (pattern.test(key)) {
1411
+ return;
1412
+ }
1413
+ }
1414
+ return {
1415
+ message: `Expected object to have a key matching ${inspect(pattern)}, but none matched`,
1416
+ };
1417
+ });
1418
+ //# sourceMappingURL=sync-collection.js.map