bupkis 0.18.2 → 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.
- package/CHANGELOG.md +29 -0
- package/README.md +1 -1
- package/dist/assertion/assertion-async.cjs +268 -0
- package/dist/assertion/assertion-async.cjs.map +1 -0
- package/dist/assertion/assertion-async.d.cts +40 -0
- package/dist/assertion/assertion-async.d.cts.map +1 -0
- package/dist/assertion/assertion-async.d.ts +40 -0
- package/dist/assertion/assertion-async.d.ts.map +1 -0
- package/dist/assertion/assertion-async.js +259 -0
- package/dist/assertion/assertion-async.js.map +1 -0
- package/dist/assertion/assertion-standard-schema-async.cjs +132 -0
- package/dist/assertion/assertion-standard-schema-async.cjs.map +1 -0
- package/dist/assertion/assertion-standard-schema-async.d.cts +52 -0
- package/dist/assertion/assertion-standard-schema-async.d.cts.map +1 -0
- package/dist/assertion/assertion-standard-schema-async.d.ts +52 -0
- package/dist/assertion/assertion-standard-schema-async.d.ts.map +1 -0
- package/dist/assertion/assertion-standard-schema-async.js +128 -0
- package/dist/assertion/assertion-standard-schema-async.js.map +1 -0
- package/dist/assertion/assertion-standard-schema-sync.cjs +141 -0
- package/dist/assertion/assertion-standard-schema-sync.cjs.map +1 -0
- package/dist/assertion/assertion-standard-schema-sync.d.cts +52 -0
- package/dist/assertion/assertion-standard-schema-sync.d.cts.map +1 -0
- package/dist/assertion/assertion-standard-schema-sync.d.ts +52 -0
- package/dist/assertion/assertion-standard-schema-sync.d.ts.map +1 -0
- package/dist/assertion/assertion-standard-schema-sync.js +137 -0
- package/dist/assertion/assertion-standard-schema-sync.js.map +1 -0
- package/dist/assertion/assertion-sync.cjs +281 -0
- package/dist/assertion/assertion-sync.cjs.map +1 -0
- package/dist/assertion/assertion-sync.d.cts +60 -0
- package/dist/assertion/assertion-sync.d.cts.map +1 -0
- package/dist/assertion/assertion-sync.d.ts +60 -0
- package/dist/assertion/assertion-sync.d.ts.map +1 -0
- package/dist/assertion/assertion-sync.js +275 -0
- package/dist/assertion/assertion-sync.js.map +1 -0
- package/dist/assertion/assertion-types.cjs +20 -0
- package/dist/assertion/assertion-types.cjs.map +1 -0
- package/dist/assertion/assertion-types.d.cts +1086 -0
- package/dist/assertion/assertion-types.d.cts.map +1 -0
- package/dist/assertion/assertion-types.d.ts +1086 -0
- package/dist/assertion/assertion-types.d.ts.map +1 -0
- package/dist/assertion/assertion-types.js +19 -0
- package/dist/assertion/assertion-types.js.map +1 -0
- package/dist/assertion/assertion.cjs +382 -0
- package/dist/assertion/assertion.cjs.map +1 -0
- package/dist/assertion/assertion.d.cts +109 -0
- package/dist/assertion/assertion.d.cts.map +1 -0
- package/dist/assertion/assertion.d.ts +109 -0
- package/dist/assertion/assertion.d.ts.map +1 -0
- package/dist/assertion/assertion.js +375 -0
- package/dist/assertion/assertion.js.map +1 -0
- package/dist/assertion/create.cjs +148 -0
- package/dist/assertion/create.cjs.map +1 -0
- package/dist/assertion/create.d.cts +85 -0
- package/dist/assertion/create.d.cts.map +1 -0
- package/dist/assertion/create.d.ts +85 -0
- package/dist/assertion/create.d.ts.map +1 -0
- package/dist/assertion/create.js +143 -0
- package/dist/assertion/create.js.map +1 -0
- package/dist/assertion/format-assertion-failure.cjs +63 -0
- package/dist/assertion/format-assertion-failure.cjs.map +1 -0
- package/dist/assertion/format-assertion-failure.d.cts +21 -0
- package/dist/assertion/format-assertion-failure.d.cts.map +1 -0
- package/dist/assertion/format-assertion-failure.d.ts +21 -0
- package/dist/assertion/format-assertion-failure.d.ts.map +1 -0
- package/dist/assertion/format-assertion-failure.js +59 -0
- package/dist/assertion/format-assertion-failure.js.map +1 -0
- package/dist/assertion/impl/assertion-util.cjs +68 -0
- package/dist/assertion/impl/assertion-util.cjs.map +1 -0
- package/dist/assertion/impl/assertion-util.d.cts +36 -0
- package/dist/assertion/impl/assertion-util.d.cts.map +1 -0
- package/dist/assertion/impl/assertion-util.d.ts +36 -0
- package/dist/assertion/impl/assertion-util.d.ts.map +1 -0
- package/dist/assertion/impl/assertion-util.js +62 -0
- package/dist/assertion/impl/assertion-util.js.map +1 -0
- package/dist/assertion/impl/async-iterable.cjs +627 -0
- package/dist/assertion/impl/async-iterable.cjs.map +1 -0
- package/dist/assertion/impl/async-iterable.d.cts +406 -0
- package/dist/assertion/impl/async-iterable.d.cts.map +1 -0
- package/dist/assertion/impl/async-iterable.d.ts +406 -0
- package/dist/assertion/impl/async-iterable.d.ts.map +1 -0
- package/dist/assertion/impl/async-iterable.js +624 -0
- package/dist/assertion/impl/async-iterable.js.map +1 -0
- package/dist/assertion/impl/async-parametric.cjs +412 -0
- package/dist/assertion/impl/async-parametric.cjs.map +1 -0
- package/dist/assertion/impl/async-parametric.d.cts +278 -0
- package/dist/assertion/impl/async-parametric.d.cts.map +1 -0
- package/dist/assertion/impl/async-parametric.d.ts +278 -0
- package/dist/assertion/impl/async-parametric.d.ts.map +1 -0
- package/dist/assertion/impl/async-parametric.js +409 -0
- package/dist/assertion/impl/async-parametric.js.map +1 -0
- package/dist/assertion/impl/async.cjs +56 -0
- package/dist/assertion/impl/async.cjs.map +1 -0
- package/dist/assertion/impl/async.d.cts +179 -0
- package/dist/assertion/impl/async.d.cts.map +1 -0
- package/dist/assertion/impl/async.d.ts +179 -0
- package/dist/assertion/impl/async.d.ts.map +1 -0
- package/dist/assertion/impl/async.js +39 -0
- package/dist/assertion/impl/async.js.map +1 -0
- package/dist/assertion/impl/index.cjs +37 -0
- package/dist/assertion/impl/index.cjs.map +1 -0
- package/dist/assertion/impl/index.d.cts +21 -0
- package/dist/assertion/impl/index.d.cts.map +1 -0
- package/dist/assertion/impl/index.d.ts +21 -0
- package/dist/assertion/impl/index.d.ts.map +1 -0
- package/dist/assertion/impl/index.js +21 -0
- package/dist/assertion/impl/index.js.map +1 -0
- package/dist/assertion/impl/iteration-util.cjs +297 -0
- package/dist/assertion/impl/iteration-util.cjs.map +1 -0
- package/dist/assertion/impl/iteration-util.d.cts +12 -0
- package/dist/assertion/impl/iteration-util.d.cts.map +1 -0
- package/dist/assertion/impl/iteration-util.d.ts +12 -0
- package/dist/assertion/impl/iteration-util.d.ts.map +1 -0
- package/dist/assertion/impl/iteration-util.js +282 -0
- package/dist/assertion/impl/iteration-util.js.map +1 -0
- package/dist/assertion/impl/snapshot.cjs +276 -0
- package/dist/assertion/impl/snapshot.cjs.map +1 -0
- package/dist/assertion/impl/snapshot.d.cts +278 -0
- package/dist/assertion/impl/snapshot.d.cts.map +1 -0
- package/dist/assertion/impl/snapshot.d.ts +278 -0
- package/dist/assertion/impl/snapshot.d.ts.map +1 -0
- package/dist/assertion/impl/snapshot.js +273 -0
- package/dist/assertion/impl/snapshot.js.map +1 -0
- package/dist/assertion/impl/sync-basic.cjs +553 -0
- package/dist/assertion/impl/sync-basic.cjs.map +1 -0
- package/dist/assertion/impl/sync-basic.d.cts +528 -0
- package/dist/assertion/impl/sync-basic.d.cts.map +1 -0
- package/dist/assertion/impl/sync-basic.d.ts +528 -0
- package/dist/assertion/impl/sync-basic.d.ts.map +1 -0
- package/dist/assertion/impl/sync-basic.js +550 -0
- package/dist/assertion/impl/sync-basic.js.map +1 -0
- package/dist/assertion/impl/sync-collection.cjs +1424 -0
- package/dist/assertion/impl/sync-collection.cjs.map +1 -0
- package/dist/assertion/impl/sync-collection.d.cts +922 -0
- package/dist/assertion/impl/sync-collection.d.cts.map +1 -0
- package/dist/assertion/impl/sync-collection.d.ts +922 -0
- package/dist/assertion/impl/sync-collection.d.ts.map +1 -0
- package/dist/assertion/impl/sync-collection.js +1418 -0
- package/dist/assertion/impl/sync-collection.js.map +1 -0
- package/dist/assertion/impl/sync-date.cjs +341 -0
- package/dist/assertion/impl/sync-date.cjs.map +1 -0
- package/dist/assertion/impl/sync-date.d.cts +209 -0
- package/dist/assertion/impl/sync-date.d.cts.map +1 -0
- package/dist/assertion/impl/sync-date.d.ts +209 -0
- package/dist/assertion/impl/sync-date.d.ts.map +1 -0
- package/dist/assertion/impl/sync-date.js +338 -0
- package/dist/assertion/impl/sync-date.js.map +1 -0
- package/dist/assertion/impl/sync-esoteric.cjs +214 -0
- package/dist/assertion/impl/sync-esoteric.cjs.map +1 -0
- package/dist/assertion/impl/sync-esoteric.d.cts +191 -0
- package/dist/assertion/impl/sync-esoteric.d.cts.map +1 -0
- package/dist/assertion/impl/sync-esoteric.d.ts +191 -0
- package/dist/assertion/impl/sync-esoteric.d.ts.map +1 -0
- package/dist/assertion/impl/sync-esoteric.js +211 -0
- package/dist/assertion/impl/sync-esoteric.js.map +1 -0
- package/dist/assertion/impl/sync-iterable.cjs +512 -0
- package/dist/assertion/impl/sync-iterable.cjs.map +1 -0
- package/dist/assertion/impl/sync-iterable.d.cts +334 -0
- package/dist/assertion/impl/sync-iterable.d.cts.map +1 -0
- package/dist/assertion/impl/sync-iterable.d.ts +334 -0
- package/dist/assertion/impl/sync-iterable.d.ts.map +1 -0
- package/dist/assertion/impl/sync-iterable.js +509 -0
- package/dist/assertion/impl/sync-iterable.js.map +1 -0
- package/dist/assertion/impl/sync-parametric.cjs +805 -0
- package/dist/assertion/impl/sync-parametric.cjs.map +1 -0
- package/dist/assertion/impl/sync-parametric.d.cts +560 -0
- package/dist/assertion/impl/sync-parametric.d.cts.map +1 -0
- package/dist/assertion/impl/sync-parametric.d.ts +560 -0
- package/dist/assertion/impl/sync-parametric.d.ts.map +1 -0
- package/dist/assertion/impl/sync-parametric.js +802 -0
- package/dist/assertion/impl/sync-parametric.js.map +1 -0
- package/dist/assertion/impl/sync.cjs +229 -0
- package/dist/assertion/impl/sync.cjs.map +1 -0
- package/dist/assertion/impl/sync.d.cts +536 -0
- package/dist/assertion/impl/sync.d.cts.map +1 -0
- package/dist/assertion/impl/sync.d.ts +536 -0
- package/dist/assertion/impl/sync.d.ts.map +1 -0
- package/dist/assertion/impl/sync.js +212 -0
- package/dist/assertion/impl/sync.js.map +1 -0
- package/dist/assertion/index.cjs +38 -0
- package/dist/assertion/index.cjs.map +1 -0
- package/dist/assertion/index.d.cts +18 -0
- package/dist/assertion/index.d.cts.map +1 -0
- package/dist/assertion/index.d.ts +18 -0
- package/dist/assertion/index.d.ts.map +1 -0
- package/dist/assertion/index.js +17 -0
- package/dist/assertion/index.js.map +1 -0
- package/dist/assertion/slotify.cjs +165 -0
- package/dist/assertion/slotify.cjs.map +1 -0
- package/dist/assertion/slotify.d.cts +11 -0
- package/dist/assertion/slotify.d.cts.map +1 -0
- package/dist/assertion/slotify.d.ts +11 -0
- package/dist/assertion/slotify.d.ts.map +1 -0
- package/dist/assertion/slotify.js +161 -0
- package/dist/assertion/slotify.js.map +1 -0
- package/dist/bootstrap.cjs +43 -0
- package/dist/bootstrap.cjs.map +1 -0
- package/dist/bootstrap.d.cts +27 -0
- package/dist/bootstrap.d.cts.map +1 -0
- package/dist/bootstrap.d.ts +27 -0
- package/dist/bootstrap.d.ts.map +1 -0
- package/dist/bootstrap.js +40 -0
- package/dist/bootstrap.js.map +1 -0
- package/dist/constant.cjs +82 -0
- package/dist/constant.cjs.map +1 -0
- package/dist/constant.d.cts +69 -0
- package/dist/constant.d.cts.map +1 -0
- package/dist/constant.d.ts +69 -0
- package/dist/constant.d.ts.map +1 -0
- package/dist/constant.js +79 -0
- package/dist/constant.js.map +1 -0
- package/dist/diff.cjs +340 -0
- package/dist/diff.cjs.map +1 -0
- package/dist/diff.d.cts +51 -0
- package/dist/diff.d.cts.map +1 -0
- package/dist/diff.d.ts +51 -0
- package/dist/diff.d.ts.map +1 -0
- package/dist/diff.js +334 -0
- package/dist/diff.js.map +1 -0
- package/dist/error.cjs +194 -0
- package/dist/error.cjs.map +1 -0
- package/dist/error.d.cts +212 -0
- package/dist/error.d.cts.map +1 -0
- package/dist/error.d.ts +212 -0
- package/dist/error.d.ts.map +1 -0
- package/dist/error.js +181 -0
- package/dist/error.js.map +1 -0
- package/dist/expect.cjs +587 -0
- package/dist/expect.cjs.map +1 -0
- package/dist/expect.d.cts +138 -0
- package/dist/expect.d.cts.map +1 -0
- package/dist/expect.d.ts +138 -0
- package/dist/expect.d.ts.map +1 -0
- package/dist/expect.js +582 -0
- package/dist/expect.js.map +1 -0
- package/dist/guards.cjs +291 -0
- package/dist/guards.cjs.map +1 -0
- package/dist/guards.d.cts +225 -0
- package/dist/guards.d.cts.map +1 -0
- package/dist/guards.d.ts +225 -0
- package/dist/guards.d.ts.map +1 -0
- package/dist/guards.js +273 -0
- package/dist/guards.js.map +1 -0
- package/dist/index.cjs +111 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +460 -0
- package/dist/index.d.cts.map +1 -0
- package/dist/index.d.ts +460 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +71 -0
- package/dist/index.js.map +1 -0
- package/dist/internal-schema.cjs +234 -0
- package/dist/internal-schema.cjs.map +1 -0
- package/dist/internal-schema.d.cts +8 -0
- package/dist/internal-schema.d.cts.map +1 -0
- package/dist/internal-schema.d.ts +8 -0
- package/dist/internal-schema.d.ts.map +1 -0
- package/dist/internal-schema.js +229 -0
- package/dist/internal-schema.js.map +1 -0
- package/dist/metadata.cjs +57 -0
- package/dist/metadata.cjs.map +1 -0
- package/dist/metadata.d.cts +27 -0
- package/dist/metadata.d.cts.map +1 -0
- package/dist/metadata.d.ts +27 -0
- package/dist/metadata.d.ts.map +1 -0
- package/dist/metadata.js +54 -0
- package/dist/metadata.js.map +1 -0
- package/dist/schema.cjs +1522 -0
- package/dist/schema.cjs.map +1 -0
- package/dist/schema.d.cts +1196 -0
- package/dist/schema.d.cts.map +1 -0
- package/dist/schema.d.ts +1196 -0
- package/dist/schema.d.ts.map +1 -0
- package/dist/schema.js +1516 -0
- package/dist/schema.js.map +1 -0
- package/dist/snapshot/adapter.cjs +29 -0
- package/dist/snapshot/adapter.cjs.map +1 -0
- package/dist/snapshot/adapter.d.cts +258 -0
- package/dist/snapshot/adapter.d.cts.map +1 -0
- package/dist/snapshot/adapter.d.ts +258 -0
- package/dist/snapshot/adapter.d.ts.map +1 -0
- package/dist/snapshot/adapter.js +25 -0
- package/dist/snapshot/adapter.js.map +1 -0
- package/dist/snapshot/adapters/fallback.cjs +452 -0
- package/dist/snapshot/adapters/fallback.cjs.map +1 -0
- package/dist/snapshot/adapters/fallback.d.cts +185 -0
- package/dist/snapshot/adapters/fallback.d.cts.map +1 -0
- package/dist/snapshot/adapters/fallback.d.ts +185 -0
- package/dist/snapshot/adapters/fallback.d.ts.map +1 -0
- package/dist/snapshot/adapters/fallback.js +445 -0
- package/dist/snapshot/adapters/fallback.js.map +1 -0
- package/dist/snapshot/adapters/node-test.cjs +297 -0
- package/dist/snapshot/adapters/node-test.cjs.map +1 -0
- package/dist/snapshot/adapters/node-test.d.cts +131 -0
- package/dist/snapshot/adapters/node-test.d.cts.map +1 -0
- package/dist/snapshot/adapters/node-test.d.ts +131 -0
- package/dist/snapshot/adapters/node-test.d.ts.map +1 -0
- package/dist/snapshot/adapters/node-test.js +293 -0
- package/dist/snapshot/adapters/node-test.js.map +1 -0
- package/dist/snapshot/index.cjs +61 -0
- package/dist/snapshot/index.cjs.map +1 -0
- package/dist/snapshot/index.d.cts +40 -0
- package/dist/snapshot/index.d.cts.map +1 -0
- package/dist/snapshot/index.d.ts +40 -0
- package/dist/snapshot/index.d.ts.map +1 -0
- package/dist/snapshot/index.js +44 -0
- package/dist/snapshot/index.js.map +1 -0
- package/dist/snapshot/node-version.cjs +49 -0
- package/dist/snapshot/node-version.cjs.map +1 -0
- package/dist/snapshot/node-version.d.cts +34 -0
- package/dist/snapshot/node-version.d.cts.map +1 -0
- package/dist/snapshot/node-version.d.ts +34 -0
- package/dist/snapshot/node-version.d.ts.map +1 -0
- package/dist/snapshot/node-version.js +44 -0
- package/dist/snapshot/node-version.js.map +1 -0
- package/dist/snapshot/select-adapter.cjs +170 -0
- package/dist/snapshot/select-adapter.cjs.map +1 -0
- package/dist/snapshot/select-adapter.d.cts +128 -0
- package/dist/snapshot/select-adapter.d.cts.map +1 -0
- package/dist/snapshot/select-adapter.d.ts +128 -0
- package/dist/snapshot/select-adapter.d.ts.map +1 -0
- package/dist/snapshot/select-adapter.js +164 -0
- package/dist/snapshot/select-adapter.js.map +1 -0
- package/dist/snapshot/serializer.cjs +245 -0
- package/dist/snapshot/serializer.cjs.map +1 -0
- package/dist/snapshot/serializer.d.cts +126 -0
- package/dist/snapshot/serializer.d.cts.map +1 -0
- package/dist/snapshot/serializer.d.ts +126 -0
- package/dist/snapshot/serializer.d.ts.map +1 -0
- package/dist/snapshot/serializer.js +237 -0
- package/dist/snapshot/serializer.js.map +1 -0
- package/dist/standard-schema.cjs +13 -0
- package/dist/standard-schema.cjs.map +1 -0
- package/dist/standard-schema.d.cts +192 -0
- package/dist/standard-schema.d.cts.map +1 -0
- package/dist/standard-schema.d.ts +192 -0
- package/dist/standard-schema.d.ts.map +1 -0
- package/dist/standard-schema.js +12 -0
- package/dist/standard-schema.js.map +1 -0
- package/dist/types.cjs +22 -0
- package/dist/types.cjs.map +1 -0
- package/dist/types.d.cts +756 -0
- package/dist/types.d.cts.map +1 -0
- package/dist/types.d.ts +756 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +21 -0
- package/dist/types.js.map +1 -0
- package/dist/use.cjs +240 -0
- package/dist/use.cjs.map +1 -0
- package/dist/use.d.cts +8 -0
- package/dist/use.d.cts.map +1 -0
- package/dist/use.d.ts +8 -0
- package/dist/use.d.ts.map +1 -0
- package/dist/use.js +236 -0
- package/dist/use.js.map +1 -0
- package/dist/util.cjs +255 -0
- package/dist/util.cjs.map +1 -0
- package/dist/util.d.cts +141 -0
- package/dist/util.d.cts.map +1 -0
- package/dist/util.d.ts +141 -0
- package/dist/util.d.ts.map +1 -0
- package/dist/util.js +234 -0
- package/dist/util.js.map +1 -0
- package/dist/value-to-schema.cjs +537 -0
- package/dist/value-to-schema.cjs.map +1 -0
- package/dist/value-to-schema.d.cts +144 -0
- package/dist/value-to-schema.d.cts.map +1 -0
- package/dist/value-to-schema.d.ts +144 -0
- package/dist/value-to-schema.d.ts.map +1 -0
- package/dist/value-to-schema.js +533 -0
- package/dist/value-to-schema.js.map +1 -0
- package/package.json +24 -21
- package/src/assertion/assertion-sync.ts +1 -1
- package/src/assertion/assertion-types.ts +4 -8
- package/src/assertion/assertion.ts +12 -7
- package/src/assertion/format-assertion-failure.ts +2 -0
- package/src/assertion/impl/assertion-util.ts +1 -2
- package/src/assertion/impl/iteration-util.ts +3 -5
- package/src/assertion/impl/sync-collection.ts +633 -7
- package/src/assertion/impl/sync.ts +27 -0
- package/src/error.ts +13 -22
- package/src/expect.ts +1 -1
- package/src/guards.ts +8 -14
- package/src/internal-schema.ts +4 -8
- package/src/metadata.ts +1 -2
- package/src/snapshot/adapter.ts +2 -3
- package/src/snapshot/adapters/fallback.ts +2 -3
- package/src/snapshot/adapters/node-test.ts +14 -20
- package/src/snapshot/select-adapter.ts +3 -3
- package/src/snapshot/serializer.ts +2 -3
- 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
|