Skip to content

Commit edf0aa0

Browse files
authored
feat(bupkis): consolidate satisfy and deep equal assertions (#338)
1 parent 1a67238 commit edf0aa0

File tree

15 files changed

+1440
-652
lines changed

15 files changed

+1440
-652
lines changed

packages/bupkis/src/assertion/impl/sync-parametric.ts

Lines changed: 34 additions & 104 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ import { BupkisError, InvalidObjectSchemaError } from '../../error.js';
2020
import { isA, isError, isNonNullObject, isString } from '../../guards.js';
2121
import {
2222
AnyObjectSchema,
23-
ArrayLikeSchema,
2423
BigintSchema,
2524
BooleanSchema,
2625
ConstructibleSchema,
@@ -39,7 +38,6 @@ import {
3938
SymbolSchema,
4039
UndefinedSchema,
4140
UnknownArraySchema,
42-
UnknownRecordSchema,
4341
UnknownSchema,
4442
WeakMapSchema,
4543
WeakRefSchema,
@@ -590,95 +588,36 @@ export const strictEqualityAssertion = createAssertion(
590588
);
591589

592590
/**
593-
* Assertion for testing deep equality between objects.
591+
* Assertion for testing deep equality between any values.
592+
*
593+
* Works with primitives, objects, arrays, Maps, Sets, and other types.
594594
*
595595
* @example
596596
*
597597
* ```typescript
598+
* // Primitives
599+
* expect(42, 'to deep equal', 42); // passes
600+
* expect('hello', 'to deeply equal', 'world'); // fails
601+
*
602+
* // Objects
598603
* expect({ a: 1, b: 2 }, 'to deep equal', { a: 1, b: 2 }); // passes
599604
* expect({ a: 1 }, 'to deeply equal', { a: 1, b: 2 }); // fails
600-
* ```
601-
*
602-
* @group Parametric Assertions (Sync)
603-
*/
604-
export const objectDeepEqualAssertion = createAssertion(
605-
[UnknownRecordSchema, ['to deep equal', 'to deeply equal'], UnknownSchema],
606-
(_, expected) => valueToSchema(expected, valueToSchemaOptionsForDeepEqual),
607-
);
608-
609-
/**
610-
* Assertion for testing deep equality between array-like structures.
611605
*
612-
* @example
613-
*
614-
* ```typescript
606+
* // Arrays
615607
* expect([1, 2, 3], 'to deep equal', [1, 2, 3]); // passes
616-
* expect([1, 2], 'to deeply equal', [1, 2, 3]); // fails
617-
* ```
618-
*
619-
* @group Parametric Assertions (Sync)
620-
*/
621-
export const arrayDeepEqualAssertion = createAssertion(
622-
[ArrayLikeSchema, ['to deep equal', 'to deeply equal'], UnknownSchema],
623-
(_, expected) => {
624-
return valueToSchema(expected, valueToSchemaOptionsForDeepEqual);
625-
},
626-
);
627-
628-
/**
629-
* Assertion for testing deep equality between Map instances.
630-
*
631-
* @example
632-
*
633-
* ```typescript
634-
* const map1 = new Map([
635-
* ['a', 1],
636-
* ['b', 2],
637-
* ]);
638-
* const map2 = new Map([
639-
* ['a', 1],
640-
* ['b', 2],
641-
* ]);
642-
* expect(map1, 'to deep equal', map2); // passes
643-
*
644-
* const map3 = new Map([['a', 1]]);
645-
* expect(map1, 'to deeply equal', map3); // fails
646-
* ```
647-
*
648-
* @group Parametric Assertions (Sync)
649-
* @bupkisAnchor map-to-deep-equal
650-
* @bupkisAssertionCategory collections
651-
*/
652-
export const mapDeepEqualAssertion = createAssertion(
653-
[MapSchema, ['to deep equal', 'to deeply equal'], UnknownSchema],
654-
(_, expected) => {
655-
return valueToSchema(expected, valueToSchemaOptionsForDeepEqual);
656-
},
657-
);
658-
659-
/**
660-
* Assertion for testing deep equality between Set instances.
661-
*
662-
* @example
663-
*
664-
* ```typescript
665-
* const set1 = new Set([1, 2, 3]);
666-
* const set2 = new Set([1, 2, 3]);
667-
* expect(set1, 'to deep equal', set2); // passes
668608
*
669-
* const set3 = new Set([1, 2]);
670-
* expect(set1, 'to deeply equal', set3); // fails
609+
* // Maps and Sets
610+
* expect(new Map([['a', 1]]), 'to deep equal', new Map([['a', 1]])); // passes
611+
* expect(new Set([1, 2]), 'to deeply equal', new Set([1, 2])); // passes
671612
* ```
672613
*
673614
* @group Parametric Assertions (Sync)
674-
* @bupkisAnchor set-to-deep-equal
675-
* @bupkisAssertionCategory collections
615+
* @bupkisAnchor unknown-to-deep-equal-any
616+
* @bupkisAssertionCategory equality
676617
*/
677-
export const setDeepEqualAssertion = createAssertion(
678-
[SetSchema, ['to deep equal', 'to deeply equal'], UnknownSchema],
679-
(_, expected) => {
680-
return valueToSchema(expected, valueToSchemaOptionsForDeepEqual);
681-
},
618+
export const deepEqualAssertion = createAssertion(
619+
[['to deep equal', 'to deeply equal'], UnknownSchema],
620+
(_, expected) => valueToSchema(expected, valueToSchemaOptionsForDeepEqual),
682621
);
683622

684623
/**
@@ -975,44 +914,35 @@ export const stringLengthAssertion = createAssertion(
975914
);
976915

977916
/**
978-
* Assertion for testing if an object satisfies a pattern or shape.
917+
* Assertion for testing if a value satisfies a pattern or shape.
918+
*
919+
* Works with any value type: primitives, objects, arrays, or cross-type checks.
920+
* Uses partial matching semantics - extra properties are allowed in objects.
979921
*
980922
* @example
981923
*
982924
* ```typescript
925+
* // Primitives
926+
* expect(42, 'to satisfy', 42); // passes
927+
* expect('hello', 'satisfies', 'hello'); // passes
928+
*
929+
* // Objects (partial matching)
983930
* expect({ name: 'John', age: 30 }, 'to satisfy', { name: 'John' }); // passes
984931
* expect({ name: 'John' }, 'to be like', { name: 'John', age: 30 }); // fails
985-
* ```
986932
*
987-
* @group Parametric Assertions (Sync)
988-
* @bupkisAnchor object-to-satisfy-any
989-
* @bupkisAssertionCategory object
990-
* @bupkisRedirect satisfies
991-
*/
992-
export const objectSatisfiesAssertion = createAssertion(
993-
[
994-
AnyObjectSchema.nonoptional(),
995-
['to satisfy', 'to be like', 'satisfies'],
996-
UnknownSchema,
997-
],
998-
(_subject, shape) => valueToSchema(shape, valueToSchemaOptionsForSatisfies),
999-
);
1000-
1001-
/**
1002-
* Assertion for testing if an array-like structure satisfies a pattern or
1003-
* shape.
933+
* // Arrays
934+
* expect([1, 2, 3], 'to satisfy', [1, 2, 3]); // passes
1004935
*
1005-
* @example
1006-
*
1007-
* ```typescript
1008-
* expect([1, 2, 3], 'to satisfy', [1, NumberSchema, 3]); // passes
1009-
* expect([1, 'two'], 'to be like', [1, NumberSchema]); // fails
936+
* // Cross-type satisfaction
937+
* expect([1, 2, 3], 'to satisfy', { length: 3 }); // passes
1010938
* ```
1011939
*
1012940
* @group Parametric Assertions (Sync)
941+
* @bupkisAnchor unknown-to-satisfy-any
942+
* @bupkisAssertionCategory equality
1013943
*/
1014-
export const arraySatisfiesAssertion = createAssertion(
1015-
[ArrayLikeSchema, ['to satisfy', 'to be like'], UnknownSchema],
944+
export const satisfiesAssertion = createAssertion(
945+
[['to satisfy', 'to be like', 'satisfies'], UnknownSchema],
1016946
(_subject, shape) => valueToSchema(shape, valueToSchemaOptionsForSatisfies),
1017947
);
1018948

packages/bupkis/src/assertion/impl/sync.ts

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -106,8 +106,7 @@ import {
106106
} from './sync-esoteric.js';
107107
import { SyncIterableAssertions } from './sync-iterable.js';
108108
import {
109-
arrayDeepEqualAssertion,
110-
arraySatisfiesAssertion,
109+
deepEqualAssertion,
111110
errorMessageAssertion,
112111
errorMessageMatchingAssertion,
113112
functionArityAssertion,
@@ -116,17 +115,14 @@ import {
116115
functionThrowsTypeAssertion,
117116
functionThrowsTypeSatisfyingAssertion,
118117
instanceOfAssertion,
119-
mapDeepEqualAssertion,
120118
numberCloseToAssertion,
121119
numberGreaterThanAssertion,
122120
numberGreaterThanOrEqualAssertion,
123121
numberLessThanAssertion,
124122
numberLessThanOrEqualAssertion,
125123
numberWithinRangeAssertion,
126-
objectDeepEqualAssertion,
127-
objectSatisfiesAssertion,
128124
oneOfAssertion,
129-
setDeepEqualAssertion,
125+
satisfiesAssertion,
130126
strictEqualityAssertion,
131127
stringBeginsWithAssertion,
132128
stringEndsWithAssertion,
@@ -242,19 +238,15 @@ export const SyncParametricAssertions = [
242238
errorMessageAssertion,
243239
errorMessageMatchingAssertion,
244240
strictEqualityAssertion,
245-
objectDeepEqualAssertion,
246-
arrayDeepEqualAssertion,
247-
mapDeepEqualAssertion,
248-
setDeepEqualAssertion,
241+
deepEqualAssertion,
249242
functionThrowsAssertion,
250243
functionThrowsTypeAssertion,
251244
functionThrowsSatisfyingAssertion,
252245
functionThrowsTypeSatisfyingAssertion,
253246
stringIncludesAssertion,
254247
stringLengthAssertion,
255248
stringMatchesAssertion,
256-
objectSatisfiesAssertion,
257-
arraySatisfiesAssertion,
249+
satisfiesAssertion,
258250
] as const;
259251

260252
/**

0 commit comments

Comments
 (0)