@haskou/value-objects 1.0.1
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/.editorconfig +15 -0
- package/.eslintignore +3 -0
- package/.eslintrc.json +218 -0
- package/.prettierrc.json +13 -0
- package/README.md +156 -0
- package/TECHNICAL_DOCUMENTATION.md +1091 -0
- package/jest.config.ts +30 -0
- package/package.json +49 -0
- package/src/errors/BaseError.ts +20 -0
- package/src/errors/DomainError.ts +12 -0
- package/src/errors/InvalidColorError.ts +7 -0
- package/src/errors/InvalidDayError.ts +7 -0
- package/src/errors/InvalidDayFormatError.ts +7 -0
- package/src/errors/InvalidEmailError.ts +7 -0
- package/src/errors/InvalidHourError.ts +7 -0
- package/src/errors/InvalidIntegerError.ts +7 -0
- package/src/errors/InvalidLatitudeError.ts +7 -0
- package/src/errors/InvalidLongitudeError.ts +7 -0
- package/src/errors/InvalidMinutesError.ts +7 -0
- package/src/errors/InvalidNumberError.ts +7 -0
- package/src/errors/InvalidPositiveNumberError.ts +7 -0
- package/src/errors/InvalidStringLengthError.ts +9 -0
- package/src/errors/InvalidTimestampIntervalError.ts +10 -0
- package/src/errors/NullObjectError.ts +8 -0
- package/src/errors/ValueNotInEnumError.ts +9 -0
- package/src/errors/index.ts +17 -0
- package/src/index.ts +5 -0
- package/src/interfaces/PrimitiveOf.ts +5 -0
- package/src/interfaces/index.ts +1 -0
- package/src/patterns/Assert.ts +15 -0
- package/src/patterns/NullObject.ts +60 -0
- package/src/patterns/ValueObject.ts +40 -0
- package/src/patterns/index.ts +3 -0
- package/src/types/Nullish.ts +1 -0
- package/src/types/Primitive.ts +1 -0
- package/src/types/index.ts +2 -0
- package/src/value-objects/Color.ts +39 -0
- package/src/value-objects/Email.ts +23 -0
- package/src/value-objects/Enum.ts +31 -0
- package/src/value-objects/Integer.ts +22 -0
- package/src/value-objects/NumberValueObject.ts +56 -0
- package/src/value-objects/PositiveNumber.ts +20 -0
- package/src/value-objects/StringValueObject.ts +27 -0
- package/src/value-objects/coordinates/Coordinates.ts +30 -0
- package/src/value-objects/coordinates/Latitude.ts +22 -0
- package/src/value-objects/coordinates/Longitude.ts +25 -0
- package/src/value-objects/coordinates/index.ts +3 -0
- package/src/value-objects/index.ts +9 -0
- package/src/value-objects/time/CalendarDay.ts +91 -0
- package/src/value-objects/time/Day.ts +17 -0
- package/src/value-objects/time/DayOfWeek.ts +60 -0
- package/src/value-objects/time/Duration.ts +142 -0
- package/src/value-objects/time/Hour.ts +105 -0
- package/src/value-objects/time/Month.ts +39 -0
- package/src/value-objects/time/MonthOfYear.ts +52 -0
- package/src/value-objects/time/Timestamp.ts +208 -0
- package/src/value-objects/time/TimestampInterval.ts +122 -0
- package/src/value-objects/time/Year.ts +27 -0
- package/src/value-objects/time/index.ts +10 -0
- package/tests/errors/BaseError.spec.ts +63 -0
- package/tests/errors/DomainError.spec.ts +52 -0
- package/tests/patterns/Assert.spec.ts +29 -0
- package/tests/patterns/NullObject.spec.ts +55 -0
- package/tests/setup.jest.ts +2 -0
- package/tests/value-objects/Color.spec.ts +214 -0
- package/tests/value-objects/Email.spec.ts +145 -0
- package/tests/value-objects/Enum.spec.ts +293 -0
- package/tests/value-objects/Integer.spec.ts +38 -0
- package/tests/value-objects/NumberValueObject.spec.ts +446 -0
- package/tests/value-objects/PositiveNumber.spec.ts +274 -0
- package/tests/value-objects/StringValueObject.spec.ts +135 -0
- package/tests/value-objects/coordinates/Coordinates.spec.ts +90 -0
- package/tests/value-objects/coordinates/Latitude.spec.ts +24 -0
- package/tests/value-objects/coordinates/Longitude.spec.ts +24 -0
- package/tests/value-objects/time/CalendarDay.spec.ts +182 -0
- package/tests/value-objects/time/Day.spec.ts +29 -0
- package/tests/value-objects/time/DayOfWeek.spec.ts +71 -0
- package/tests/value-objects/time/Duration.spec.ts +278 -0
- package/tests/value-objects/time/Hour.spec.ts +197 -0
- package/tests/value-objects/time/MonthOfYear.spec.ts +111 -0
- package/tests/value-objects/time/Timestamp.spec.ts +497 -0
- package/tests/value-objects/time/TimestampInterval.spec.ts +383 -0
- package/tests/value-objects/time/Year.spec.ts +48 -0
- package/tsconfig.jest.json +33 -0
- package/tsconfig.json +42 -0
|
@@ -0,0 +1,446 @@
|
|
|
1
|
+
import { InvalidNumberError, NullObject, NumberValueObject } from '../../src';
|
|
2
|
+
|
|
3
|
+
describe('NumberValueObject', () => {
|
|
4
|
+
describe('constructor', () => {
|
|
5
|
+
it('should return a NullValueObject when a Nullish is received', () => {
|
|
6
|
+
expect(
|
|
7
|
+
() => new NumberValueObject(undefined as unknown as number),
|
|
8
|
+
).not.toThrow();
|
|
9
|
+
expect(
|
|
10
|
+
NullObject.isNullObject(
|
|
11
|
+
new NumberValueObject(undefined as unknown as number),
|
|
12
|
+
),
|
|
13
|
+
).toBeTrue();
|
|
14
|
+
expect(
|
|
15
|
+
NullObject.isNullObject(
|
|
16
|
+
new NumberValueObject(null as unknown as number),
|
|
17
|
+
),
|
|
18
|
+
).toBeTrue();
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
it('should throw InvalidNumberError for NaN', () => {
|
|
22
|
+
const value = NaN;
|
|
23
|
+
|
|
24
|
+
expect(() => new NumberValueObject(value)).toThrow(InvalidNumberError);
|
|
25
|
+
expect(() => new NumberValueObject(value)).toThrow(
|
|
26
|
+
`Invalid number ${value}`,
|
|
27
|
+
);
|
|
28
|
+
});
|
|
29
|
+
it('should throw InvalidNumberError for a parsed string', () => {
|
|
30
|
+
const value = parseInt('Not a number');
|
|
31
|
+
|
|
32
|
+
expect(() => new NumberValueObject(value)).toThrow(InvalidNumberError);
|
|
33
|
+
expect(() => new NumberValueObject(value)).toThrow(
|
|
34
|
+
`Invalid number ${value}`,
|
|
35
|
+
);
|
|
36
|
+
});
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
describe('isZero', () => {
|
|
40
|
+
it('should return true when value is 0', () => {
|
|
41
|
+
expect(new NumberValueObject(0).isZero()).toBeTrue();
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
it('should return false when value is not 0', () => {
|
|
45
|
+
expect(new NumberValueObject(1).isZero()).toBeFalse();
|
|
46
|
+
});
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
describe('isGreaterThan', () => {
|
|
50
|
+
it('should return true when value is greater than other', () => {
|
|
51
|
+
expect(
|
|
52
|
+
new NumberValueObject(1).isGreaterThan(new NumberValueObject(0)),
|
|
53
|
+
).toBeTrue();
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
it('should return false when value is not greater than other', () => {
|
|
57
|
+
expect(
|
|
58
|
+
new NumberValueObject(0).isGreaterThan(new NumberValueObject(1)),
|
|
59
|
+
).toBeFalse();
|
|
60
|
+
});
|
|
61
|
+
});
|
|
62
|
+
describe('isGreaterOrEqualThan', () => {
|
|
63
|
+
it('should return true when value is greater than other', () => {
|
|
64
|
+
expect(
|
|
65
|
+
new NumberValueObject(1).isGreaterOrEqualThan(new NumberValueObject(0)),
|
|
66
|
+
).toBeTrue();
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
it('should return true when value is the equal than other', () => {
|
|
70
|
+
expect(
|
|
71
|
+
new NumberValueObject(1).isGreaterOrEqualThan(new NumberValueObject(1)),
|
|
72
|
+
).toBeTrue();
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
it('should return false when value is not greater than other', () => {
|
|
76
|
+
expect(
|
|
77
|
+
new NumberValueObject(0).isGreaterOrEqualThan(new NumberValueObject(1)),
|
|
78
|
+
).toBeFalse();
|
|
79
|
+
});
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
describe('isLessThan', () => {
|
|
83
|
+
it('should return true when value is less than other', () => {
|
|
84
|
+
expect(
|
|
85
|
+
new NumberValueObject(0).isLessThan(new NumberValueObject(1)),
|
|
86
|
+
).toBeTrue();
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
it('should return false when value is not less than other', () => {
|
|
90
|
+
expect(
|
|
91
|
+
new NumberValueObject(1).isLessThan(new NumberValueObject(0)),
|
|
92
|
+
).toBeFalse();
|
|
93
|
+
});
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
describe('isLessOrEqualThan', () => {
|
|
97
|
+
it('should return true when value is less than other', () => {
|
|
98
|
+
expect(
|
|
99
|
+
new NumberValueObject(0).isLessOrEqualThan(new NumberValueObject(1)),
|
|
100
|
+
).toBeTrue();
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
it('should return true when value is equal than other', () => {
|
|
104
|
+
expect(
|
|
105
|
+
new NumberValueObject(1).isLessOrEqualThan(new NumberValueObject(1)),
|
|
106
|
+
).toBeTrue();
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
it('should return false when value is not less than other', () => {
|
|
110
|
+
expect(
|
|
111
|
+
new NumberValueObject(1).isLessOrEqualThan(new NumberValueObject(0)),
|
|
112
|
+
).toBeFalse();
|
|
113
|
+
});
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
describe('add', () => {
|
|
117
|
+
it('should return a new NumberValueObject with the sum of the two values', () => {
|
|
118
|
+
const value = new NumberValueObject(1);
|
|
119
|
+
const other = new NumberValueObject(2);
|
|
120
|
+
const result = value.add(other);
|
|
121
|
+
expect(result.valueOf()).toEqual(3);
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
it('should not mutate original objects when adding', () => {
|
|
125
|
+
const original = new NumberValueObject(10);
|
|
126
|
+
const other = new NumberValueObject(5);
|
|
127
|
+
const originalValue = original.valueOf();
|
|
128
|
+
const otherValue = other.valueOf();
|
|
129
|
+
|
|
130
|
+
const result = original.add(other);
|
|
131
|
+
|
|
132
|
+
// Original objects should remain unchanged
|
|
133
|
+
expect(original.valueOf()).toBe(originalValue);
|
|
134
|
+
expect(original.valueOf()).toBe(10);
|
|
135
|
+
expect(other.valueOf()).toBe(otherValue);
|
|
136
|
+
expect(other.valueOf()).toBe(5);
|
|
137
|
+
|
|
138
|
+
// Result should be a new instance
|
|
139
|
+
expect(result.valueOf()).toBe(15);
|
|
140
|
+
expect(result).not.toBe(original);
|
|
141
|
+
expect(result).not.toBe(other);
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
it('should work with primitive numbers and maintain immutability', () => {
|
|
145
|
+
const original = new NumberValueObject(15);
|
|
146
|
+
const originalValue = original.valueOf();
|
|
147
|
+
|
|
148
|
+
const result = original.add(5);
|
|
149
|
+
|
|
150
|
+
// Original should remain unchanged
|
|
151
|
+
expect(original.valueOf()).toBe(originalValue);
|
|
152
|
+
expect(original.valueOf()).toBe(15);
|
|
153
|
+
|
|
154
|
+
// Result should be correct and a new instance
|
|
155
|
+
expect(result.valueOf()).toBe(20);
|
|
156
|
+
expect(result).not.toBe(original);
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
it('should maintain immutability when adding zero', () => {
|
|
160
|
+
const original = new NumberValueObject(42);
|
|
161
|
+
const zero = new NumberValueObject(0);
|
|
162
|
+
const originalValue = original.valueOf();
|
|
163
|
+
|
|
164
|
+
const result = original.add(zero);
|
|
165
|
+
|
|
166
|
+
// Original should remain unchanged
|
|
167
|
+
expect(original.valueOf()).toBe(originalValue);
|
|
168
|
+
expect(original.valueOf()).toBe(42);
|
|
169
|
+
expect(zero.valueOf()).toBe(0);
|
|
170
|
+
|
|
171
|
+
// Result should be correct and a new instance
|
|
172
|
+
expect(result.valueOf()).toBe(42);
|
|
173
|
+
expect(result).not.toBe(original);
|
|
174
|
+
});
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
describe('subtract', () => {
|
|
178
|
+
it('should return a new NumberValueObject with the difference of the two values', () => {
|
|
179
|
+
const value = new NumberValueObject(1);
|
|
180
|
+
const other = new NumberValueObject(2);
|
|
181
|
+
const result = value.subtract(other);
|
|
182
|
+
expect(result.valueOf()).toEqual(-1);
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
it('should not mutate original objects when subtracting', () => {
|
|
186
|
+
const original = new NumberValueObject(10);
|
|
187
|
+
const other = new NumberValueObject(3);
|
|
188
|
+
const originalValue = original.valueOf();
|
|
189
|
+
const otherValue = other.valueOf();
|
|
190
|
+
|
|
191
|
+
const result = original.subtract(other);
|
|
192
|
+
|
|
193
|
+
// Original objects should remain unchanged
|
|
194
|
+
expect(original.valueOf()).toBe(originalValue);
|
|
195
|
+
expect(original.valueOf()).toBe(10);
|
|
196
|
+
expect(other.valueOf()).toBe(otherValue);
|
|
197
|
+
expect(other.valueOf()).toBe(3);
|
|
198
|
+
|
|
199
|
+
// Result should be a new instance
|
|
200
|
+
expect(result.valueOf()).toBe(7);
|
|
201
|
+
expect(result).not.toBe(original);
|
|
202
|
+
expect(result).not.toBe(other);
|
|
203
|
+
});
|
|
204
|
+
|
|
205
|
+
it('should work with primitive numbers and maintain immutability', () => {
|
|
206
|
+
const original = new NumberValueObject(15);
|
|
207
|
+
const originalValue = original.valueOf();
|
|
208
|
+
|
|
209
|
+
const result = original.subtract(3);
|
|
210
|
+
|
|
211
|
+
// Original should remain unchanged
|
|
212
|
+
expect(original.valueOf()).toBe(originalValue);
|
|
213
|
+
expect(original.valueOf()).toBe(15);
|
|
214
|
+
|
|
215
|
+
// Result should be correct and a new instance
|
|
216
|
+
expect(result.valueOf()).toBe(12);
|
|
217
|
+
expect(result).not.toBe(original);
|
|
218
|
+
});
|
|
219
|
+
|
|
220
|
+
it('should maintain immutability when subtracting zero', () => {
|
|
221
|
+
const original = new NumberValueObject(42);
|
|
222
|
+
const zero = new NumberValueObject(0);
|
|
223
|
+
const originalValue = original.valueOf();
|
|
224
|
+
|
|
225
|
+
const result = original.subtract(zero);
|
|
226
|
+
|
|
227
|
+
// Original should remain unchanged
|
|
228
|
+
expect(original.valueOf()).toBe(originalValue);
|
|
229
|
+
expect(original.valueOf()).toBe(42);
|
|
230
|
+
expect(zero.valueOf()).toBe(0);
|
|
231
|
+
|
|
232
|
+
// Result should be correct and a new instance
|
|
233
|
+
expect(result.valueOf()).toBe(42);
|
|
234
|
+
expect(result).not.toBe(original);
|
|
235
|
+
});
|
|
236
|
+
});
|
|
237
|
+
|
|
238
|
+
describe('multiply', () => {
|
|
239
|
+
it('should return a new NumberValueObject with the product of the two values', () => {
|
|
240
|
+
const value = new NumberValueObject(1);
|
|
241
|
+
const other = new NumberValueObject(2);
|
|
242
|
+
const result = value.multiply(other);
|
|
243
|
+
expect(result.valueOf()).toEqual(2);
|
|
244
|
+
});
|
|
245
|
+
|
|
246
|
+
it('should not mutate original objects when multiplying', () => {
|
|
247
|
+
const original = new NumberValueObject(7);
|
|
248
|
+
const other = new NumberValueObject(6);
|
|
249
|
+
const originalValue = original.valueOf();
|
|
250
|
+
const otherValue = other.valueOf();
|
|
251
|
+
|
|
252
|
+
const result = original.multiply(other);
|
|
253
|
+
|
|
254
|
+
// Original objects should remain unchanged
|
|
255
|
+
expect(original.valueOf()).toBe(originalValue);
|
|
256
|
+
expect(original.valueOf()).toBe(7);
|
|
257
|
+
expect(other.valueOf()).toBe(otherValue);
|
|
258
|
+
expect(other.valueOf()).toBe(6);
|
|
259
|
+
|
|
260
|
+
// Result should be a new instance
|
|
261
|
+
expect(result.valueOf()).toBe(42);
|
|
262
|
+
expect(result).not.toBe(original);
|
|
263
|
+
expect(result).not.toBe(other);
|
|
264
|
+
});
|
|
265
|
+
|
|
266
|
+
it('should work with primitive numbers and maintain immutability', () => {
|
|
267
|
+
const original = new NumberValueObject(15);
|
|
268
|
+
const originalValue = original.valueOf();
|
|
269
|
+
|
|
270
|
+
const result = original.multiply(2);
|
|
271
|
+
|
|
272
|
+
// Original should remain unchanged
|
|
273
|
+
expect(original.valueOf()).toBe(originalValue);
|
|
274
|
+
expect(original.valueOf()).toBe(15);
|
|
275
|
+
|
|
276
|
+
// Result should be correct and a new instance
|
|
277
|
+
expect(result.valueOf()).toBe(30);
|
|
278
|
+
expect(result).not.toBe(original);
|
|
279
|
+
});
|
|
280
|
+
|
|
281
|
+
it('should maintain immutability when multiplying by zero', () => {
|
|
282
|
+
const original = new NumberValueObject(42);
|
|
283
|
+
const zero = new NumberValueObject(0);
|
|
284
|
+
const originalValue = original.valueOf();
|
|
285
|
+
|
|
286
|
+
const result = original.multiply(zero);
|
|
287
|
+
|
|
288
|
+
// Original should remain unchanged
|
|
289
|
+
expect(original.valueOf()).toBe(originalValue);
|
|
290
|
+
expect(original.valueOf()).toBe(42);
|
|
291
|
+
expect(zero.valueOf()).toBe(0);
|
|
292
|
+
|
|
293
|
+
// Result should be correct and a new instance
|
|
294
|
+
expect(result.valueOf()).toBe(0);
|
|
295
|
+
expect(result).not.toBe(original);
|
|
296
|
+
});
|
|
297
|
+
});
|
|
298
|
+
|
|
299
|
+
describe('divide', () => {
|
|
300
|
+
it('should return a new NumberValueObject with the quotient of the two values', () => {
|
|
301
|
+
const value = new NumberValueObject(1);
|
|
302
|
+
const other = new NumberValueObject(2);
|
|
303
|
+
const result = value.divide(other);
|
|
304
|
+
expect(result.valueOf()).toEqual(0.5);
|
|
305
|
+
});
|
|
306
|
+
|
|
307
|
+
it('should not mutate original objects when dividing', () => {
|
|
308
|
+
const original = new NumberValueObject(20);
|
|
309
|
+
const other = new NumberValueObject(4);
|
|
310
|
+
const originalValue = original.valueOf();
|
|
311
|
+
const otherValue = other.valueOf();
|
|
312
|
+
|
|
313
|
+
const result = original.divide(other);
|
|
314
|
+
|
|
315
|
+
// Original objects should remain unchanged
|
|
316
|
+
expect(original.valueOf()).toBe(originalValue);
|
|
317
|
+
expect(original.valueOf()).toBe(20);
|
|
318
|
+
expect(other.valueOf()).toBe(otherValue);
|
|
319
|
+
expect(other.valueOf()).toBe(4);
|
|
320
|
+
|
|
321
|
+
// Result should be a new instance
|
|
322
|
+
expect(result.valueOf()).toBe(5);
|
|
323
|
+
expect(result).not.toBe(original);
|
|
324
|
+
expect(result).not.toBe(other);
|
|
325
|
+
});
|
|
326
|
+
|
|
327
|
+
it('should work with primitive numbers and maintain immutability', () => {
|
|
328
|
+
const original = new NumberValueObject(15);
|
|
329
|
+
const originalValue = original.valueOf();
|
|
330
|
+
|
|
331
|
+
const result = original.divide(3);
|
|
332
|
+
|
|
333
|
+
// Original should remain unchanged
|
|
334
|
+
expect(original.valueOf()).toBe(originalValue);
|
|
335
|
+
expect(original.valueOf()).toBe(15);
|
|
336
|
+
|
|
337
|
+
// Result should be correct and a new instance
|
|
338
|
+
expect(result.valueOf()).toBe(5);
|
|
339
|
+
expect(result).not.toBe(original);
|
|
340
|
+
});
|
|
341
|
+
});
|
|
342
|
+
|
|
343
|
+
describe('inheritance and ValueObject behavior', () => {
|
|
344
|
+
it('should inherit from ValueObject', () => {
|
|
345
|
+
const numberValueObject = new NumberValueObject(42);
|
|
346
|
+
expect(numberValueObject).toBeInstanceOf(NumberValueObject);
|
|
347
|
+
expect(numberValueObject.valueOf).toBeDefined();
|
|
348
|
+
expect(numberValueObject.isEqual).toBeDefined();
|
|
349
|
+
expect(numberValueObject.toString).toBeDefined();
|
|
350
|
+
});
|
|
351
|
+
|
|
352
|
+
it('should implement valueOf() method correctly', () => {
|
|
353
|
+
const value = 123.45;
|
|
354
|
+
const numberValueObject = new NumberValueObject(value);
|
|
355
|
+
expect(numberValueObject.valueOf()).toBe(value);
|
|
356
|
+
});
|
|
357
|
+
|
|
358
|
+
it('should implement toString() method correctly from ValueObject', () => {
|
|
359
|
+
const value = 987.654;
|
|
360
|
+
const numberValueObject = new NumberValueObject(value);
|
|
361
|
+
expect(numberValueObject.toString()).toBe(value.toString());
|
|
362
|
+
expect(numberValueObject.toString()).toBe('987.654');
|
|
363
|
+
});
|
|
364
|
+
|
|
365
|
+
it('should implement isEqual() method correctly', () => {
|
|
366
|
+
const value = 100;
|
|
367
|
+
const numberValueObject1 = new NumberValueObject(value);
|
|
368
|
+
const numberValueObject2 = new NumberValueObject(value);
|
|
369
|
+
const numberValueObject3 = new NumberValueObject(200);
|
|
370
|
+
|
|
371
|
+
expect(numberValueObject1.isEqual(numberValueObject2)).toBeTrue();
|
|
372
|
+
expect(numberValueObject1.isEqual(numberValueObject3)).toBeFalse();
|
|
373
|
+
expect(numberValueObject1.isEqual(value)).toBeTrue();
|
|
374
|
+
expect(numberValueObject1.isEqual(200)).toBeFalse();
|
|
375
|
+
});
|
|
376
|
+
|
|
377
|
+
it('should compare with primitive values using isEqual', () => {
|
|
378
|
+
const numberValueObject = new NumberValueObject(42);
|
|
379
|
+
expect(numberValueObject.isEqual(42)).toBeTrue();
|
|
380
|
+
expect(numberValueObject.isEqual(43)).toBeFalse();
|
|
381
|
+
});
|
|
382
|
+
|
|
383
|
+
it('should implement clone() method correctly', () => {
|
|
384
|
+
const originalValue = 3.14159;
|
|
385
|
+
const original = new NumberValueObject(originalValue);
|
|
386
|
+
const cloned = (original as any).clone();
|
|
387
|
+
|
|
388
|
+
expect(cloned).toBeInstanceOf(NumberValueObject);
|
|
389
|
+
expect(cloned.valueOf()).toBe(originalValue);
|
|
390
|
+
expect(cloned.toString()).toBe(originalValue.toString());
|
|
391
|
+
expect(cloned.isEqual(original)).toBeTrue();
|
|
392
|
+
expect(cloned).not.toBe(original); // Different instances
|
|
393
|
+
});
|
|
394
|
+
|
|
395
|
+
it('should accept another NumberValueObject in constructor', () => {
|
|
396
|
+
const original = new NumberValueObject(555);
|
|
397
|
+
const copy = new NumberValueObject(original);
|
|
398
|
+
expect(copy.valueOf()).toBe(555);
|
|
399
|
+
expect(copy.isEqual(original)).toBeTrue();
|
|
400
|
+
});
|
|
401
|
+
|
|
402
|
+
it('should validate number when constructed from another NumberValueObject', () => {
|
|
403
|
+
const validNumberValueObject = new NumberValueObject(123);
|
|
404
|
+
expect(() => new NumberValueObject(validNumberValueObject)).not.toThrow();
|
|
405
|
+
|
|
406
|
+
// Create an invalid NumberValueObject by bypassing validation (for testing)
|
|
407
|
+
const invalidValue = NaN;
|
|
408
|
+
expect(() => new NumberValueObject(invalidValue)).toThrow(
|
|
409
|
+
InvalidNumberError,
|
|
410
|
+
);
|
|
411
|
+
});
|
|
412
|
+
|
|
413
|
+
it('should maintain immutability with chained operations', () => {
|
|
414
|
+
const original = new NumberValueObject(10);
|
|
415
|
+
const two = new NumberValueObject(2);
|
|
416
|
+
const three = new NumberValueObject(3);
|
|
417
|
+
|
|
418
|
+
const originalValue = original.valueOf();
|
|
419
|
+
const twoValue = two.valueOf();
|
|
420
|
+
const threeValue = three.valueOf();
|
|
421
|
+
|
|
422
|
+
// Chain operations: (10 + 2) * 3 / 2
|
|
423
|
+
const step1 = original.add(two);
|
|
424
|
+
const step2 = step1.multiply(three);
|
|
425
|
+
const final = step2.divide(two);
|
|
426
|
+
|
|
427
|
+
// All original objects should remain unchanged
|
|
428
|
+
expect(original.valueOf()).toBe(originalValue);
|
|
429
|
+
expect(original.valueOf()).toBe(10);
|
|
430
|
+
expect(two.valueOf()).toBe(twoValue);
|
|
431
|
+
expect(two.valueOf()).toBe(2);
|
|
432
|
+
expect(three.valueOf()).toBe(threeValue);
|
|
433
|
+
expect(three.valueOf()).toBe(3);
|
|
434
|
+
|
|
435
|
+
// Each step should create new instances
|
|
436
|
+
expect(step1.valueOf()).toBe(12);
|
|
437
|
+
expect(step2.valueOf()).toBe(36);
|
|
438
|
+
expect(final.valueOf()).toBe(18);
|
|
439
|
+
|
|
440
|
+
// All results should be different instances
|
|
441
|
+
expect(step1).not.toBe(original);
|
|
442
|
+
expect(step2).not.toBe(step1);
|
|
443
|
+
expect(final).not.toBe(step2);
|
|
444
|
+
});
|
|
445
|
+
});
|
|
446
|
+
});
|