@startinblox/components-ds4go 2.3.0 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.gitlab-ci.yml +8 -2
- package/AGENTS.md +516 -0
- package/cypress/component/no-component-test.cy.ts +9 -0
- package/cypress/e2e/helpers/components/setupCacheInvalidation.cy.ts +512 -0
- package/cypress/e2e/helpers/components/setupCacheOnResourceReady.cy.ts +483 -0
- package/cypress/e2e/helpers/components/setupComponentSubscriptions.cy.ts +239 -0
- package/cypress/e2e/helpers/components/setupOnSaveReset.cy.ts +380 -0
- package/cypress/e2e/helpers/datas/checkValueInIntervalRecursive.cy.ts +563 -0
- package/cypress/e2e/helpers/datas/dataBuilder.cy.ts +508 -0
- package/cypress/e2e/helpers/datas/filterGenerator.cy.ts +285 -0
- package/cypress/e2e/helpers/datas/filterObjectByDateAfter.cy.ts +389 -0
- package/cypress/e2e/helpers/datas/filterObjectByDateInterval.cy.ts +613 -0
- package/cypress/e2e/helpers/datas/filterObjectById.cy.ts +276 -0
- package/cypress/e2e/helpers/datas/filterObjectByInterval.cy.ts +237 -0
- package/cypress/e2e/helpers/datas/filterObjectByNamedValue.cy.ts +299 -0
- package/cypress/e2e/helpers/datas/filterObjectByType.cy.ts +307 -0
- package/cypress/e2e/helpers/datas/filterObjectByValue.cy.ts +375 -0
- package/cypress/e2e/helpers/datas/sort.cy.ts +293 -0
- package/cypress/e2e/helpers/ui/formatDate.cy.ts +233 -0
- package/cypress/e2e/helpers/utils/requestNavigation.cy.ts +257 -0
- package/cypress/e2e/helpers/utils/uniq.cy.ts +160 -0
- package/cypress/support/e2e.ts +1 -0
- package/cypress.config.ts +2 -0
- package/dist/index.js +1102 -1002
- package/package.json +10 -10
- package/src/components/solid-boilerplate.ts +76 -0
- package/src/helpers/components/componentObjectHandler.ts +5 -7
- package/src/helpers/components/componentObjectsHandler.ts +8 -3
- package/src/helpers/components/orbitComponent.ts +87 -68
- package/src/helpers/components/setupCacheInvalidation.ts +50 -23
- package/src/helpers/components/setupCacheOnResourceReady.ts +42 -23
- package/src/helpers/components/setupComponentSubscriptions.ts +10 -9
- package/src/helpers/components/setupOnSaveReset.ts +27 -5
- package/src/helpers/datas/checkValueInIntervalRecursive.ts +66 -0
- package/src/helpers/datas/dataBuilder.ts +4 -4
- package/src/helpers/datas/filterGenerator.ts +13 -10
- package/src/helpers/datas/filterObjectByDateAfter.ts +3 -3
- package/src/helpers/datas/filterObjectByDateInterval.ts +44 -0
- package/src/helpers/datas/filterObjectById.ts +7 -6
- package/src/helpers/datas/filterObjectByInterval.ts +6 -110
- package/src/helpers/datas/filterObjectByNamedValue.ts +35 -33
- package/src/helpers/datas/filterObjectByType.ts +3 -3
- package/src/helpers/datas/filterObjectByValue.ts +17 -16
- package/src/helpers/datas/sort.ts +50 -23
- package/src/helpers/index.ts +2 -0
- package/src/helpers/ui/formatDate.ts +14 -1
- package/src/helpers/utils/requestNavigation.ts +5 -2
- package/src/helpers/utils/uniq.ts +1 -1
- package/cypress/component/solid-boilerplate.cy.ts +0 -9
|
@@ -0,0 +1,508 @@
|
|
|
1
|
+
import { dataBuilder, recusiveRemovePath } from "@helpers/datas/dataBuilder";
|
|
2
|
+
|
|
3
|
+
describe("dataBuilder helper function", () => {
|
|
4
|
+
describe("Basic functionality", () => {
|
|
5
|
+
it("should clone the resource object", () => {
|
|
6
|
+
const resource = { name: "Alice", age: 30 };
|
|
7
|
+
const result = dataBuilder(resource);
|
|
8
|
+
expect(result).to.deep.equal(resource);
|
|
9
|
+
expect(result).to.not.equal(resource);
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
it("should remove specified paths", () => {
|
|
13
|
+
const resource = { name: "Alice", age: 30, email: "alice@example.com" };
|
|
14
|
+
const result = dataBuilder(resource, ["age"]);
|
|
15
|
+
expect(result).to.deep.equal({
|
|
16
|
+
name: "Alice",
|
|
17
|
+
email: "alice@example.com",
|
|
18
|
+
});
|
|
19
|
+
expect(result).to.not.have.property("age");
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
it("should replace specified properties", () => {
|
|
23
|
+
const resource = { name: "Alice", age: 30 };
|
|
24
|
+
const replacements = { age: 35, email: "alice@example.com" };
|
|
25
|
+
const result = dataBuilder(resource, [], replacements);
|
|
26
|
+
expect(result).to.deep.equal({
|
|
27
|
+
name: "Alice",
|
|
28
|
+
age: 35,
|
|
29
|
+
email: "alice@example.com",
|
|
30
|
+
});
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
it("should handle both removals and replacements (default order: remove then replace)", () => {
|
|
34
|
+
const resource = { name: "Alice", age: 30, email: "alice@example.com" };
|
|
35
|
+
const replacements = { email: "newemail@example.com" };
|
|
36
|
+
const result = dataBuilder(resource, ["age"], replacements);
|
|
37
|
+
expect(result).to.deep.equal({
|
|
38
|
+
name: "Alice",
|
|
39
|
+
email: "newemail@example.com",
|
|
40
|
+
});
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
it("should handle both removals and replacements with removeThenReplace=true", () => {
|
|
44
|
+
const resource = { name: "Alice", age: 30 };
|
|
45
|
+
const replacements = { email: "alice@example.com", age: 35 };
|
|
46
|
+
const result = dataBuilder(resource, ["age"], replacements, true);
|
|
47
|
+
expect(result).to.deep.equal({
|
|
48
|
+
name: "Alice",
|
|
49
|
+
email: "alice@example.com",
|
|
50
|
+
});
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
it("should not mutate the original resource", () => {
|
|
54
|
+
const resource = { name: "Alice", age: 30 };
|
|
55
|
+
const originalData = JSON.stringify(resource);
|
|
56
|
+
dataBuilder(resource, ["name"]);
|
|
57
|
+
expect(JSON.stringify(resource)).to.equal(originalData);
|
|
58
|
+
});
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
describe("recusiveRemovePath", () => {
|
|
62
|
+
it("should remove top-level property", () => {
|
|
63
|
+
const obj = { name: "Alice", age: 30 };
|
|
64
|
+
recusiveRemovePath(obj, ["age"]);
|
|
65
|
+
expect(obj).to.deep.equal({ name: "Alice" });
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
it("should remove nested property", () => {
|
|
69
|
+
const obj = {
|
|
70
|
+
name: "Alice",
|
|
71
|
+
profile: { age: 30, email: "alice@example.com" },
|
|
72
|
+
};
|
|
73
|
+
recusiveRemovePath(obj, ["profile", "age"]);
|
|
74
|
+
expect(obj.profile).to.deep.equal({ email: "alice@example.com" });
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
it("should remove deeply nested property", () => {
|
|
78
|
+
const obj = {
|
|
79
|
+
name: "Alice",
|
|
80
|
+
data: { profile: { settings: { theme: "dark" } } },
|
|
81
|
+
};
|
|
82
|
+
recusiveRemovePath(obj, ["data", "profile", "settings", "theme"]);
|
|
83
|
+
expect(obj.data.profile.settings).to.deep.equal({});
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
it("should handle non-existent paths", () => {
|
|
87
|
+
const obj = { name: "Alice", age: 30 };
|
|
88
|
+
const original = JSON.stringify(obj);
|
|
89
|
+
recusiveRemovePath(obj, ["nonexistent", "property"]);
|
|
90
|
+
expect(JSON.stringify(obj)).to.equal(original);
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
it("should handle undefined object", () => {
|
|
94
|
+
const obj = undefined as any;
|
|
95
|
+
recusiveRemovePath(obj, ["name"]);
|
|
96
|
+
expect(obj).to.be.undefined;
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
it("should handle null object", () => {
|
|
100
|
+
const obj = null as any;
|
|
101
|
+
recusiveRemovePath(obj, ["name"]);
|
|
102
|
+
expect(obj).to.be.null;
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
it("should handle empty path array", () => {
|
|
106
|
+
const obj = { name: "Alice", age: 30 };
|
|
107
|
+
const original = JSON.stringify(obj);
|
|
108
|
+
recusiveRemovePath(obj, []);
|
|
109
|
+
expect(JSON.stringify(obj)).to.equal(original);
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
it("should not mutate path array", () => {
|
|
113
|
+
const obj = { name: "Alice", profile: { age: 30 } };
|
|
114
|
+
const path = ["profile", "age"];
|
|
115
|
+
const originalPath = [...path];
|
|
116
|
+
recusiveRemovePath(obj, path);
|
|
117
|
+
expect(path).to.deep.equal([]);
|
|
118
|
+
});
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
describe("Path removal", () => {
|
|
122
|
+
it("should remove multiple paths", () => {
|
|
123
|
+
const resource = {
|
|
124
|
+
name: "Alice",
|
|
125
|
+
age: 30,
|
|
126
|
+
email: "alice@example.com",
|
|
127
|
+
city: "Paris",
|
|
128
|
+
};
|
|
129
|
+
const result = dataBuilder(resource, ["age", "email"]);
|
|
130
|
+
expect(result).to.deep.equal({ name: "Alice", city: "Paris" });
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
it("should handle nested paths using dot notation", () => {
|
|
134
|
+
const resource = {
|
|
135
|
+
name: "Alice",
|
|
136
|
+
profile: {
|
|
137
|
+
age: 30,
|
|
138
|
+
email: "alice@example.com",
|
|
139
|
+
address: {
|
|
140
|
+
city: "Paris",
|
|
141
|
+
country: "France",
|
|
142
|
+
},
|
|
143
|
+
},
|
|
144
|
+
};
|
|
145
|
+
const result = dataBuilder(resource, [
|
|
146
|
+
"profile.age",
|
|
147
|
+
"profile.address.city",
|
|
148
|
+
]);
|
|
149
|
+
expect(result).to.deep.equal({
|
|
150
|
+
name: "Alice",
|
|
151
|
+
profile: {
|
|
152
|
+
email: "alice@example.com",
|
|
153
|
+
address: {
|
|
154
|
+
country: "France",
|
|
155
|
+
},
|
|
156
|
+
},
|
|
157
|
+
});
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
it("should handle paths with same prefix", () => {
|
|
161
|
+
const resource = {
|
|
162
|
+
name: "Alice",
|
|
163
|
+
profile: {
|
|
164
|
+
age: 30,
|
|
165
|
+
address: {
|
|
166
|
+
city: "Paris",
|
|
167
|
+
country: "France",
|
|
168
|
+
},
|
|
169
|
+
},
|
|
170
|
+
};
|
|
171
|
+
const result = dataBuilder(resource, ["profile.age", "profile.address"]);
|
|
172
|
+
expect(result).to.deep.equal({
|
|
173
|
+
name: "Alice",
|
|
174
|
+
profile: {},
|
|
175
|
+
});
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
it("should remove entire nested object", () => {
|
|
179
|
+
const resource = {
|
|
180
|
+
name: "Alice",
|
|
181
|
+
profile: {
|
|
182
|
+
age: 30,
|
|
183
|
+
email: "alice@example.com",
|
|
184
|
+
},
|
|
185
|
+
};
|
|
186
|
+
const result = dataBuilder(resource, ["profile"]);
|
|
187
|
+
expect(result).to.deep.equal({ name: "Alice" });
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
it("should handle removing from nested arrays", () => {
|
|
191
|
+
const resource = {
|
|
192
|
+
name: "Alice",
|
|
193
|
+
items: [
|
|
194
|
+
{ id: 1, name: "Item 1" },
|
|
195
|
+
{ id: 2, name: "Item 2" },
|
|
196
|
+
],
|
|
197
|
+
};
|
|
198
|
+
const result = dataBuilder(resource, ["items"]);
|
|
199
|
+
expect(result).to.deep.equal({ name: "Alice" });
|
|
200
|
+
});
|
|
201
|
+
|
|
202
|
+
it("should handle removing property that does not exist", () => {
|
|
203
|
+
const resource = { name: "Alice", age: 30 };
|
|
204
|
+
const result = dataBuilder(resource, ["nonexistent"]);
|
|
205
|
+
expect(result).to.deep.equal({ name: "Alice", age: 30 });
|
|
206
|
+
});
|
|
207
|
+
|
|
208
|
+
it("should handle removing deeply nested non-existent property", () => {
|
|
209
|
+
const resource = { name: "Alice", age: 30 };
|
|
210
|
+
const result = dataBuilder(resource, ["profile", "age"]);
|
|
211
|
+
expect(result).to.deep.equal({ name: "Alice" });
|
|
212
|
+
});
|
|
213
|
+
});
|
|
214
|
+
|
|
215
|
+
describe("Replacements", () => {
|
|
216
|
+
it("should add new properties", () => {
|
|
217
|
+
const resource = { name: "Alice" };
|
|
218
|
+
const replacements = { age: 30, email: "alice@example.com" };
|
|
219
|
+
const result = dataBuilder(resource, [], replacements);
|
|
220
|
+
expect(result).to.deep.equal({
|
|
221
|
+
name: "Alice",
|
|
222
|
+
age: 30,
|
|
223
|
+
email: "alice@example.com",
|
|
224
|
+
});
|
|
225
|
+
});
|
|
226
|
+
|
|
227
|
+
it("should overwrite existing properties", () => {
|
|
228
|
+
const resource = { name: "Alice", age: 30 };
|
|
229
|
+
const replacements = { age: 35 };
|
|
230
|
+
const result = dataBuilder(resource, [], replacements);
|
|
231
|
+
expect(result).to.deep.equal({ name: "Alice", age: 35 });
|
|
232
|
+
});
|
|
233
|
+
|
|
234
|
+
it("should handle complex replacement values", () => {
|
|
235
|
+
const resource = { name: "Alice" };
|
|
236
|
+
const replacements = {
|
|
237
|
+
profile: { age: 30, email: "alice@example.com" },
|
|
238
|
+
tags: ["engineer", "developer"],
|
|
239
|
+
};
|
|
240
|
+
const result = dataBuilder(resource, [], replacements);
|
|
241
|
+
expect(result).to.deep.equal({
|
|
242
|
+
name: "Alice",
|
|
243
|
+
profile: { age: 30, email: "alice@example.com" },
|
|
244
|
+
tags: ["engineer", "developer"],
|
|
245
|
+
});
|
|
246
|
+
});
|
|
247
|
+
|
|
248
|
+
it("should handle null replacements", () => {
|
|
249
|
+
const resource = { name: "Alice", age: 30 };
|
|
250
|
+
const replacements = { age: null };
|
|
251
|
+
const result = dataBuilder(resource, [], replacements);
|
|
252
|
+
expect(result).to.deep.equal({ name: "Alice", age: null });
|
|
253
|
+
});
|
|
254
|
+
|
|
255
|
+
it("should handle undefined replacements", () => {
|
|
256
|
+
const resource = { name: "Alice", age: 30 };
|
|
257
|
+
const replacements = { age: undefined };
|
|
258
|
+
const result = dataBuilder(resource, [], replacements);
|
|
259
|
+
expect(result).to.deep.equal({ name: "Alice", age: undefined });
|
|
260
|
+
});
|
|
261
|
+
|
|
262
|
+
it("should handle empty replacements object", () => {
|
|
263
|
+
const resource = { name: "Alice", age: 30 };
|
|
264
|
+
const result = dataBuilder(resource, [], {});
|
|
265
|
+
expect(result).to.deep.equal({ name: "Alice", age: 30 });
|
|
266
|
+
});
|
|
267
|
+
});
|
|
268
|
+
|
|
269
|
+
describe("removeThenReplace flag", () => {
|
|
270
|
+
it("should remove first, then replace when removeThenReplace=false (default)", () => {
|
|
271
|
+
const resource = { name: "Alice", age: 30 };
|
|
272
|
+
const replacements = { age: 35 };
|
|
273
|
+
const result = dataBuilder(resource, ["age"], replacements, false);
|
|
274
|
+
expect(result).to.deep.equal({ name: "Alice", age: 35 });
|
|
275
|
+
});
|
|
276
|
+
|
|
277
|
+
it("should replace first, then remove when removeThenReplace=true", () => {
|
|
278
|
+
const resource = { name: "Alice", age: 30 };
|
|
279
|
+
const replacements = { age: 35 };
|
|
280
|
+
const result = dataBuilder(resource, ["age"], replacements, true);
|
|
281
|
+
expect(result).to.deep.equal({ name: "Alice" });
|
|
282
|
+
});
|
|
283
|
+
|
|
284
|
+
it("should replace nested object then remove when removeThenReplace=true", () => {
|
|
285
|
+
const resource = { name: "Alice", profile: { age: 30 } };
|
|
286
|
+
const replacements = { profile: { age: 35, email: "alice@example.com" } };
|
|
287
|
+
const result = dataBuilder(resource, ["profile.age"], replacements, true);
|
|
288
|
+
expect(result).to.deep.equal({
|
|
289
|
+
name: "Alice",
|
|
290
|
+
profile: { email: "alice@example.com" },
|
|
291
|
+
});
|
|
292
|
+
});
|
|
293
|
+
|
|
294
|
+
it("should handle multiple paths with removeThenReplace=true", () => {
|
|
295
|
+
const resource = { name: "Alice", age: 30, email: "old@example.com" };
|
|
296
|
+
const replacements = { age: 35, email: "new@example.com" };
|
|
297
|
+
const result = dataBuilder(
|
|
298
|
+
resource,
|
|
299
|
+
["age", "email"],
|
|
300
|
+
replacements,
|
|
301
|
+
true,
|
|
302
|
+
);
|
|
303
|
+
expect(result).to.deep.equal({ name: "Alice" });
|
|
304
|
+
});
|
|
305
|
+
});
|
|
306
|
+
|
|
307
|
+
describe("Edge cases", () => {
|
|
308
|
+
it("should handle empty resource", () => {
|
|
309
|
+
const resource = {};
|
|
310
|
+
const result = dataBuilder(resource);
|
|
311
|
+
expect(result).to.deep.equal({});
|
|
312
|
+
});
|
|
313
|
+
|
|
314
|
+
it("should handle null resource", () => {
|
|
315
|
+
const resource = null as any;
|
|
316
|
+
const result = dataBuilder(resource);
|
|
317
|
+
expect(result).to.be.null;
|
|
318
|
+
});
|
|
319
|
+
|
|
320
|
+
it("should handle undefined resource", () => {
|
|
321
|
+
const resource = undefined as any;
|
|
322
|
+
const result = dataBuilder(resource);
|
|
323
|
+
expect(result).to.be.undefined;
|
|
324
|
+
});
|
|
325
|
+
|
|
326
|
+
it("should handle empty path array", () => {
|
|
327
|
+
const resource = { name: "Alice", age: 30 };
|
|
328
|
+
const result = dataBuilder(resource, [], {});
|
|
329
|
+
expect(result).to.deep.equal({ name: "Alice", age: 30 });
|
|
330
|
+
});
|
|
331
|
+
|
|
332
|
+
it("should handle resource with nested objects", () => {
|
|
333
|
+
const resource = {
|
|
334
|
+
name: "Alice",
|
|
335
|
+
profile: {
|
|
336
|
+
age: 30,
|
|
337
|
+
address: {
|
|
338
|
+
city: "Paris",
|
|
339
|
+
country: "France",
|
|
340
|
+
},
|
|
341
|
+
},
|
|
342
|
+
};
|
|
343
|
+
const result = dataBuilder(resource);
|
|
344
|
+
expect(result).to.deep.equal(JSON.parse(JSON.stringify(resource)));
|
|
345
|
+
});
|
|
346
|
+
|
|
347
|
+
it("should handle resource with arrays", () => {
|
|
348
|
+
const resource = {
|
|
349
|
+
name: "Alice",
|
|
350
|
+
tags: ["engineer", "developer"],
|
|
351
|
+
items: [{ id: 1 }, { id: 2 }],
|
|
352
|
+
};
|
|
353
|
+
const result = dataBuilder(resource);
|
|
354
|
+
expect(result).to.deep.equal(JSON.parse(JSON.stringify(resource)));
|
|
355
|
+
});
|
|
356
|
+
|
|
357
|
+
it("should handle resource with mixed types", () => {
|
|
358
|
+
const resource = {
|
|
359
|
+
name: "Alice",
|
|
360
|
+
age: 30,
|
|
361
|
+
active: true,
|
|
362
|
+
score: 95.5,
|
|
363
|
+
data: null,
|
|
364
|
+
};
|
|
365
|
+
const result = dataBuilder(resource);
|
|
366
|
+
expect(result).to.deep.equal(JSON.parse(JSON.stringify(resource)));
|
|
367
|
+
});
|
|
368
|
+
|
|
369
|
+
it("should handle circular references by using structuredClone", () => {
|
|
370
|
+
const resource: any = { name: "Alice" };
|
|
371
|
+
resource.self = resource;
|
|
372
|
+
const result = dataBuilder(resource);
|
|
373
|
+
expect(result.name).to.equal("Alice");
|
|
374
|
+
expect(result.self).to.equal(result);
|
|
375
|
+
});
|
|
376
|
+
});
|
|
377
|
+
|
|
378
|
+
describe("Complex scenarios", () => {
|
|
379
|
+
it("should handle complex nested removal and replacement", () => {
|
|
380
|
+
const resource = {
|
|
381
|
+
id: 1,
|
|
382
|
+
name: "Alice",
|
|
383
|
+
metadata: {
|
|
384
|
+
createdAt: "2023-01-01",
|
|
385
|
+
updatedAt: "2023-02-01",
|
|
386
|
+
createdBy: { id: 10, name: "Admin" },
|
|
387
|
+
},
|
|
388
|
+
settings: {
|
|
389
|
+
theme: "dark",
|
|
390
|
+
notifications: true,
|
|
391
|
+
},
|
|
392
|
+
};
|
|
393
|
+
const replacements = {
|
|
394
|
+
id: 2,
|
|
395
|
+
metadata: { createdAt: "2023-03-01" },
|
|
396
|
+
};
|
|
397
|
+
const result = dataBuilder(
|
|
398
|
+
resource,
|
|
399
|
+
["metadata.updatedBy", "settings.theme"],
|
|
400
|
+
replacements,
|
|
401
|
+
false,
|
|
402
|
+
);
|
|
403
|
+
expect(result).to.deep.equal({
|
|
404
|
+
id: 2,
|
|
405
|
+
name: "Alice",
|
|
406
|
+
metadata: {
|
|
407
|
+
createdAt: "2023-03-01",
|
|
408
|
+
},
|
|
409
|
+
settings: {
|
|
410
|
+
notifications: true,
|
|
411
|
+
},
|
|
412
|
+
});
|
|
413
|
+
});
|
|
414
|
+
|
|
415
|
+
it("should remove path and replace with different structure", () => {
|
|
416
|
+
const resource = {
|
|
417
|
+
name: "Alice",
|
|
418
|
+
profile: { age: 30, email: "old@example.com" },
|
|
419
|
+
};
|
|
420
|
+
const replacements = {
|
|
421
|
+
profile: { name: "Alice Profile", bio: "Software engineer" },
|
|
422
|
+
};
|
|
423
|
+
const result = dataBuilder(
|
|
424
|
+
resource,
|
|
425
|
+
["profile.age"],
|
|
426
|
+
replacements,
|
|
427
|
+
false,
|
|
428
|
+
);
|
|
429
|
+
expect(result).to.deep.equal({
|
|
430
|
+
name: "Alice",
|
|
431
|
+
profile: {
|
|
432
|
+
name: "Alice Profile",
|
|
433
|
+
bio: "Software engineer",
|
|
434
|
+
},
|
|
435
|
+
});
|
|
436
|
+
});
|
|
437
|
+
});
|
|
438
|
+
|
|
439
|
+
describe("Real-world scenarios", () => {
|
|
440
|
+
it("should prepare resource for API request by removing internal fields", () => {
|
|
441
|
+
const resource = {
|
|
442
|
+
"@id": "/resource/1",
|
|
443
|
+
"@type": "User",
|
|
444
|
+
name: "Alice",
|
|
445
|
+
_internalId: 123,
|
|
446
|
+
_metadata: { created: true },
|
|
447
|
+
};
|
|
448
|
+
const result = dataBuilder(resource, ["_internalId", "_metadata"]);
|
|
449
|
+
expect(result).to.deep.equal({
|
|
450
|
+
"@id": "/resource/1",
|
|
451
|
+
"@type": "User",
|
|
452
|
+
name: "Alice",
|
|
453
|
+
});
|
|
454
|
+
});
|
|
455
|
+
|
|
456
|
+
it("should sanitize user data for response", () => {
|
|
457
|
+
const user = {
|
|
458
|
+
id: 1,
|
|
459
|
+
name: "Alice",
|
|
460
|
+
email: "alice@example.com",
|
|
461
|
+
password: "secret123",
|
|
462
|
+
salt: "abc123",
|
|
463
|
+
};
|
|
464
|
+
const result = dataBuilder(user, ["password", "salt"]);
|
|
465
|
+
expect(result).to.deep.equal({
|
|
466
|
+
id: 1,
|
|
467
|
+
name: "Alice",
|
|
468
|
+
email: "alice@example.com",
|
|
469
|
+
});
|
|
470
|
+
});
|
|
471
|
+
|
|
472
|
+
it("should update partial data while preserving other fields", () => {
|
|
473
|
+
const resource = {
|
|
474
|
+
id: 1,
|
|
475
|
+
name: "Alice",
|
|
476
|
+
age: 30,
|
|
477
|
+
email: "alice@example.com",
|
|
478
|
+
};
|
|
479
|
+
const updates = { age: 31, email: "newalice@example.com" };
|
|
480
|
+
const result = dataBuilder(resource, [], updates);
|
|
481
|
+
expect(result).to.deep.equal({
|
|
482
|
+
id: 1,
|
|
483
|
+
name: "Alice",
|
|
484
|
+
age: 31,
|
|
485
|
+
email: "newalice@example.com",
|
|
486
|
+
});
|
|
487
|
+
});
|
|
488
|
+
|
|
489
|
+
it("should clone and prepare resource for creation", () => {
|
|
490
|
+
const template = {
|
|
491
|
+
"@type": "Task",
|
|
492
|
+
status: "pending",
|
|
493
|
+
priority: "medium",
|
|
494
|
+
};
|
|
495
|
+
const newResource = dataBuilder(template, [], {
|
|
496
|
+
name: "New Task",
|
|
497
|
+
"@id": "",
|
|
498
|
+
});
|
|
499
|
+
expect(newResource).to.deep.equal({
|
|
500
|
+
"@type": "Task",
|
|
501
|
+
status: "pending",
|
|
502
|
+
priority: "medium",
|
|
503
|
+
name: "New Task",
|
|
504
|
+
"@id": "",
|
|
505
|
+
});
|
|
506
|
+
});
|
|
507
|
+
});
|
|
508
|
+
});
|