@simplysm/core-common 13.0.99 → 14.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/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 +5 -0
- package/dist/env.d.ts.map +1 -1
- package/dist/env.js +12 -8
- 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/package.json +5 -7
- package/src/common.types.ts +14 -14
- package/src/env.ts +9 -1
- 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/README.md +0 -160
- package/docs/errors.md +0 -119
- package/docs/extensions.md +0 -387
- package/docs/features.md +0 -143
- package/docs/types.md +0 -287
- package/docs/utils.md +0 -757
- 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
|
@@ -1,810 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect } from "vitest";
|
|
2
|
-
import { obj as objU, DateTime, DateOnly, Uuid } from "@simplysm/core-common";
|
|
3
|
-
|
|
4
|
-
describe("object utils", () => {
|
|
5
|
-
//#region clone
|
|
6
|
-
|
|
7
|
-
describe("objClone()", () => {
|
|
8
|
-
it("Clones primitive values", () => {
|
|
9
|
-
expect(objU.clone(42)).toBe(42);
|
|
10
|
-
expect(objU.clone("hello")).toBe("hello");
|
|
11
|
-
expect(objU.clone(true)).toBe(true);
|
|
12
|
-
expect(objU.clone(null)).toBe(null);
|
|
13
|
-
expect(objU.clone(undefined)).toBe(undefined);
|
|
14
|
-
});
|
|
15
|
-
|
|
16
|
-
it("Deep clones array", () => {
|
|
17
|
-
const arr = [1, [2, 3], { a: 4 }];
|
|
18
|
-
const cloned = objU.clone(arr);
|
|
19
|
-
|
|
20
|
-
expect(cloned).toEqual(arr);
|
|
21
|
-
expect(cloned).not.toBe(arr);
|
|
22
|
-
expect(cloned[1]).not.toBe(arr[1]);
|
|
23
|
-
expect(cloned[2]).not.toBe(arr[2]);
|
|
24
|
-
});
|
|
25
|
-
|
|
26
|
-
it("Deep clones object", () => {
|
|
27
|
-
const obj = { a: 1, b: { c: 2 }, d: [3, 4] };
|
|
28
|
-
const cloned = objU.clone(obj);
|
|
29
|
-
|
|
30
|
-
expect(cloned).toEqual(obj);
|
|
31
|
-
expect(cloned).not.toBe(obj);
|
|
32
|
-
expect(cloned.b).not.toBe(obj.b);
|
|
33
|
-
expect(cloned.d).not.toBe(obj.d);
|
|
34
|
-
});
|
|
35
|
-
|
|
36
|
-
it("Clones Date", () => {
|
|
37
|
-
const date = new Date(2024, 2, 15);
|
|
38
|
-
const cloned = objU.clone(date);
|
|
39
|
-
|
|
40
|
-
expect(cloned).toEqual(date);
|
|
41
|
-
expect(cloned).not.toBe(date);
|
|
42
|
-
});
|
|
43
|
-
|
|
44
|
-
it("Clones DateTime", () => {
|
|
45
|
-
const dt = new DateTime(2024, 3, 15, 10, 30);
|
|
46
|
-
const cloned = objU.clone(dt);
|
|
47
|
-
|
|
48
|
-
expect(cloned.tick).toBe(dt.tick);
|
|
49
|
-
expect(cloned).not.toBe(dt);
|
|
50
|
-
});
|
|
51
|
-
|
|
52
|
-
it("Clones DateOnly", () => {
|
|
53
|
-
const d = new DateOnly(2024, 3, 15);
|
|
54
|
-
const cloned = objU.clone(d);
|
|
55
|
-
|
|
56
|
-
expect(cloned.tick).toBe(d.tick);
|
|
57
|
-
expect(cloned).not.toBe(d);
|
|
58
|
-
});
|
|
59
|
-
|
|
60
|
-
it("Clones Uuid", () => {
|
|
61
|
-
const uuid = Uuid.generate();
|
|
62
|
-
const cloned = objU.clone(uuid);
|
|
63
|
-
|
|
64
|
-
expect(cloned.toString()).toBe(uuid.toString());
|
|
65
|
-
expect(cloned).not.toBe(uuid);
|
|
66
|
-
});
|
|
67
|
-
|
|
68
|
-
it("Clones Map", () => {
|
|
69
|
-
const map = new Map<string, number | { c: number }>([
|
|
70
|
-
["a", 1],
|
|
71
|
-
["b", { c: 2 }],
|
|
72
|
-
]);
|
|
73
|
-
const cloned = objU.clone(map);
|
|
74
|
-
|
|
75
|
-
expect(cloned.get("a")).toBe(1);
|
|
76
|
-
expect(cloned.get("b")).toEqual({ c: 2 });
|
|
77
|
-
expect(cloned.get("b")).not.toBe(map.get("b"));
|
|
78
|
-
});
|
|
79
|
-
|
|
80
|
-
it("Clones Set", () => {
|
|
81
|
-
const obj = { a: 1 };
|
|
82
|
-
const set = new Set([1, 2, obj]);
|
|
83
|
-
const cloned = objU.clone(set);
|
|
84
|
-
|
|
85
|
-
expect(cloned.has(1)).toBe(true);
|
|
86
|
-
expect(cloned.has(2)).toBe(true);
|
|
87
|
-
// Object in Set is cloned
|
|
88
|
-
const clonedObj = Array.from(cloned).find((item) => typeof item === "object");
|
|
89
|
-
expect(clonedObj).toEqual(obj);
|
|
90
|
-
expect(clonedObj).not.toBe(obj);
|
|
91
|
-
});
|
|
92
|
-
|
|
93
|
-
it("Handles circular references", () => {
|
|
94
|
-
const obj: Record<string, unknown> = { a: 1 };
|
|
95
|
-
obj["self"] = obj;
|
|
96
|
-
|
|
97
|
-
const cloned = objU.clone(obj);
|
|
98
|
-
|
|
99
|
-
expect(cloned["a"]).toBe(1);
|
|
100
|
-
expect(cloned["self"]).toBe(cloned);
|
|
101
|
-
expect(cloned).not.toBe(obj);
|
|
102
|
-
});
|
|
103
|
-
|
|
104
|
-
it("Clones RegExp", () => {
|
|
105
|
-
const regex = /test/gi;
|
|
106
|
-
const cloned = objU.clone(regex);
|
|
107
|
-
|
|
108
|
-
expect(cloned).toEqual(regex);
|
|
109
|
-
expect(cloned).not.toBe(regex);
|
|
110
|
-
expect(cloned.source).toBe("test");
|
|
111
|
-
expect(cloned.flags).toBe("gi");
|
|
112
|
-
});
|
|
113
|
-
|
|
114
|
-
it("Clones Error", () => {
|
|
115
|
-
const error = new Error("test error");
|
|
116
|
-
const cloned = objU.clone(error);
|
|
117
|
-
|
|
118
|
-
expect(cloned.message).toBe("test error");
|
|
119
|
-
expect(cloned).not.toBe(error);
|
|
120
|
-
});
|
|
121
|
-
|
|
122
|
-
it("Clones Error cause", () => {
|
|
123
|
-
const cause = new Error("cause error");
|
|
124
|
-
const error = new Error("test error", { cause });
|
|
125
|
-
const cloned = objU.clone(error);
|
|
126
|
-
|
|
127
|
-
expect(cloned.message).toBe("test error");
|
|
128
|
-
expect(cloned.cause).toBeInstanceOf(Error);
|
|
129
|
-
expect((cloned.cause as Error).message).toBe("cause error");
|
|
130
|
-
});
|
|
131
|
-
|
|
132
|
-
it("Clones Error custom properties", () => {
|
|
133
|
-
const error = new Error("test") as Error & { code: string; detail: object };
|
|
134
|
-
error.code = "ERR_CODE";
|
|
135
|
-
error.detail = { key: "value" };
|
|
136
|
-
const cloned = objU.clone(error);
|
|
137
|
-
|
|
138
|
-
expect(cloned.code).toBe("ERR_CODE");
|
|
139
|
-
expect(cloned.detail).toEqual({ key: "value" });
|
|
140
|
-
expect(cloned.detail).not.toBe(error.detail);
|
|
141
|
-
});
|
|
142
|
-
|
|
143
|
-
it("Clones Uint8Array", () => {
|
|
144
|
-
const arr = new Uint8Array([1, 2, 3, 4, 5]);
|
|
145
|
-
const cloned = objU.clone(arr);
|
|
146
|
-
|
|
147
|
-
expect(cloned).toEqual(arr);
|
|
148
|
-
expect(cloned).not.toBe(arr);
|
|
149
|
-
expect(cloned.buffer).not.toBe(arr.buffer);
|
|
150
|
-
});
|
|
151
|
-
|
|
152
|
-
it("Symbol keys are not cloned", () => {
|
|
153
|
-
// Object.keys() does not enumerate Symbol keys, so they are not cloned
|
|
154
|
-
const sym = Symbol("test");
|
|
155
|
-
const obj = { a: 1, [sym]: "symbol value" };
|
|
156
|
-
const cloned = objU.clone(obj);
|
|
157
|
-
|
|
158
|
-
expect(cloned.a).toBe(1);
|
|
159
|
-
expect(cloned[sym]).toBeUndefined();
|
|
160
|
-
});
|
|
161
|
-
});
|
|
162
|
-
|
|
163
|
-
//#endregion
|
|
164
|
-
|
|
165
|
-
//#region equal
|
|
166
|
-
|
|
167
|
-
describe("objU.equal()", () => {
|
|
168
|
-
it("Compares primitive values", () => {
|
|
169
|
-
expect(objU.equal(1, 1)).toBe(true);
|
|
170
|
-
expect(objU.equal(1, 2)).toBe(false);
|
|
171
|
-
expect(objU.equal("a", "a")).toBe(true);
|
|
172
|
-
expect(objU.equal(null, null)).toBe(true);
|
|
173
|
-
expect(objU.equal(undefined, undefined)).toBe(true);
|
|
174
|
-
expect(objU.equal(null, undefined)).toBe(false);
|
|
175
|
-
});
|
|
176
|
-
|
|
177
|
-
it("Compares arrays", () => {
|
|
178
|
-
expect(objU.equal([1, 2, 3], [1, 2, 3])).toBe(true);
|
|
179
|
-
expect(objU.equal([1, 2, 3], [1, 2])).toBe(false);
|
|
180
|
-
expect(objU.equal([1, 2, 3], [1, 3, 2])).toBe(false);
|
|
181
|
-
});
|
|
182
|
-
|
|
183
|
-
it("Compares objects", () => {
|
|
184
|
-
expect(objU.equal({ a: 1, b: 2 }, { a: 1, b: 2 })).toBe(true);
|
|
185
|
-
expect(objU.equal({ a: 1, b: 2 }, { a: 1, b: 3 })).toBe(false);
|
|
186
|
-
expect(objU.equal({ a: 1 }, { a: 1, b: 2 })).toBe(false);
|
|
187
|
-
});
|
|
188
|
-
|
|
189
|
-
it("Compares nested objects", () => {
|
|
190
|
-
expect(objU.equal({ a: { b: { c: 1 } } }, { a: { b: { c: 1 } } })).toBe(true);
|
|
191
|
-
expect(objU.equal({ a: { b: { c: 1 } } }, { a: { b: { c: 2 } } })).toBe(false);
|
|
192
|
-
});
|
|
193
|
-
|
|
194
|
-
it("Compares DateTime", () => {
|
|
195
|
-
const dt1 = new DateTime(2024, 3, 15);
|
|
196
|
-
const dt2 = new DateTime(2024, 3, 15);
|
|
197
|
-
const dt3 = new DateTime(2024, 3, 16);
|
|
198
|
-
|
|
199
|
-
expect(objU.equal(dt1, dt2)).toBe(true);
|
|
200
|
-
expect(objU.equal(dt1, dt3)).toBe(false);
|
|
201
|
-
});
|
|
202
|
-
|
|
203
|
-
it("Compares Uuid", () => {
|
|
204
|
-
const uuid1 = new Uuid("12345678-9abc-def0-1234-56789abcdef0");
|
|
205
|
-
const uuid2 = new Uuid("12345678-9abc-def0-1234-56789abcdef0");
|
|
206
|
-
const uuid3 = new Uuid("12345678-9abc-def0-1234-56789abcdef1");
|
|
207
|
-
|
|
208
|
-
expect(objU.equal(uuid1, uuid2)).toBe(true);
|
|
209
|
-
expect(objU.equal(uuid1, uuid3)).toBe(false);
|
|
210
|
-
});
|
|
211
|
-
|
|
212
|
-
it("Compares RegExp", () => {
|
|
213
|
-
const regex1 = /test/gi;
|
|
214
|
-
const regex2 = /test/gi;
|
|
215
|
-
const regex3 = /test/g;
|
|
216
|
-
const regex4 = /other/gi;
|
|
217
|
-
|
|
218
|
-
expect(objU.equal(regex1, regex2)).toBe(true);
|
|
219
|
-
expect(objU.equal(regex1, regex3)).toBe(false); // Different flags
|
|
220
|
-
expect(objU.equal(regex1, regex4)).toBe(false); // Different source
|
|
221
|
-
});
|
|
222
|
-
|
|
223
|
-
it("Compares Map", () => {
|
|
224
|
-
const map1 = new Map([
|
|
225
|
-
["a", 1],
|
|
226
|
-
["b", 2],
|
|
227
|
-
]);
|
|
228
|
-
const map2 = new Map([
|
|
229
|
-
["a", 1],
|
|
230
|
-
["b", 2],
|
|
231
|
-
]);
|
|
232
|
-
const map3 = new Map([
|
|
233
|
-
["a", 1],
|
|
234
|
-
["b", 3],
|
|
235
|
-
]);
|
|
236
|
-
|
|
237
|
-
expect(objU.equal(map1, map2)).toBe(true);
|
|
238
|
-
expect(objU.equal(map1, map3)).toBe(false);
|
|
239
|
-
});
|
|
240
|
-
|
|
241
|
-
it("Compares Set", () => {
|
|
242
|
-
const set1 = new Set([1, 2, 3]);
|
|
243
|
-
const set2 = new Set([1, 2, 3]);
|
|
244
|
-
const set3 = new Set([1, 2, 4]);
|
|
245
|
-
|
|
246
|
-
expect(objU.equal(set1, set2)).toBe(true);
|
|
247
|
-
expect(objU.equal(set1, set3)).toBe(false);
|
|
248
|
-
});
|
|
249
|
-
|
|
250
|
-
it("Compares only specific keys with topLevelIncludes option", () => {
|
|
251
|
-
const obj1 = { a: 1, b: 2, c: 3 };
|
|
252
|
-
const obj2 = { a: 1, b: 99, c: 99 };
|
|
253
|
-
|
|
254
|
-
expect(objU.equal(obj1, obj2, { topLevelIncludes: ["a"] })).toBe(true);
|
|
255
|
-
expect(objU.equal(obj1, obj2, { topLevelIncludes: ["a", "b"] })).toBe(false);
|
|
256
|
-
});
|
|
257
|
-
|
|
258
|
-
it("Excludes specific keys with topLevelExcludes option", () => {
|
|
259
|
-
const obj1 = { a: 1, b: 2, c: 3 };
|
|
260
|
-
const obj2 = { a: 1, b: 99, c: 99 };
|
|
261
|
-
|
|
262
|
-
expect(objU.equal(obj1, obj2, { topLevelExcludes: ["b", "c"] })).toBe(true);
|
|
263
|
-
});
|
|
264
|
-
|
|
265
|
-
it("Ignores array order with ignoreArrayIndex option", () => {
|
|
266
|
-
expect(objU.equal([1, 2, 3], [3, 2, 1], { ignoreArrayIndex: true })).toBe(true);
|
|
267
|
-
});
|
|
268
|
-
|
|
269
|
-
it("Performs shallow comparison with shallow option", () => {
|
|
270
|
-
const inner = { c: 1 };
|
|
271
|
-
const obj1 = { a: 1, b: inner };
|
|
272
|
-
const obj2 = { a: 1, b: inner };
|
|
273
|
-
const obj3 = { a: 1, b: { c: 1 } };
|
|
274
|
-
|
|
275
|
-
expect(objU.equal(obj1, obj2, { shallow: true })).toBe(true);
|
|
276
|
-
expect(objU.equal(obj1, obj3, { shallow: true })).toBe(false);
|
|
277
|
-
});
|
|
278
|
-
});
|
|
279
|
-
|
|
280
|
-
//#endregion
|
|
281
|
-
|
|
282
|
-
//#region merge
|
|
283
|
-
|
|
284
|
-
describe("objU.merge()", () => {
|
|
285
|
-
it("Copies target when source is null", () => {
|
|
286
|
-
const target = { a: 1 };
|
|
287
|
-
const result = objU.merge(null, target);
|
|
288
|
-
|
|
289
|
-
expect(result).toEqual({ a: 1 });
|
|
290
|
-
expect(result).not.toBe(target);
|
|
291
|
-
});
|
|
292
|
-
|
|
293
|
-
it("Copies source when target is undefined", () => {
|
|
294
|
-
const source = { a: 1 };
|
|
295
|
-
const result = objU.merge(source, undefined);
|
|
296
|
-
|
|
297
|
-
expect(result).toEqual({ a: 1 });
|
|
298
|
-
});
|
|
299
|
-
|
|
300
|
-
it("Merges objects", () => {
|
|
301
|
-
const source = { a: 1, b: 2 };
|
|
302
|
-
const target = { b: 3, c: 4 };
|
|
303
|
-
const result = objU.merge(source, target);
|
|
304
|
-
|
|
305
|
-
expect(result).toEqual({ a: 1, b: 3, c: 4 });
|
|
306
|
-
});
|
|
307
|
-
|
|
308
|
-
it("Merges nested objects", () => {
|
|
309
|
-
const source = { a: { b: 1, c: 2 } };
|
|
310
|
-
const target = { a: { c: 3, d: 4 } };
|
|
311
|
-
const result = objU.merge(source, target);
|
|
312
|
-
|
|
313
|
-
expect(result).toEqual({ a: { b: 1, c: 3, d: 4 } });
|
|
314
|
-
});
|
|
315
|
-
|
|
316
|
-
it("Replaces array with arrayProcess: replace", () => {
|
|
317
|
-
const source = { arr: [1, 2, 3] };
|
|
318
|
-
const target = { arr: [4, 5] };
|
|
319
|
-
const result = objU.merge(source, target, { arrayProcess: "replace" });
|
|
320
|
-
|
|
321
|
-
expect(result.arr).toEqual([4, 5]);
|
|
322
|
-
});
|
|
323
|
-
|
|
324
|
-
it("Concatenates arrays with arrayProcess: concat", () => {
|
|
325
|
-
const source = { arr: [1, 2, 3] };
|
|
326
|
-
const target = { arr: [3, 4, 5] };
|
|
327
|
-
const result = objU.merge(source, target, { arrayProcess: "concat" });
|
|
328
|
-
|
|
329
|
-
// Duplicates removed via Set
|
|
330
|
-
expect(result.arr).toEqual([1, 2, 3, 4, 5]);
|
|
331
|
-
});
|
|
332
|
-
|
|
333
|
-
it("Deletes when null with useDelTargetNull option", () => {
|
|
334
|
-
const source = { a: 1, b: 2 };
|
|
335
|
-
const target = { b: null };
|
|
336
|
-
const result = objU.merge(source, target, { useDelTargetNull: true });
|
|
337
|
-
|
|
338
|
-
expect(result).toEqual({ a: 1 });
|
|
339
|
-
});
|
|
340
|
-
|
|
341
|
-
it("Returns target when source is object and target is primitive", () => {
|
|
342
|
-
const source = { a: 1 };
|
|
343
|
-
const target = "string";
|
|
344
|
-
|
|
345
|
-
const result = objU.merge(source, target as any);
|
|
346
|
-
|
|
347
|
-
expect(result).toBe("string");
|
|
348
|
-
});
|
|
349
|
-
|
|
350
|
-
it("Returns target when source is primitive and target is object", () => {
|
|
351
|
-
const source = "string";
|
|
352
|
-
const target = { a: 1 };
|
|
353
|
-
|
|
354
|
-
const result = objU.merge(source as any, target);
|
|
355
|
-
|
|
356
|
-
expect(result).toEqual({ a: 1 });
|
|
357
|
-
});
|
|
358
|
-
|
|
359
|
-
it("Returns target when source is array and target is plain object", () => {
|
|
360
|
-
const source = [1, 2, 3];
|
|
361
|
-
const target = { a: 1 };
|
|
362
|
-
|
|
363
|
-
const result = objU.merge(source as any, target);
|
|
364
|
-
|
|
365
|
-
expect(result).toEqual({ a: 1 });
|
|
366
|
-
});
|
|
367
|
-
|
|
368
|
-
it("Returns target when source is plain object and target is array", () => {
|
|
369
|
-
const source = { a: 1 };
|
|
370
|
-
const target = [1, 2, 3];
|
|
371
|
-
|
|
372
|
-
const result = objU.merge(source as any, target);
|
|
373
|
-
|
|
374
|
-
expect(result).toEqual([1, 2, 3]);
|
|
375
|
-
});
|
|
376
|
-
|
|
377
|
-
it("Merges deeply nested objects (3+ levels)", () => {
|
|
378
|
-
const source = {
|
|
379
|
-
level1: {
|
|
380
|
-
level2: {
|
|
381
|
-
level3: {
|
|
382
|
-
a: 1,
|
|
383
|
-
b: 2,
|
|
384
|
-
},
|
|
385
|
-
x: 10,
|
|
386
|
-
},
|
|
387
|
-
y: 20,
|
|
388
|
-
},
|
|
389
|
-
z: 30,
|
|
390
|
-
};
|
|
391
|
-
const target = {
|
|
392
|
-
level1: {
|
|
393
|
-
level2: {
|
|
394
|
-
level3: {
|
|
395
|
-
b: 3,
|
|
396
|
-
c: 4,
|
|
397
|
-
},
|
|
398
|
-
},
|
|
399
|
-
},
|
|
400
|
-
};
|
|
401
|
-
|
|
402
|
-
const result = objU.merge(source, target);
|
|
403
|
-
|
|
404
|
-
expect(result).toEqual({
|
|
405
|
-
level1: {
|
|
406
|
-
level2: {
|
|
407
|
-
level3: {
|
|
408
|
-
a: 1,
|
|
409
|
-
b: 3,
|
|
410
|
-
c: 4,
|
|
411
|
-
},
|
|
412
|
-
x: 10,
|
|
413
|
-
},
|
|
414
|
-
y: 20,
|
|
415
|
-
},
|
|
416
|
-
z: 30,
|
|
417
|
-
});
|
|
418
|
-
});
|
|
419
|
-
|
|
420
|
-
it("Modifies only deep value in 4-level nesting", () => {
|
|
421
|
-
const source = {
|
|
422
|
-
a: {
|
|
423
|
-
b: {
|
|
424
|
-
c: {
|
|
425
|
-
d: { value: 1 },
|
|
426
|
-
},
|
|
427
|
-
},
|
|
428
|
-
},
|
|
429
|
-
};
|
|
430
|
-
const target = {
|
|
431
|
-
a: {
|
|
432
|
-
b: {
|
|
433
|
-
c: {
|
|
434
|
-
d: { value: 2 },
|
|
435
|
-
},
|
|
436
|
-
},
|
|
437
|
-
},
|
|
438
|
-
};
|
|
439
|
-
|
|
440
|
-
const result = objU.merge(source, target);
|
|
441
|
-
|
|
442
|
-
expect(result.a.b.c.d.value).toBe(2);
|
|
443
|
-
});
|
|
444
|
-
|
|
445
|
-
it("Clones new key-value in Map merge", () => {
|
|
446
|
-
const sourceMap = new Map<string, { value: number }>([["key1", { value: 1 }]]);
|
|
447
|
-
const targetObj = { value: 2 };
|
|
448
|
-
const targetMap = new Map<string, { value: number }>([["key2", targetObj]]);
|
|
449
|
-
|
|
450
|
-
const result = objU.merge(sourceMap, targetMap);
|
|
451
|
-
|
|
452
|
-
// key2 value is cloned, should be different reference
|
|
453
|
-
expect(result.get("key2")).toEqual({ value: 2 });
|
|
454
|
-
expect(result.get("key2")).not.toBe(targetObj);
|
|
455
|
-
});
|
|
456
|
-
});
|
|
457
|
-
|
|
458
|
-
describe("objU.merge3()", () => {
|
|
459
|
-
it("Uses source value when only source changes", () => {
|
|
460
|
-
const origin = { a: 1, b: 2 };
|
|
461
|
-
const source = { a: 1, b: 3 };
|
|
462
|
-
const target = { a: 1, b: 2 };
|
|
463
|
-
const { conflict, result } = objU.merge3(source, origin, target);
|
|
464
|
-
|
|
465
|
-
expect(conflict).toBe(false);
|
|
466
|
-
expect(result).toEqual({ a: 1, b: 3 });
|
|
467
|
-
});
|
|
468
|
-
|
|
469
|
-
it("Uses target value when only target changes", () => {
|
|
470
|
-
const origin = { a: 1, b: 2 };
|
|
471
|
-
const source = { a: 1, b: 2 };
|
|
472
|
-
const target = { a: 1, b: 4 };
|
|
473
|
-
const { conflict, result } = objU.merge3(source, origin, target);
|
|
474
|
-
|
|
475
|
-
expect(conflict).toBe(false);
|
|
476
|
-
expect(result).toEqual({ a: 1, b: 4 });
|
|
477
|
-
});
|
|
478
|
-
|
|
479
|
-
it("Uses value without conflict when both change to same value", () => {
|
|
480
|
-
const origin = { a: 1, b: 2 };
|
|
481
|
-
const source = { a: 1, b: 5 };
|
|
482
|
-
const target = { a: 1, b: 5 };
|
|
483
|
-
const { conflict, result } = objU.merge3(source, origin, target);
|
|
484
|
-
|
|
485
|
-
expect(conflict).toBe(false);
|
|
486
|
-
expect(result).toEqual({ a: 1, b: 5 });
|
|
487
|
-
});
|
|
488
|
-
|
|
489
|
-
it("Returns conflict when both change to different values", () => {
|
|
490
|
-
const origin = { a: 1, b: 2 };
|
|
491
|
-
const source = { a: 1, b: 3 };
|
|
492
|
-
const target = { a: 1, b: 4 };
|
|
493
|
-
const { conflict, result } = objU.merge3(source, origin, target);
|
|
494
|
-
|
|
495
|
-
expect(conflict).toBe(true);
|
|
496
|
-
// Origin value preserved
|
|
497
|
-
expect(result.b).toBe(2);
|
|
498
|
-
});
|
|
499
|
-
|
|
500
|
-
it("Returns conflict when only some keys conflict", () => {
|
|
501
|
-
const origin = { a: 1, b: 2, c: 3 };
|
|
502
|
-
const source = { a: 10, b: 20, c: 3 };
|
|
503
|
-
const target = { a: 1, b: 30, c: 4 };
|
|
504
|
-
const { conflict, result } = objU.merge3(source, origin, target);
|
|
505
|
-
|
|
506
|
-
expect(conflict).toBe(true);
|
|
507
|
-
expect(result.a).toBe(10); // Only source changed
|
|
508
|
-
expect(result.b).toBe(2); // Both changed differently → conflict → origin preserved
|
|
509
|
-
expect(result.c).toBe(4); // Only target changed
|
|
510
|
-
});
|
|
511
|
-
|
|
512
|
-
it("Detects conflict in nested objects", () => {
|
|
513
|
-
const origin = { a: { b: 1, c: 2 } };
|
|
514
|
-
const source = { a: { b: 10, c: 2 } };
|
|
515
|
-
const target = { a: { b: 20, c: 2 } };
|
|
516
|
-
const { conflict, result } = objU.merge3(source, origin, target);
|
|
517
|
-
|
|
518
|
-
expect(conflict).toBe(true);
|
|
519
|
-
expect(result.a.b).toBe(1); // Both changed differently → conflict → origin preserved
|
|
520
|
-
expect(result.a.c).toBe(2);
|
|
521
|
-
});
|
|
522
|
-
|
|
523
|
-
it("Detects conflict in nested object when different internal keys change", () => {
|
|
524
|
-
// merge3 compares at key level, so entire { a: {...} } is compared
|
|
525
|
-
// If source.a differs from origin.a and target.a differs from origin.a, conflict
|
|
526
|
-
const origin = { a: { b: 1, c: 2 } };
|
|
527
|
-
const source = { a: { b: 10, c: 2 } };
|
|
528
|
-
const target = { a: { b: 1, c: 20 } };
|
|
529
|
-
const { conflict, result } = objU.merge3(source, origin, target);
|
|
530
|
-
|
|
531
|
-
expect(conflict).toBe(true);
|
|
532
|
-
expect(result.a.b).toBe(1); // Conflict → origin preserved
|
|
533
|
-
expect(result.a.c).toBe(2);
|
|
534
|
-
});
|
|
535
|
-
|
|
536
|
-
it("Detects conflict in array", () => {
|
|
537
|
-
const origin = { arr: [1, 2, 3] };
|
|
538
|
-
const source = { arr: [1, 2, 4] };
|
|
539
|
-
const target = { arr: [1, 2, 5] };
|
|
540
|
-
const { conflict, result } = objU.merge3(source, origin, target);
|
|
541
|
-
|
|
542
|
-
expect(conflict).toBe(true);
|
|
543
|
-
expect(result.arr).toEqual([1, 2, 3]); // Conflict → origin preserved
|
|
544
|
-
});
|
|
545
|
-
|
|
546
|
-
it("Detects conflict in primitive value", () => {
|
|
547
|
-
const origin = { value: "original" };
|
|
548
|
-
const source = { value: "from source" };
|
|
549
|
-
const target = { value: "from target" };
|
|
550
|
-
const { conflict, result } = objU.merge3(source, origin, target);
|
|
551
|
-
|
|
552
|
-
expect(conflict).toBe(true);
|
|
553
|
-
expect(result.value).toBe("original"); // Conflict → origin preserved
|
|
554
|
-
});
|
|
555
|
-
});
|
|
556
|
-
|
|
557
|
-
//#endregion
|
|
558
|
-
|
|
559
|
-
//#region omit / pick
|
|
560
|
-
|
|
561
|
-
describe("objU.omit()", () => {
|
|
562
|
-
it("Excludes specific keys", () => {
|
|
563
|
-
const obj = { a: 1, b: 2, c: 3 };
|
|
564
|
-
const result = objU.omit(obj, ["b"]);
|
|
565
|
-
|
|
566
|
-
expect(result).toEqual({ a: 1, c: 3 });
|
|
567
|
-
});
|
|
568
|
-
|
|
569
|
-
it("Excludes multiple keys", () => {
|
|
570
|
-
const obj = { a: 1, b: 2, c: 3, d: 4 };
|
|
571
|
-
const result = objU.omit(obj, ["a", "c"]);
|
|
572
|
-
|
|
573
|
-
expect(result).toEqual({ b: 2, d: 4 });
|
|
574
|
-
});
|
|
575
|
-
});
|
|
576
|
-
|
|
577
|
-
describe("objU.omitByFilter()", () => {
|
|
578
|
-
it("Excludes keys matching condition", () => {
|
|
579
|
-
const obj = { a: 1, b: 2, c: 3 };
|
|
580
|
-
const result = objU.omitByFilter(obj, (key) => key === "b");
|
|
581
|
-
|
|
582
|
-
expect(result).toEqual({ a: 1, c: 3 });
|
|
583
|
-
});
|
|
584
|
-
});
|
|
585
|
-
|
|
586
|
-
describe("objU.pick()", () => {
|
|
587
|
-
it("Selects only specific keys", () => {
|
|
588
|
-
const obj = { a: 1, b: 2, c: 3 };
|
|
589
|
-
const result = objU.pick(obj, ["a", "c"]);
|
|
590
|
-
|
|
591
|
-
expect(result).toEqual({ a: 1, c: 3 });
|
|
592
|
-
});
|
|
593
|
-
});
|
|
594
|
-
|
|
595
|
-
//#endregion
|
|
596
|
-
|
|
597
|
-
//#region chain value
|
|
598
|
-
|
|
599
|
-
describe("objU.getChainValue()", () => {
|
|
600
|
-
it("Gets value using dot notation", () => {
|
|
601
|
-
const obj = { a: { b: { c: 1 } } };
|
|
602
|
-
|
|
603
|
-
expect(objU.getChainValue(obj, "a.b.c")).toBe(1);
|
|
604
|
-
});
|
|
605
|
-
|
|
606
|
-
it("Gets value using array notation", () => {
|
|
607
|
-
const obj = { arr: [{ name: "first" }, { name: "second" }] };
|
|
608
|
-
|
|
609
|
-
expect(objU.getChainValue(obj, "arr[1].name")).toBe("second");
|
|
610
|
-
});
|
|
611
|
-
|
|
612
|
-
it("Returns undefined for non-existent path with optional: true", () => {
|
|
613
|
-
const obj = { a: 1 };
|
|
614
|
-
|
|
615
|
-
expect(objU.getChainValue(obj, "b.c.d", true)).toBe(undefined);
|
|
616
|
-
});
|
|
617
|
-
});
|
|
618
|
-
|
|
619
|
-
describe("objU.getChainValueByDepth()", () => {
|
|
620
|
-
it("Descends by depth using same key", () => {
|
|
621
|
-
const obj = {
|
|
622
|
-
parent: {
|
|
623
|
-
parent: {
|
|
624
|
-
parent: {
|
|
625
|
-
name: "leaf",
|
|
626
|
-
},
|
|
627
|
-
},
|
|
628
|
-
},
|
|
629
|
-
};
|
|
630
|
-
|
|
631
|
-
const result = objU.getChainValueByDepth(obj, "parent", 2);
|
|
632
|
-
|
|
633
|
-
expect(result).toEqual({ parent: { name: "leaf" } });
|
|
634
|
-
});
|
|
635
|
-
|
|
636
|
-
it("Throws error when depth is 0", () => {
|
|
637
|
-
const obj = { parent: { name: "child" } };
|
|
638
|
-
|
|
639
|
-
expect(() => objU.getChainValueByDepth(obj, "parent", 0)).toThrow(
|
|
640
|
-
"depth must be 1 or greater",
|
|
641
|
-
);
|
|
642
|
-
});
|
|
643
|
-
|
|
644
|
-
it("Descends one level when depth is 1", () => {
|
|
645
|
-
const obj = { parent: { name: "child" } };
|
|
646
|
-
|
|
647
|
-
const result = objU.getChainValueByDepth(obj, "parent", 1);
|
|
648
|
-
|
|
649
|
-
expect(result).toEqual({ name: "child" });
|
|
650
|
-
});
|
|
651
|
-
|
|
652
|
-
it("Returns undefined when intermediate path missing with optional: true", () => {
|
|
653
|
-
const obj = { parent: { name: "child" } };
|
|
654
|
-
|
|
655
|
-
const result = objU.getChainValueByDepth(obj, "parent", 5, true);
|
|
656
|
-
|
|
657
|
-
expect(result).toBe(undefined);
|
|
658
|
-
});
|
|
659
|
-
|
|
660
|
-
it("Throws error when intermediate path missing without optional", () => {
|
|
661
|
-
const obj = { parent: undefined as unknown };
|
|
662
|
-
|
|
663
|
-
// Without optional, trying to access property on undefined throws error
|
|
664
|
-
// Current implementation only checks result == null inside optional condition
|
|
665
|
-
// So without optional, error is possible
|
|
666
|
-
expect(() => objU.getChainValueByDepth(obj as any, "parent", 2)).toThrow();
|
|
667
|
-
});
|
|
668
|
-
});
|
|
669
|
-
|
|
670
|
-
describe("objU.setChainValue()", () => {
|
|
671
|
-
it("Sets value using dot notation", () => {
|
|
672
|
-
const obj: Record<string, unknown> = {};
|
|
673
|
-
objU.setChainValue(obj, "a.b.c", 1);
|
|
674
|
-
|
|
675
|
-
expect(obj).toEqual({ a: { b: { c: 1 } } });
|
|
676
|
-
});
|
|
677
|
-
|
|
678
|
-
it("Overwrites existing value", () => {
|
|
679
|
-
const obj = { a: { b: { c: 1 } } };
|
|
680
|
-
objU.setChainValue(obj, "a.b.c", 2);
|
|
681
|
-
|
|
682
|
-
expect(obj.a.b.c).toBe(2);
|
|
683
|
-
});
|
|
684
|
-
|
|
685
|
-
it("Throws error for empty chain", () => {
|
|
686
|
-
const obj: Record<string, unknown> = {};
|
|
687
|
-
|
|
688
|
-
expect(() => objU.setChainValue(obj, "", 1)).toThrow();
|
|
689
|
-
});
|
|
690
|
-
});
|
|
691
|
-
|
|
692
|
-
describe("objU.deleteChainValue()", () => {
|
|
693
|
-
it("Deletes value at chain path", () => {
|
|
694
|
-
const obj = { a: { b: { c: 1, d: 2 } } };
|
|
695
|
-
objU.deleteChainValue(obj, "a.b.c");
|
|
696
|
-
|
|
697
|
-
expect(obj.a.b).toEqual({ d: 2 });
|
|
698
|
-
});
|
|
699
|
-
|
|
700
|
-
it("Silently ignores non-existent path", () => {
|
|
701
|
-
const obj = { a: 1 };
|
|
702
|
-
|
|
703
|
-
// No error when intermediate path missing
|
|
704
|
-
expect(() => objU.deleteChainValue(obj, "b.c.d")).not.toThrow();
|
|
705
|
-
expect(obj).toEqual({ a: 1 });
|
|
706
|
-
});
|
|
707
|
-
|
|
708
|
-
it("Silently ignores undefined intermediate path", () => {
|
|
709
|
-
const obj: Record<string, unknown> = { a: undefined };
|
|
710
|
-
|
|
711
|
-
expect(() => objU.deleteChainValue(obj, "a.b.c")).not.toThrow();
|
|
712
|
-
expect(obj).toEqual({ a: undefined });
|
|
713
|
-
});
|
|
714
|
-
|
|
715
|
-
it("Silently ignores null intermediate path", () => {
|
|
716
|
-
const obj: Record<string, unknown> = { a: null };
|
|
717
|
-
|
|
718
|
-
expect(() => objU.deleteChainValue(obj, "a.b.c")).not.toThrow();
|
|
719
|
-
expect(obj).toEqual({ a: null });
|
|
720
|
-
});
|
|
721
|
-
|
|
722
|
-
it("Deletes using array index path", () => {
|
|
723
|
-
const obj = { arr: [{ name: "first" }, { name: "second" }] };
|
|
724
|
-
objU.deleteChainValue(obj, "arr[0].name");
|
|
725
|
-
|
|
726
|
-
expect(obj.arr[0]).toEqual({});
|
|
727
|
-
expect(obj.arr[1]).toEqual({ name: "second" });
|
|
728
|
-
});
|
|
729
|
-
|
|
730
|
-
it("Throws error for empty chain", () => {
|
|
731
|
-
const obj = { a: 1 };
|
|
732
|
-
|
|
733
|
-
expect(() => objU.deleteChainValue(obj, "")).toThrow();
|
|
734
|
-
});
|
|
735
|
-
});
|
|
736
|
-
|
|
737
|
-
//#endregion
|
|
738
|
-
|
|
739
|
-
//#region clear / transform
|
|
740
|
-
|
|
741
|
-
describe("objU.clearUndefined()", () => {
|
|
742
|
-
it("Deletes keys with undefined value", () => {
|
|
743
|
-
const obj = { a: 1, b: undefined, c: 3 };
|
|
744
|
-
const result = objU.clearUndefined(obj);
|
|
745
|
-
|
|
746
|
-
expect(result).toEqual({ a: 1, c: 3 });
|
|
747
|
-
expect("b" in result).toBe(false);
|
|
748
|
-
});
|
|
749
|
-
});
|
|
750
|
-
|
|
751
|
-
describe("objU.clear()", () => {
|
|
752
|
-
it("Deletes all keys", () => {
|
|
753
|
-
const obj = { a: 1, b: 2, c: 3 };
|
|
754
|
-
const result = objU.clear(obj);
|
|
755
|
-
|
|
756
|
-
expect(Object.keys(result)).toHaveLength(0);
|
|
757
|
-
});
|
|
758
|
-
});
|
|
759
|
-
|
|
760
|
-
describe("objU.nullToUndefined()", () => {
|
|
761
|
-
it("Converts null to undefined", () => {
|
|
762
|
-
expect(objU.nullToUndefined(null)).toBe(undefined);
|
|
763
|
-
});
|
|
764
|
-
|
|
765
|
-
it("Converts nested null to undefined", () => {
|
|
766
|
-
const obj = { a: 1, b: null, c: { d: null } };
|
|
767
|
-
const result = objU.nullToUndefined(obj);
|
|
768
|
-
|
|
769
|
-
expect(result).toEqual({ a: 1, b: undefined, c: { d: undefined } });
|
|
770
|
-
});
|
|
771
|
-
|
|
772
|
-
it("Converts null in array to undefined", () => {
|
|
773
|
-
const arr = [1, null, { a: null }];
|
|
774
|
-
const result = objU.nullToUndefined(arr);
|
|
775
|
-
|
|
776
|
-
expect(result).toEqual([1, undefined, { a: undefined }]);
|
|
777
|
-
});
|
|
778
|
-
|
|
779
|
-
it("Safely handles object with circular references", () => {
|
|
780
|
-
const obj: Record<string, unknown> = { a: null };
|
|
781
|
-
obj["self"] = obj;
|
|
782
|
-
const result = objU.nullToUndefined(obj);
|
|
783
|
-
expect(result).toBeDefined();
|
|
784
|
-
expect((result as Record<string, unknown>)["a"]).toBeUndefined();
|
|
785
|
-
});
|
|
786
|
-
|
|
787
|
-
it("Safely handles array with circular references", () => {
|
|
788
|
-
const arr: unknown[] = [null, 1];
|
|
789
|
-
arr.push(arr);
|
|
790
|
-
const result = objU.nullToUndefined(arr);
|
|
791
|
-
expect(result).toBeDefined();
|
|
792
|
-
expect((result as unknown[])[0]).toBeUndefined();
|
|
793
|
-
expect((result as unknown[])[1]).toBe(1);
|
|
794
|
-
});
|
|
795
|
-
});
|
|
796
|
-
|
|
797
|
-
describe("objU.unflatten()", () => {
|
|
798
|
-
it("Converts flattened object to nested", () => {
|
|
799
|
-
const flat = { "a.b.c": 1, "a.b.d": 2, "e": 3 };
|
|
800
|
-
const result = objU.unflatten(flat);
|
|
801
|
-
|
|
802
|
-
expect(result).toEqual({
|
|
803
|
-
a: { b: { c: 1, d: 2 } },
|
|
804
|
-
e: 3,
|
|
805
|
-
});
|
|
806
|
-
});
|
|
807
|
-
});
|
|
808
|
-
|
|
809
|
-
//#endregion
|
|
810
|
-
});
|