@simplysm/core-common 13.0.100 → 14.0.4
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/README.md +86 -92
- package/dist/common.types.d.ts +14 -14
- package/dist/common.types.js +2 -1
- package/dist/common.types.js.map +1 -6
- package/dist/env.d.ts +8 -1
- package/dist/env.d.ts.map +1 -1
- package/dist/env.js +13 -9
- package/dist/env.js.map +1 -6
- package/dist/errors/argument-error.d.ts +10 -10
- package/dist/errors/argument-error.d.ts.map +1 -1
- package/dist/errors/argument-error.js +31 -14
- package/dist/errors/argument-error.js.map +1 -6
- package/dist/errors/not-implemented-error.d.ts +8 -8
- package/dist/errors/not-implemented-error.js +30 -12
- package/dist/errors/not-implemented-error.js.map +1 -6
- package/dist/errors/sd-error.d.ts +10 -10
- package/dist/errors/sd-error.d.ts.map +1 -1
- package/dist/errors/sd-error.js +45 -24
- package/dist/errors/sd-error.js.map +1 -6
- package/dist/errors/timeout-error.d.ts +10 -10
- package/dist/errors/timeout-error.js +34 -15
- package/dist/errors/timeout-error.js.map +1 -6
- package/dist/extensions/arr-ext.d.ts +2 -2
- package/dist/extensions/arr-ext.helpers.d.ts +10 -10
- package/dist/extensions/arr-ext.helpers.js +112 -89
- package/dist/extensions/arr-ext.helpers.js.map +1 -6
- package/dist/extensions/arr-ext.js +458 -422
- package/dist/extensions/arr-ext.js.map +1 -6
- package/dist/extensions/arr-ext.types.d.ts +57 -57
- package/dist/extensions/arr-ext.types.d.ts.map +1 -1
- package/dist/extensions/arr-ext.types.js +6 -1
- package/dist/extensions/arr-ext.types.js.map +1 -6
- package/dist/extensions/map-ext.d.ts +16 -16
- package/dist/extensions/map-ext.js +27 -22
- package/dist/extensions/map-ext.js.map +1 -6
- package/dist/extensions/set-ext.d.ts +11 -11
- package/dist/extensions/set-ext.js +32 -25
- package/dist/extensions/set-ext.js.map +1 -6
- package/dist/features/debounce-queue.d.ts +17 -17
- package/dist/features/debounce-queue.js +98 -70
- package/dist/features/debounce-queue.js.map +1 -6
- package/dist/features/event-emitter.d.ts +20 -20
- package/dist/features/event-emitter.js +101 -78
- package/dist/features/event-emitter.js.map +1 -6
- package/dist/features/serial-queue.d.ts +11 -11
- package/dist/features/serial-queue.js +78 -57
- package/dist/features/serial-queue.js.map +1 -6
- package/dist/globals.d.ts +4 -4
- package/dist/globals.js +9 -1
- package/dist/globals.js.map +1 -6
- package/dist/index.js +28 -27
- package/dist/index.js.map +1 -6
- package/dist/types/date-only.d.ts +64 -64
- package/dist/types/date-only.d.ts.map +1 -1
- package/dist/types/date-only.js +263 -252
- package/dist/types/date-only.js.map +1 -6
- package/dist/types/date-time.d.ts +36 -36
- package/dist/types/date-time.d.ts.map +1 -1
- package/dist/types/date-time.js +196 -288
- package/dist/types/date-time.js.map +1 -6
- package/dist/types/lazy-gc-map.d.ts +26 -26
- package/dist/types/lazy-gc-map.d.ts.map +1 -1
- package/dist/types/lazy-gc-map.js +202 -159
- package/dist/types/lazy-gc-map.js.map +1 -6
- package/dist/types/time.d.ts +23 -23
- package/dist/types/time.d.ts.map +1 -1
- package/dist/types/time.js +169 -158
- package/dist/types/time.js.map +1 -6
- package/dist/types/uuid.d.ts +11 -11
- package/dist/types/uuid.d.ts.map +1 -1
- package/dist/types/uuid.js +95 -70
- package/dist/types/uuid.js.map +1 -6
- package/dist/utils/bytes.d.ts +17 -17
- package/dist/utils/bytes.js +137 -81
- package/dist/utils/bytes.js.map +1 -6
- package/dist/utils/date-format.d.ts +40 -40
- package/dist/utils/date-format.js +187 -101
- package/dist/utils/date-format.js.map +1 -6
- package/dist/utils/error.d.ts +4 -4
- package/dist/utils/error.js +11 -6
- package/dist/utils/error.js.map +1 -6
- package/dist/utils/json.d.ts +19 -19
- package/dist/utils/json.js +187 -135
- package/dist/utils/json.js.map +1 -6
- package/dist/utils/num.d.ts +20 -20
- package/dist/utils/num.js +76 -34
- package/dist/utils/num.js.map +1 -6
- package/dist/utils/obj.d.ts +111 -111
- package/dist/utils/obj.d.ts.map +1 -1
- package/dist/utils/obj.js +706 -496
- package/dist/utils/obj.js.map +1 -6
- package/dist/utils/path.d.ts +10 -10
- package/dist/utils/path.js +35 -18
- package/dist/utils/path.js.map +1 -6
- package/dist/utils/primitive.d.ts +5 -5
- package/dist/utils/primitive.js +34 -14
- package/dist/utils/primitive.js.map +1 -6
- package/dist/utils/str.d.ts +38 -38
- package/dist/utils/str.js +217 -113
- package/dist/utils/str.js.map +1 -6
- package/dist/utils/template-strings.d.ts +26 -26
- package/dist/utils/template-strings.js +113 -40
- package/dist/utils/template-strings.js.map +1 -6
- package/dist/utils/transferable.d.ts +18 -18
- package/dist/utils/transferable.js +218 -151
- package/dist/utils/transferable.js.map +1 -6
- package/dist/utils/wait.d.ts +9 -9
- package/dist/utils/wait.js +30 -15
- package/dist/utils/wait.js.map +1 -6
- package/dist/utils/xml.d.ts +13 -13
- package/dist/utils/xml.js +84 -46
- package/dist/utils/xml.js.map +1 -6
- package/dist/utils/zip.d.ts +22 -22
- package/dist/utils/zip.js +172 -148
- package/dist/utils/zip.js.map +1 -6
- package/docs/array-extensions.md +430 -0
- package/docs/env.md +52 -0
- package/docs/errors.md +41 -56
- package/docs/features.md +82 -97
- package/docs/type-utilities.md +91 -0
- package/docs/types.md +221 -201
- package/docs/utils.md +319 -435
- package/package.json +7 -5
- package/src/common.types.ts +14 -14
- package/src/env.ts +12 -3
- package/src/errors/argument-error.ts +15 -15
- package/src/errors/not-implemented-error.ts +9 -9
- package/src/errors/sd-error.ts +12 -12
- package/src/errors/timeout-error.ts +12 -12
- package/src/extensions/arr-ext.helpers.ts +16 -16
- package/src/extensions/arr-ext.ts +35 -35
- package/src/extensions/arr-ext.types.ts +57 -57
- package/src/extensions/map-ext.ts +16 -16
- package/src/extensions/set-ext.ts +11 -11
- package/src/features/debounce-queue.ts +23 -23
- package/src/features/event-emitter.ts +25 -25
- package/src/features/serial-queue.ts +13 -13
- package/src/globals.ts +4 -4
- package/src/index.ts +5 -5
- package/src/types/date-only.ts +84 -83
- package/src/types/date-time.ts +43 -42
- package/src/types/lazy-gc-map.ts +44 -44
- package/src/types/time.ts +29 -29
- package/src/types/uuid.ts +15 -15
- package/src/utils/bytes.ts +35 -35
- package/src/utils/date-format.ts +59 -59
- package/src/utils/error.ts +4 -4
- package/src/utils/json.ts +41 -41
- package/src/utils/num.ts +20 -20
- package/src/utils/obj.ts +138 -138
- package/src/utils/path.ts +10 -10
- package/src/utils/primitive.ts +6 -6
- package/src/utils/str.ts +48 -48
- package/src/utils/template-strings.ts +29 -29
- package/src/utils/transferable.ts +38 -38
- package/src/utils/wait.ts +10 -10
- package/src/utils/xml.ts +19 -19
- package/src/utils/zip.ts +25 -25
- package/docs/extensions.md +0 -387
- package/tests/errors/errors.spec.ts +0 -80
- package/tests/extensions/array-extension.spec.ts +0 -654
- package/tests/extensions/map-extension.spec.ts +0 -117
- package/tests/extensions/set-extension.spec.ts +0 -67
- package/tests/types/date-only.spec.ts +0 -533
- package/tests/types/date-time.spec.ts +0 -246
- package/tests/types/lazy-gc-map.spec.ts +0 -606
- package/tests/types/time.spec.ts +0 -428
- package/tests/types/uuid.spec.ts +0 -74
- package/tests/utils/bytes-utils.spec.ts +0 -197
- package/tests/utils/date-format.spec.ts +0 -350
- package/tests/utils/debounce-queue.spec.ts +0 -226
- package/tests/utils/json.spec.ts +0 -400
- package/tests/utils/number.spec.ts +0 -136
- package/tests/utils/object.spec.ts +0 -810
- package/tests/utils/path.spec.ts +0 -70
- package/tests/utils/primitive.spec.ts +0 -43
- package/tests/utils/sd-event-emitter.spec.ts +0 -189
- package/tests/utils/serial-queue.spec.ts +0 -305
- package/tests/utils/string.spec.ts +0 -265
- package/tests/utils/template-strings.spec.ts +0 -48
- package/tests/utils/transferable.spec.ts +0 -639
- package/tests/utils/wait.spec.ts +0 -123
- package/tests/utils/xml.spec.ts +0 -146
- package/tests/utils/zip.spec.ts +0 -221
package/tests/types/time.spec.ts
DELETED
|
@@ -1,428 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect } from "vitest";
|
|
2
|
-
import { Time } from "@simplysm/core-common";
|
|
3
|
-
|
|
4
|
-
describe("Time", () => {
|
|
5
|
-
//#region Constructor
|
|
6
|
-
|
|
7
|
-
describe("constructor", () => {
|
|
8
|
-
it("Returns current time when created without arguments", () => {
|
|
9
|
-
const time = new Time();
|
|
10
|
-
|
|
11
|
-
// Time changes in real-time so range test
|
|
12
|
-
expect(time.hour).toBeGreaterThanOrEqual(0);
|
|
13
|
-
expect(time.hour).toBeLessThanOrEqual(23);
|
|
14
|
-
expect(time.minute).toBeGreaterThanOrEqual(0);
|
|
15
|
-
expect(time.minute).toBeLessThanOrEqual(59);
|
|
16
|
-
});
|
|
17
|
-
|
|
18
|
-
it("Creates with hour, minute, second", () => {
|
|
19
|
-
const time = new Time(15, 30, 45);
|
|
20
|
-
|
|
21
|
-
expect(time.hour).toBe(15);
|
|
22
|
-
expect(time.minute).toBe(30);
|
|
23
|
-
expect(time.second).toBe(45);
|
|
24
|
-
expect(time.millisecond).toBe(0);
|
|
25
|
-
});
|
|
26
|
-
|
|
27
|
-
it("Creates with hour, minute, second, millisecond", () => {
|
|
28
|
-
const time = new Time(15, 30, 45, 123);
|
|
29
|
-
|
|
30
|
-
expect(time.hour).toBe(15);
|
|
31
|
-
expect(time.minute).toBe(30);
|
|
32
|
-
expect(time.second).toBe(45);
|
|
33
|
-
expect(time.millisecond).toBe(123);
|
|
34
|
-
});
|
|
35
|
-
|
|
36
|
-
it("Creates with tick (millisecond)", () => {
|
|
37
|
-
// 15:30:45.123 = (15*60*60 + 30*60 + 45)*1000 + 123
|
|
38
|
-
const tick = (15 * 60 * 60 + 30 * 60 + 45) * 1000 + 123;
|
|
39
|
-
const time = new Time(tick);
|
|
40
|
-
|
|
41
|
-
expect(time.hour).toBe(15);
|
|
42
|
-
expect(time.minute).toBe(30);
|
|
43
|
-
expect(time.second).toBe(45);
|
|
44
|
-
expect(time.millisecond).toBe(123);
|
|
45
|
-
});
|
|
46
|
-
|
|
47
|
-
it("Creates with Date type", () => {
|
|
48
|
-
const date = new Date(2025, 0, 6, 15, 30, 45, 123);
|
|
49
|
-
const time = new Time(date);
|
|
50
|
-
|
|
51
|
-
expect(time.hour).toBe(15);
|
|
52
|
-
expect(time.minute).toBe(30);
|
|
53
|
-
expect(time.second).toBe(45);
|
|
54
|
-
expect(time.millisecond).toBe(123);
|
|
55
|
-
});
|
|
56
|
-
|
|
57
|
-
it("Normalizes to 24 hours if exceeds", () => {
|
|
58
|
-
// 25 hours = 1 hour
|
|
59
|
-
const time = new Time(25, 0, 0);
|
|
60
|
-
|
|
61
|
-
expect(time.hour).toBe(1);
|
|
62
|
-
});
|
|
63
|
-
|
|
64
|
-
it("Normalizes negative hours/minutes/seconds to within 24 hours", () => {
|
|
65
|
-
// -1 hour 30 minutes = 23 hours 30 minutes (24 - 0.5 = 23.5)
|
|
66
|
-
const time = new Time(-1, 30, 0);
|
|
67
|
-
|
|
68
|
-
expect(time.hour).toBe(23);
|
|
69
|
-
expect(time.minute).toBe(30);
|
|
70
|
-
});
|
|
71
|
-
|
|
72
|
-
it("Normalizes negative tick to within 24 hours", () => {
|
|
73
|
-
// -1 hour = -3600000ms → 23 hours
|
|
74
|
-
const time = new Time(-3600000);
|
|
75
|
-
|
|
76
|
-
expect(time.hour).toBe(23);
|
|
77
|
-
expect(time.minute).toBe(0);
|
|
78
|
-
expect(time.second).toBe(0);
|
|
79
|
-
});
|
|
80
|
-
|
|
81
|
-
it("Negative tick (-1ms) normalizes to 23:59:59.999", () => {
|
|
82
|
-
const time = new Time(-1);
|
|
83
|
-
|
|
84
|
-
expect(time.hour).toBe(23);
|
|
85
|
-
expect(time.minute).toBe(59);
|
|
86
|
-
expect(time.second).toBe(59);
|
|
87
|
-
expect(time.millisecond).toBe(999);
|
|
88
|
-
});
|
|
89
|
-
});
|
|
90
|
-
|
|
91
|
-
//#endregion
|
|
92
|
-
|
|
93
|
-
//#region parse
|
|
94
|
-
|
|
95
|
-
describe("parse()", () => {
|
|
96
|
-
it("Parses HH:mm:ss format", () => {
|
|
97
|
-
const time = Time.parse("15:30:45");
|
|
98
|
-
|
|
99
|
-
expect(time.hour).toBe(15);
|
|
100
|
-
expect(time.minute).toBe(30);
|
|
101
|
-
expect(time.second).toBe(45);
|
|
102
|
-
expect(time.millisecond).toBe(0);
|
|
103
|
-
});
|
|
104
|
-
|
|
105
|
-
it("Parses HH:mm:ss.fff format", () => {
|
|
106
|
-
const time = Time.parse("15:30:45.123");
|
|
107
|
-
|
|
108
|
-
expect(time.hour).toBe(15);
|
|
109
|
-
expect(time.minute).toBe(30);
|
|
110
|
-
expect(time.second).toBe(45);
|
|
111
|
-
expect(time.millisecond).toBe(123);
|
|
112
|
-
});
|
|
113
|
-
|
|
114
|
-
it("Parses AM HH:mm:ss format", () => {
|
|
115
|
-
const time = Time.parse("AM 9:30:45");
|
|
116
|
-
|
|
117
|
-
expect(time.hour).toBe(9);
|
|
118
|
-
expect(time.minute).toBe(30);
|
|
119
|
-
expect(time.second).toBe(45);
|
|
120
|
-
});
|
|
121
|
-
|
|
122
|
-
it("Parses PM HH:mm:ss format", () => {
|
|
123
|
-
const time = Time.parse("PM 3:30:45");
|
|
124
|
-
|
|
125
|
-
expect(time.hour).toBe(15); // 12 + 3
|
|
126
|
-
expect(time.minute).toBe(30);
|
|
127
|
-
expect(time.second).toBe(45);
|
|
128
|
-
});
|
|
129
|
-
|
|
130
|
-
it("Pads milliseconds with 0 if insufficient digits", () => {
|
|
131
|
-
const time = Time.parse("15:30:45.1");
|
|
132
|
-
|
|
133
|
-
expect(time.millisecond).toBe(100); // '1' → '100'
|
|
134
|
-
});
|
|
135
|
-
|
|
136
|
-
it("Throws error for invalid format", () => {
|
|
137
|
-
expect(() => Time.parse("invalid-time")).toThrow();
|
|
138
|
-
});
|
|
139
|
-
|
|
140
|
-
it("PM 12:00:00 is noon (12 o'clock)", () => {
|
|
141
|
-
const time = Time.parse("PM 12:00:00");
|
|
142
|
-
|
|
143
|
-
expect(time.hour).toBe(12);
|
|
144
|
-
expect(time.minute).toBe(0);
|
|
145
|
-
expect(time.second).toBe(0);
|
|
146
|
-
});
|
|
147
|
-
|
|
148
|
-
it("AM 12:00:00 is midnight (0 o'clock)", () => {
|
|
149
|
-
const time = Time.parse("AM 12:00:00");
|
|
150
|
-
|
|
151
|
-
expect(time.hour).toBe(0);
|
|
152
|
-
expect(time.minute).toBe(0);
|
|
153
|
-
expect(time.second).toBe(0);
|
|
154
|
-
});
|
|
155
|
-
|
|
156
|
-
it("PM 12:30:45 is after noon (12:30:45)", () => {
|
|
157
|
-
const time = Time.parse("PM 12:30:45");
|
|
158
|
-
|
|
159
|
-
expect(time.hour).toBe(12);
|
|
160
|
-
expect(time.minute).toBe(30);
|
|
161
|
-
expect(time.second).toBe(45);
|
|
162
|
-
});
|
|
163
|
-
|
|
164
|
-
it("AM 12:30:45 is after midnight (0:30:45)", () => {
|
|
165
|
-
const time = Time.parse("AM 12:30:45");
|
|
166
|
-
|
|
167
|
-
expect(time.hour).toBe(0);
|
|
168
|
-
expect(time.minute).toBe(30);
|
|
169
|
-
expect(time.second).toBe(45);
|
|
170
|
-
});
|
|
171
|
-
|
|
172
|
-
it("Parses time from ISO 8601 format (UTC -> local conversion)", () => {
|
|
173
|
-
// UTC time is converted to local time
|
|
174
|
-
const time = Time.parse("2025-01-15T10:30:45Z");
|
|
175
|
-
const expected = new Date("2025-01-15T10:30:45Z");
|
|
176
|
-
|
|
177
|
-
expect(time.hour).toBe(expected.getHours());
|
|
178
|
-
expect(time.minute).toBe(30);
|
|
179
|
-
expect(time.second).toBe(45);
|
|
180
|
-
});
|
|
181
|
-
|
|
182
|
-
it("Parses milliseconds from ISO 8601 format (UTC -> local conversion)", () => {
|
|
183
|
-
// UTC time is converted to local time
|
|
184
|
-
const time = Time.parse("2025-01-15T10:30:45.123Z");
|
|
185
|
-
const expected = new Date("2025-01-15T10:30:45.123Z");
|
|
186
|
-
|
|
187
|
-
expect(time.hour).toBe(expected.getHours());
|
|
188
|
-
expect(time.minute).toBe(30);
|
|
189
|
-
expect(time.second).toBe(45);
|
|
190
|
-
expect(time.millisecond).toBe(123);
|
|
191
|
-
});
|
|
192
|
-
});
|
|
193
|
-
|
|
194
|
-
//#endregion
|
|
195
|
-
|
|
196
|
-
//#region setX methods (immutable)
|
|
197
|
-
|
|
198
|
-
describe("setMillisecond()", () => {
|
|
199
|
-
it("Returns new instance with millisecond changed", () => {
|
|
200
|
-
const time = new Time(15, 30, 45, 123);
|
|
201
|
-
const newTime = time.setMillisecond(456);
|
|
202
|
-
|
|
203
|
-
expect(newTime.hour).toBe(15);
|
|
204
|
-
expect(newTime.minute).toBe(30);
|
|
205
|
-
expect(newTime.second).toBe(45);
|
|
206
|
-
expect(newTime.millisecond).toBe(456);
|
|
207
|
-
expect(time.millisecond).toBe(123); // original immutable
|
|
208
|
-
});
|
|
209
|
-
});
|
|
210
|
-
|
|
211
|
-
//#endregion
|
|
212
|
-
|
|
213
|
-
//#region addX methods (immutable)
|
|
214
|
-
|
|
215
|
-
describe("addHours()", () => {
|
|
216
|
-
it("Adds positive hours", () => {
|
|
217
|
-
const time = new Time(15, 30, 45);
|
|
218
|
-
const newTime = time.addHours(3);
|
|
219
|
-
|
|
220
|
-
expect(newTime.hour).toBe(18);
|
|
221
|
-
expect(newTime.minute).toBe(30);
|
|
222
|
-
expect(newTime.second).toBe(45);
|
|
223
|
-
});
|
|
224
|
-
|
|
225
|
-
it("Adds negative hours (subtraction)", () => {
|
|
226
|
-
const time = new Time(15, 30, 45);
|
|
227
|
-
const newTime = time.addHours(-5);
|
|
228
|
-
|
|
229
|
-
expect(newTime.hour).toBe(10);
|
|
230
|
-
});
|
|
231
|
-
|
|
232
|
-
it("Keeps remainder if exceeds 24 hours", () => {
|
|
233
|
-
const time = new Time(22, 0, 0);
|
|
234
|
-
const newTime = time.addHours(5);
|
|
235
|
-
|
|
236
|
-
expect(newTime.hour).toBe(3); // (22 + 5) % 24
|
|
237
|
-
});
|
|
238
|
-
});
|
|
239
|
-
|
|
240
|
-
describe("addMinutes()", () => {
|
|
241
|
-
it("Adds positive minutes", () => {
|
|
242
|
-
const time = new Time(15, 30, 45);
|
|
243
|
-
const newTime = time.addMinutes(20);
|
|
244
|
-
|
|
245
|
-
expect(newTime.hour).toBe(15);
|
|
246
|
-
expect(newTime.minute).toBe(50);
|
|
247
|
-
});
|
|
248
|
-
|
|
249
|
-
it("Adds negative minutes (subtraction)", () => {
|
|
250
|
-
const time = new Time(15, 30, 45);
|
|
251
|
-
const newTime = time.addMinutes(-20);
|
|
252
|
-
|
|
253
|
-
expect(newTime.minute).toBe(10);
|
|
254
|
-
});
|
|
255
|
-
|
|
256
|
-
it("Increases hour if exceeds 60 minutes", () => {
|
|
257
|
-
const time = new Time(15, 50, 0);
|
|
258
|
-
const newTime = time.addMinutes(20);
|
|
259
|
-
|
|
260
|
-
expect(newTime.hour).toBe(16);
|
|
261
|
-
expect(newTime.minute).toBe(10);
|
|
262
|
-
});
|
|
263
|
-
});
|
|
264
|
-
|
|
265
|
-
describe("addSeconds()", () => {
|
|
266
|
-
it("Adds positive seconds", () => {
|
|
267
|
-
const time = new Time(15, 30, 45);
|
|
268
|
-
const newTime = time.addSeconds(10);
|
|
269
|
-
|
|
270
|
-
expect(newTime.hour).toBe(15);
|
|
271
|
-
expect(newTime.minute).toBe(30);
|
|
272
|
-
expect(newTime.second).toBe(55);
|
|
273
|
-
});
|
|
274
|
-
|
|
275
|
-
it("Adds negative seconds (subtraction)", () => {
|
|
276
|
-
const time = new Time(15, 30, 45);
|
|
277
|
-
const newTime = time.addSeconds(-10);
|
|
278
|
-
|
|
279
|
-
expect(newTime.second).toBe(35);
|
|
280
|
-
});
|
|
281
|
-
|
|
282
|
-
it("Increases minute if exceeds 60 seconds", () => {
|
|
283
|
-
const time = new Time(15, 30, 50);
|
|
284
|
-
const newTime = time.addSeconds(20);
|
|
285
|
-
|
|
286
|
-
expect(newTime.minute).toBe(31);
|
|
287
|
-
expect(newTime.second).toBe(10);
|
|
288
|
-
});
|
|
289
|
-
});
|
|
290
|
-
|
|
291
|
-
describe("addMilliseconds()", () => {
|
|
292
|
-
it("Adds positive milliseconds", () => {
|
|
293
|
-
const time = new Time(15, 30, 45, 100);
|
|
294
|
-
const newTime = time.addMilliseconds(50);
|
|
295
|
-
|
|
296
|
-
expect(newTime.millisecond).toBe(150);
|
|
297
|
-
});
|
|
298
|
-
|
|
299
|
-
it("Adds negative milliseconds (subtraction)", () => {
|
|
300
|
-
const time = new Time(15, 30, 45, 100);
|
|
301
|
-
const newTime = time.addMilliseconds(-50);
|
|
302
|
-
|
|
303
|
-
expect(newTime.millisecond).toBe(50);
|
|
304
|
-
});
|
|
305
|
-
|
|
306
|
-
it("Increases second if exceeds 1000 milliseconds", () => {
|
|
307
|
-
const time = new Time(15, 30, 45, 900);
|
|
308
|
-
const newTime = time.addMilliseconds(200);
|
|
309
|
-
|
|
310
|
-
expect(newTime.second).toBe(46);
|
|
311
|
-
expect(newTime.millisecond).toBe(100);
|
|
312
|
-
});
|
|
313
|
-
});
|
|
314
|
-
|
|
315
|
-
//#endregion
|
|
316
|
-
|
|
317
|
-
//#region Negative operations (24-hour boundary handling)
|
|
318
|
-
|
|
319
|
-
describe("Negative operations (24-hour boundary)", () => {
|
|
320
|
-
it("addHours(-25) is same time yesterday (23 hours ago)", () => {
|
|
321
|
-
// Subtracting 25 hours from 10:00 = previous day 9:00 = 24 - 25 + 10 = 9:00
|
|
322
|
-
const time = new Time(10, 0, 0);
|
|
323
|
-
const newTime = time.addHours(-25);
|
|
324
|
-
|
|
325
|
-
expect(newTime.hour).toBe(9);
|
|
326
|
-
expect(newTime.minute).toBe(0);
|
|
327
|
-
expect(newTime.second).toBe(0);
|
|
328
|
-
});
|
|
329
|
-
|
|
330
|
-
it("addHours(-10) crosses midnight to previous day", () => {
|
|
331
|
-
// Subtracting 10 hours from 5:00 = 19:00
|
|
332
|
-
const time = new Time(5, 0, 0);
|
|
333
|
-
const newTime = time.addHours(-10);
|
|
334
|
-
|
|
335
|
-
expect(newTime.hour).toBe(19);
|
|
336
|
-
});
|
|
337
|
-
|
|
338
|
-
it("addMinutes(-90) is 1 hour 30 minutes ago", () => {
|
|
339
|
-
// Subtracting 90 minutes from 1:30 = 0:00
|
|
340
|
-
const time = new Time(1, 30, 0);
|
|
341
|
-
const newTime = time.addMinutes(-90);
|
|
342
|
-
|
|
343
|
-
expect(newTime.hour).toBe(0);
|
|
344
|
-
expect(newTime.minute).toBe(0);
|
|
345
|
-
});
|
|
346
|
-
|
|
347
|
-
it("addMinutes(-90) crosses midnight to previous day", () => {
|
|
348
|
-
// Subtracting 90 minutes from 0:30 = previous day 23:00
|
|
349
|
-
const time = new Time(0, 30, 0);
|
|
350
|
-
const newTime = time.addMinutes(-90);
|
|
351
|
-
|
|
352
|
-
expect(newTime.hour).toBe(23);
|
|
353
|
-
expect(newTime.minute).toBe(0);
|
|
354
|
-
});
|
|
355
|
-
|
|
356
|
-
it("addSeconds(-3700) is about 1 hour ago", () => {
|
|
357
|
-
// Subtracting 3700 seconds (1 hour 1 minute 40 seconds) from 1:00:00 = 23:58:20
|
|
358
|
-
const time = new Time(1, 0, 0);
|
|
359
|
-
const newTime = time.addSeconds(-3700);
|
|
360
|
-
|
|
361
|
-
expect(newTime.hour).toBe(23);
|
|
362
|
-
expect(newTime.minute).toBe(58);
|
|
363
|
-
expect(newTime.second).toBe(20);
|
|
364
|
-
});
|
|
365
|
-
|
|
366
|
-
it("addMilliseconds(-1000) crosses midnight to previous day", () => {
|
|
367
|
-
// Subtracting 1000ms from 0:00:00.500ms = previous day 23:59:59.500ms
|
|
368
|
-
const time = new Time(0, 0, 0, 500);
|
|
369
|
-
const newTime = time.addMilliseconds(-1000);
|
|
370
|
-
|
|
371
|
-
expect(newTime.hour).toBe(23);
|
|
372
|
-
expect(newTime.minute).toBe(59);
|
|
373
|
-
expect(newTime.second).toBe(59);
|
|
374
|
-
expect(newTime.millisecond).toBe(500);
|
|
375
|
-
});
|
|
376
|
-
});
|
|
377
|
-
|
|
378
|
-
//#endregion
|
|
379
|
-
|
|
380
|
-
//#region isValid
|
|
381
|
-
|
|
382
|
-
describe("isValid", () => {
|
|
383
|
-
it("Time created with NaN tick has isValid false", () => {
|
|
384
|
-
const time = new Time(NaN);
|
|
385
|
-
expect(time.isValid).toBe(false);
|
|
386
|
-
});
|
|
387
|
-
});
|
|
388
|
-
|
|
389
|
-
//#endregion
|
|
390
|
-
|
|
391
|
-
//#region Formatting
|
|
392
|
-
|
|
393
|
-
describe("toFormatString()", () => {
|
|
394
|
-
it("Formats to HH:mm:ss format", () => {
|
|
395
|
-
const time = new Time(15, 30, 45);
|
|
396
|
-
expect(time.toFormatString("HH:mm:ss")).toBe("15:30:45");
|
|
397
|
-
});
|
|
398
|
-
|
|
399
|
-
it("Formats to HH:mm:ss.fff format", () => {
|
|
400
|
-
const time = new Time(15, 30, 45, 123);
|
|
401
|
-
expect(time.toFormatString("HH:mm:ss.fff")).toBe("15:30:45.123");
|
|
402
|
-
});
|
|
403
|
-
|
|
404
|
-
it("Formats to tt hh:mm:ss format (AM)", () => {
|
|
405
|
-
const time = new Time(9, 30, 45);
|
|
406
|
-
expect(time.toFormatString("tt hh:mm:ss")).toBe("AM 09:30:45");
|
|
407
|
-
});
|
|
408
|
-
|
|
409
|
-
it("Formats to tt hh:mm:ss format (PM)", () => {
|
|
410
|
-
const time = new Time(15, 30, 45);
|
|
411
|
-
expect(time.toFormatString("tt hh:mm:ss")).toBe("PM 03:30:45");
|
|
412
|
-
});
|
|
413
|
-
|
|
414
|
-
it("Formats to H:m:s format (no padding)", () => {
|
|
415
|
-
const time = new Time(9, 5, 3);
|
|
416
|
-
expect(time.toFormatString("H:m:s")).toBe("9:5:3");
|
|
417
|
-
});
|
|
418
|
-
});
|
|
419
|
-
|
|
420
|
-
describe("toString()", () => {
|
|
421
|
-
it("Returns default format HH:mm:ss.fff", () => {
|
|
422
|
-
const time = new Time(15, 30, 45, 123);
|
|
423
|
-
expect(time.toString()).toBe("15:30:45.123");
|
|
424
|
-
});
|
|
425
|
-
});
|
|
426
|
-
|
|
427
|
-
//#endregion
|
|
428
|
-
});
|
package/tests/types/uuid.spec.ts
DELETED
|
@@ -1,74 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect } from "vitest";
|
|
2
|
-
import { Uuid } from "@simplysm/core-common";
|
|
3
|
-
|
|
4
|
-
describe("Uuid", () => {
|
|
5
|
-
describe("generate()", () => {
|
|
6
|
-
it("Generates valid UUID v4 format", () => {
|
|
7
|
-
const uuid = Uuid.generate();
|
|
8
|
-
const str = uuid.toString();
|
|
9
|
-
|
|
10
|
-
// UUID v4 format: xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx
|
|
11
|
-
expect(str).toMatch(/^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/);
|
|
12
|
-
});
|
|
13
|
-
|
|
14
|
-
it("Generates new UUID each time", () => {
|
|
15
|
-
const uuid1 = Uuid.generate();
|
|
16
|
-
const uuid2 = Uuid.generate();
|
|
17
|
-
|
|
18
|
-
expect(uuid1.toString()).not.toBe(uuid2.toString());
|
|
19
|
-
});
|
|
20
|
-
});
|
|
21
|
-
|
|
22
|
-
describe("fromBytes()", () => {
|
|
23
|
-
it("Creates UUID from 16-byte Uint8Array", () => {
|
|
24
|
-
const bytes = new Uint8Array([
|
|
25
|
-
0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde,
|
|
26
|
-
0xf0,
|
|
27
|
-
]);
|
|
28
|
-
const uuid = Uuid.fromBytes(bytes);
|
|
29
|
-
|
|
30
|
-
expect(uuid.toString()).toBe("12345678-9abc-def0-1234-56789abcdef0");
|
|
31
|
-
});
|
|
32
|
-
|
|
33
|
-
it("Throws error for non-16-byte input", () => {
|
|
34
|
-
const bytes = new Uint8Array([0x12, 0x34]);
|
|
35
|
-
|
|
36
|
-
expect(() => Uuid.fromBytes(bytes)).toThrow("UUID byte size must be 16");
|
|
37
|
-
});
|
|
38
|
-
});
|
|
39
|
-
|
|
40
|
-
describe("toBytes()", () => {
|
|
41
|
-
it("Converts UUID to 16-byte Uint8Array", () => {
|
|
42
|
-
const uuid = new Uuid("12345678-9abc-def0-1234-56789abcdef0");
|
|
43
|
-
const bytes = uuid.toBytes();
|
|
44
|
-
|
|
45
|
-
expect(bytes).toBeInstanceOf(Uint8Array);
|
|
46
|
-
expect(bytes.length).toBe(16);
|
|
47
|
-
expect(Array.from(bytes)).toEqual([
|
|
48
|
-
0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde,
|
|
49
|
-
0xf0,
|
|
50
|
-
]);
|
|
51
|
-
});
|
|
52
|
-
|
|
53
|
-
it("fromBytes and toBytes are inverse operations", () => {
|
|
54
|
-
const originalBytes = new Uint8Array([
|
|
55
|
-
0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde,
|
|
56
|
-
0xf0,
|
|
57
|
-
]);
|
|
58
|
-
const uuid = Uuid.fromBytes(originalBytes);
|
|
59
|
-
const resultBytes = uuid.toBytes();
|
|
60
|
-
|
|
61
|
-
expect(Array.from(resultBytes)).toEqual(Array.from(originalBytes));
|
|
62
|
-
});
|
|
63
|
-
});
|
|
64
|
-
|
|
65
|
-
describe("constructor", () => {
|
|
66
|
-
it("Throws error for invalid UUID format", () => {
|
|
67
|
-
expect(() => new Uuid("invalid-uuid")).toThrow();
|
|
68
|
-
});
|
|
69
|
-
|
|
70
|
-
it("Throws error for mismatched UUID length", () => {
|
|
71
|
-
expect(() => new Uuid("12345678-9abc")).toThrow();
|
|
72
|
-
});
|
|
73
|
-
});
|
|
74
|
-
});
|
|
@@ -1,197 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect } from "vitest";
|
|
2
|
-
import { ArgumentError, bytes } from "@simplysm/core-common";
|
|
3
|
-
|
|
4
|
-
describe("BytesUtils", () => {
|
|
5
|
-
//#region concat
|
|
6
|
-
|
|
7
|
-
describe("bytes.concat()", () => {
|
|
8
|
-
it("Concatenates multiple Uint8Arrays", () => {
|
|
9
|
-
const arr1 = new Uint8Array([1, 2, 3]);
|
|
10
|
-
const arr2 = new Uint8Array([4, 5]);
|
|
11
|
-
const arr3 = new Uint8Array([6, 7, 8, 9]);
|
|
12
|
-
|
|
13
|
-
const result = bytes.concat([arr1, arr2, arr3]);
|
|
14
|
-
|
|
15
|
-
expect(result).toEqual(new Uint8Array([1, 2, 3, 4, 5, 6, 7, 8, 9]));
|
|
16
|
-
});
|
|
17
|
-
|
|
18
|
-
it("Handles empty array", () => {
|
|
19
|
-
const result = bytes.concat([]);
|
|
20
|
-
|
|
21
|
-
expect(result).toEqual(new Uint8Array([]));
|
|
22
|
-
expect(result.length).toBe(0);
|
|
23
|
-
});
|
|
24
|
-
|
|
25
|
-
it("Handles empty Uint8Array in array", () => {
|
|
26
|
-
const arr1 = new Uint8Array([1, 2]);
|
|
27
|
-
const arr2 = new Uint8Array([]);
|
|
28
|
-
const arr3 = new Uint8Array([3, 4]);
|
|
29
|
-
|
|
30
|
-
const result = bytes.concat([arr1, arr2, arr3]);
|
|
31
|
-
|
|
32
|
-
expect(result).toEqual(new Uint8Array([1, 2, 3, 4]));
|
|
33
|
-
});
|
|
34
|
-
});
|
|
35
|
-
|
|
36
|
-
//#endregion
|
|
37
|
-
|
|
38
|
-
//#region toHex/fromHex
|
|
39
|
-
|
|
40
|
-
describe("bytes.toHex()", () => {
|
|
41
|
-
it("Converts Uint8Array to hex string", () => {
|
|
42
|
-
const data = new Uint8Array([0, 1, 15, 16, 255]);
|
|
43
|
-
|
|
44
|
-
const result = bytes.toHex(data);
|
|
45
|
-
|
|
46
|
-
expect(result).toBe("00010f10ff");
|
|
47
|
-
});
|
|
48
|
-
|
|
49
|
-
it("Handles empty array", () => {
|
|
50
|
-
const result = bytes.toHex(new Uint8Array([]));
|
|
51
|
-
|
|
52
|
-
expect(result).toBe("");
|
|
53
|
-
});
|
|
54
|
-
|
|
55
|
-
it("Handles single byte", () => {
|
|
56
|
-
expect(bytes.toHex(new Uint8Array([0]))).toBe("00");
|
|
57
|
-
expect(bytes.toHex(new Uint8Array([255]))).toBe("ff");
|
|
58
|
-
});
|
|
59
|
-
});
|
|
60
|
-
|
|
61
|
-
describe("bytes.fromHex()", () => {
|
|
62
|
-
it("Converts hex string to Uint8Array", () => {
|
|
63
|
-
const result = bytes.fromHex("00010f10ff");
|
|
64
|
-
|
|
65
|
-
expect(result).toEqual(new Uint8Array([0, 1, 15, 16, 255]));
|
|
66
|
-
});
|
|
67
|
-
|
|
68
|
-
it("Handles empty string", () => {
|
|
69
|
-
const result = bytes.fromHex("");
|
|
70
|
-
|
|
71
|
-
expect(result).toEqual(new Uint8Array([]));
|
|
72
|
-
});
|
|
73
|
-
|
|
74
|
-
it("Handles uppercase hex", () => {
|
|
75
|
-
const result = bytes.fromHex("FF0A");
|
|
76
|
-
|
|
77
|
-
expect(result).toEqual(new Uint8Array([255, 10]));
|
|
78
|
-
});
|
|
79
|
-
|
|
80
|
-
it("Throws error for odd-length string", () => {
|
|
81
|
-
expect(() => bytes.fromHex("abc")).toThrow(ArgumentError);
|
|
82
|
-
expect(() => bytes.fromHex("a")).toThrow(ArgumentError);
|
|
83
|
-
expect(() => bytes.fromHex("12345")).toThrow(ArgumentError);
|
|
84
|
-
});
|
|
85
|
-
|
|
86
|
-
it("Throws error for invalid hex characters", () => {
|
|
87
|
-
expect(() => bytes.fromHex("zz")).toThrow(ArgumentError);
|
|
88
|
-
expect(() => bytes.fromHex("gh")).toThrow(ArgumentError);
|
|
89
|
-
expect(() => bytes.fromHex("12g4")).toThrow(ArgumentError);
|
|
90
|
-
});
|
|
91
|
-
});
|
|
92
|
-
|
|
93
|
-
describe("toHex/fromHex round-trip conversion", () => {
|
|
94
|
-
it("Round-trip conversion matches all byte values (0-255)", () => {
|
|
95
|
-
const original = new Uint8Array(256);
|
|
96
|
-
for (let i = 0; i < 256; i++) {
|
|
97
|
-
original[i] = i;
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
const hex = bytes.toHex(original);
|
|
101
|
-
const restored = bytes.fromHex(hex);
|
|
102
|
-
|
|
103
|
-
expect(restored).toEqual(original);
|
|
104
|
-
});
|
|
105
|
-
});
|
|
106
|
-
|
|
107
|
-
//#endregion
|
|
108
|
-
|
|
109
|
-
//#region toBase64/fromBase64
|
|
110
|
-
|
|
111
|
-
describe("bytes.toBase64()", () => {
|
|
112
|
-
it("Handles empty array", () => {
|
|
113
|
-
expect(bytes.toBase64(new Uint8Array([]))).toBe("");
|
|
114
|
-
});
|
|
115
|
-
|
|
116
|
-
it("Converts general data", () => {
|
|
117
|
-
expect(bytes.toBase64(new Uint8Array([72, 101, 108, 108, 111]))).toBe("SGVsbG8=");
|
|
118
|
-
});
|
|
119
|
-
|
|
120
|
-
it("Handles large data (1MB) without stack overflow", () => {
|
|
121
|
-
const data = new Uint8Array(1024 * 1024);
|
|
122
|
-
expect(() => bytes.toBase64(data)).not.toThrow();
|
|
123
|
-
});
|
|
124
|
-
|
|
125
|
-
it("Handles case with no padding needed", () => {
|
|
126
|
-
// Multiple of 3 length - no padding
|
|
127
|
-
expect(bytes.toBase64(new Uint8Array([1, 2, 3]))).toBe("AQID");
|
|
128
|
-
});
|
|
129
|
-
|
|
130
|
-
it("Handles case with single padding needed", () => {
|
|
131
|
-
// Remainder 2 when divided by 3 - 1 padding
|
|
132
|
-
expect(bytes.toBase64(new Uint8Array([1, 2]))).toBe("AQI=");
|
|
133
|
-
});
|
|
134
|
-
|
|
135
|
-
it("Handles case with double padding needed", () => {
|
|
136
|
-
// Remainder 1 when divided by 3 - 2 padding
|
|
137
|
-
expect(bytes.toBase64(new Uint8Array([1]))).toBe("AQ==");
|
|
138
|
-
});
|
|
139
|
-
});
|
|
140
|
-
|
|
141
|
-
describe("bytes.fromBase64()", () => {
|
|
142
|
-
it("Handles empty string", () => {
|
|
143
|
-
expect(bytes.fromBase64("")).toEqual(new Uint8Array([]));
|
|
144
|
-
});
|
|
145
|
-
|
|
146
|
-
it("Converts general data", () => {
|
|
147
|
-
expect(bytes.fromBase64("SGVsbG8=")).toEqual(new Uint8Array([72, 101, 108, 108, 111]));
|
|
148
|
-
});
|
|
149
|
-
|
|
150
|
-
it("Throws error for invalid base64 characters", () => {
|
|
151
|
-
expect(() => bytes.fromBase64("!!invalid!!")).toThrow(ArgumentError);
|
|
152
|
-
});
|
|
153
|
-
|
|
154
|
-
it("Throws error for invalid base64 length (remainder 1)", () => {
|
|
155
|
-
expect(() => bytes.fromBase64("A")).toThrow(ArgumentError);
|
|
156
|
-
expect(() => bytes.fromBase64("AAAAA")).toThrow(ArgumentError);
|
|
157
|
-
});
|
|
158
|
-
|
|
159
|
-
it("Handles base64 without padding", () => {
|
|
160
|
-
expect(bytes.fromBase64("AQID")).toEqual(new Uint8Array([1, 2, 3]));
|
|
161
|
-
});
|
|
162
|
-
|
|
163
|
-
it("Handles base64 with whitespace", () => {
|
|
164
|
-
expect(bytes.fromBase64("SGVs bG8=")).toEqual(new Uint8Array([72, 101, 108, 108, 111]));
|
|
165
|
-
});
|
|
166
|
-
});
|
|
167
|
-
|
|
168
|
-
describe("toBase64/fromBase64 round-trip conversion", () => {
|
|
169
|
-
it("Round-trip conversion matches all byte values (0-255)", () => {
|
|
170
|
-
const original = new Uint8Array(256);
|
|
171
|
-
for (let i = 0; i < 256; i++) {
|
|
172
|
-
original[i] = i;
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
const base64 = bytes.toBase64(original);
|
|
176
|
-
const restored = bytes.fromBase64(base64);
|
|
177
|
-
|
|
178
|
-
expect(restored).toEqual(original);
|
|
179
|
-
});
|
|
180
|
-
|
|
181
|
-
it("Round-trip conversion matches various lengths (1-10 bytes)", () => {
|
|
182
|
-
for (let len = 1; len <= 10; len++) {
|
|
183
|
-
const original = new Uint8Array(len);
|
|
184
|
-
for (let i = 0; i < len; i++) {
|
|
185
|
-
original[i] = (i * 37 + 13) % 256;
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
const base64 = bytes.toBase64(original);
|
|
189
|
-
const restored = bytes.fromBase64(base64);
|
|
190
|
-
|
|
191
|
-
expect(restored).toEqual(original);
|
|
192
|
-
}
|
|
193
|
-
});
|
|
194
|
-
});
|
|
195
|
-
|
|
196
|
-
//#endregion
|
|
197
|
-
});
|