@startinblox/components-ds4go 2.2.4 → 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.
Files changed (52) hide show
  1. package/.gitlab-ci.yml +8 -2
  2. package/AGENTS.md +516 -0
  3. package/cypress/component/no-component-test.cy.ts +9 -0
  4. package/cypress/e2e/helpers/components/setupCacheInvalidation.cy.ts +512 -0
  5. package/cypress/e2e/helpers/components/setupCacheOnResourceReady.cy.ts +483 -0
  6. package/cypress/e2e/helpers/components/setupComponentSubscriptions.cy.ts +239 -0
  7. package/cypress/e2e/helpers/components/setupOnSaveReset.cy.ts +380 -0
  8. package/cypress/e2e/helpers/datas/checkValueInIntervalRecursive.cy.ts +563 -0
  9. package/cypress/e2e/helpers/datas/dataBuilder.cy.ts +508 -0
  10. package/cypress/e2e/helpers/datas/filterGenerator.cy.ts +285 -0
  11. package/cypress/e2e/helpers/datas/filterObjectByDateAfter.cy.ts +389 -0
  12. package/cypress/e2e/helpers/datas/filterObjectByDateInterval.cy.ts +613 -0
  13. package/cypress/e2e/helpers/datas/filterObjectById.cy.ts +276 -0
  14. package/cypress/e2e/helpers/datas/filterObjectByInterval.cy.ts +237 -0
  15. package/cypress/e2e/helpers/datas/filterObjectByNamedValue.cy.ts +299 -0
  16. package/cypress/e2e/helpers/datas/filterObjectByType.cy.ts +307 -0
  17. package/cypress/e2e/helpers/datas/filterObjectByValue.cy.ts +375 -0
  18. package/cypress/e2e/helpers/datas/sort.cy.ts +293 -0
  19. package/cypress/e2e/helpers/ui/formatDate.cy.ts +233 -0
  20. package/cypress/e2e/helpers/utils/requestNavigation.cy.ts +257 -0
  21. package/cypress/e2e/helpers/utils/uniq.cy.ts +160 -0
  22. package/cypress/support/e2e.ts +1 -0
  23. package/cypress.config.ts +2 -0
  24. package/dist/index.js +932 -734
  25. package/locales/en.xlf +75 -0
  26. package/package.json +10 -10
  27. package/src/components/solid-boilerplate.ts +76 -0
  28. package/src/components/solid-fact-bundle-creation.ts +202 -59
  29. package/src/helpers/components/componentObjectHandler.ts +5 -7
  30. package/src/helpers/components/componentObjectsHandler.ts +8 -3
  31. package/src/helpers/components/orbitComponent.ts +87 -68
  32. package/src/helpers/components/setupCacheInvalidation.ts +50 -23
  33. package/src/helpers/components/setupCacheOnResourceReady.ts +42 -23
  34. package/src/helpers/components/setupComponentSubscriptions.ts +10 -9
  35. package/src/helpers/components/setupOnSaveReset.ts +27 -5
  36. package/src/helpers/datas/checkValueInIntervalRecursive.ts +66 -0
  37. package/src/helpers/datas/dataBuilder.ts +4 -4
  38. package/src/helpers/datas/filterGenerator.ts +13 -10
  39. package/src/helpers/datas/filterObjectByDateAfter.ts +3 -3
  40. package/src/helpers/datas/filterObjectByDateInterval.ts +44 -0
  41. package/src/helpers/datas/filterObjectById.ts +7 -6
  42. package/src/helpers/datas/filterObjectByInterval.ts +6 -110
  43. package/src/helpers/datas/filterObjectByNamedValue.ts +35 -33
  44. package/src/helpers/datas/filterObjectByType.ts +3 -3
  45. package/src/helpers/datas/filterObjectByValue.ts +17 -16
  46. package/src/helpers/datas/sort.ts +50 -23
  47. package/src/helpers/index.ts +2 -0
  48. package/src/helpers/ui/formatDate.ts +14 -1
  49. package/src/helpers/utils/requestNavigation.ts +5 -2
  50. package/src/helpers/utils/uniq.ts +1 -1
  51. package/src/styles/fact-bundle-creation.scss +102 -0
  52. package/cypress/component/solid-boilerplate.cy.ts +0 -9
@@ -0,0 +1,276 @@
1
+ import filterObjectById from "@helpers/datas/filterObjectById";
2
+
3
+ describe("filterObjectById helper function", () => {
4
+ describe("Basic functionality", () => {
5
+ it("should filter objects by @id property", () => {
6
+ const objects = [
7
+ { name: "Resource 1", resource: { "@id": "/resource/1" } },
8
+ { name: "Resource 2", resource: { "@id": "/resource/2" } },
9
+ { name: "Resource 3", resource: { "@id": "/resource/3" } },
10
+ ];
11
+ const result = filterObjectById(objects, "resource", "/resource/2");
12
+ expect(result).to.have.length(1);
13
+ expect(result[0].name).to.equal("Resource 2");
14
+ });
15
+
16
+ it("should return all objects when propName is empty", () => {
17
+ const objects = [
18
+ { "@id": "/resource/1", name: "Resource 1" },
19
+ { "@id": "/resource/2", name: "Resource 2" },
20
+ ];
21
+ const result = filterObjectById(objects, "", "/resource/2");
22
+ expect(result).to.have.length(2);
23
+ });
24
+
25
+ it("should return all objects when targetId is empty", () => {
26
+ const objects = [
27
+ { "@id": "/resource/1", name: "Resource 1" },
28
+ { "@id": "/resource/2", name: "Resource 2" },
29
+ ];
30
+ const result = filterObjectById(objects, "@id", "");
31
+ expect(result).to.have.length(2);
32
+ });
33
+
34
+ it("should return empty array when no match found", () => {
35
+ const objects = [
36
+ { "@id": "/resource/1", name: "Resource 1" },
37
+ { "@id": "/resource/2", name: "Resource 2" },
38
+ ];
39
+ const result = filterObjectById(objects, "@id", "/resource/99");
40
+ expect(result).to.have.length(0);
41
+ });
42
+ });
43
+
44
+ describe("Nested property handling", () => {
45
+ it("should filter by nested property using dot notation", () => {
46
+ const objects = [
47
+ { name: "Alice", team: { "@id": "/team/1", name: "Engineering" } },
48
+ { name: "Bob", team: { "@id": "/team/2", name: "Marketing" } },
49
+ { name: "Charlie", team: { "@id": "/team/1", name: "Engineering" } },
50
+ ];
51
+ const result = filterObjectById(objects, "team", "/team/1");
52
+ expect(result).to.have.length(2);
53
+ expect(result.map((r) => r.name)).to.deep.equal(["Alice", "Charlie"]);
54
+ });
55
+
56
+ it("should filter by deeply nested property", () => {
57
+ const objects = [
58
+ {
59
+ name: "Alice",
60
+ user: { profile: { organization: { "@id": "/org/1" } } },
61
+ },
62
+ {
63
+ name: "Bob",
64
+ user: { profile: { organization: { "@id": "/org/2" } } },
65
+ },
66
+ ];
67
+ const result = filterObjectById(
68
+ objects,
69
+ "user.profile.organization",
70
+ "/org/1",
71
+ );
72
+ expect(result).to.have.length(1);
73
+ expect(result[0].name).to.equal("Alice");
74
+ });
75
+
76
+ it("should return empty array when nested property does not exist", () => {
77
+ const objects = [
78
+ { name: "Alice", team: { "@id": "/team/1" } },
79
+ { name: "Bob" },
80
+ ];
81
+ const result = filterObjectById(
82
+ objects,
83
+ "nonexistent.property",
84
+ "/value",
85
+ );
86
+ expect(result).to.have.length(0);
87
+ });
88
+ });
89
+
90
+ describe("Array property handling", () => {
91
+ it("should filter objects where property is an array containing target @id", () => {
92
+ const objects = [
93
+ {
94
+ name: "Project 1",
95
+ members: [{ "@id": "/user/1" }, { "@id": "/user/2" }],
96
+ },
97
+ { name: "Project 2", members: [{ "@id": "/user/3" }] },
98
+ {
99
+ name: "Project 3",
100
+ members: [{ "@id": "/user/1" }, { "@id": "/user/4" }],
101
+ },
102
+ ];
103
+ const result = filterObjectById(objects, "members", "/user/1");
104
+ expect(result).to.have.length(2);
105
+ expect(result.map((r) => r.name)).to.deep.equal([
106
+ "Project 1",
107
+ "Project 3",
108
+ ]);
109
+ });
110
+
111
+ it("should handle nested arrays", () => {
112
+ const objects = [
113
+ { name: "Project 1", data: { members: [{ "@id": "/user/1" }] } },
114
+ { name: "Project 2", data: { members: [{ "@id": "/user/2" }] } },
115
+ ];
116
+ const result = filterObjectById(objects, "data.members", "/user/1");
117
+ expect(result).to.have.length(1);
118
+ expect(result[0].name).to.equal("Project 1");
119
+ });
120
+ });
121
+
122
+ describe("Edge cases", () => {
123
+ it("should handle empty array", () => {
124
+ const result = filterObjectById([], "@id", "/resource/1");
125
+ expect(result).to.deep.equal([]);
126
+ });
127
+
128
+ it("should handle objects without @id property", () => {
129
+ const objects = [{ name: "Resource 1" }, { name: "Resource 2" }];
130
+ const result = filterObjectById(objects, "@id", "/resource/1");
131
+ expect(result).to.have.length(0);
132
+ });
133
+
134
+ it("should handle objects with null @id", () => {
135
+ const objects = [
136
+ { name: "Resource 1", ref: null },
137
+ { name: "Resource 2", ref: { "@id": "/resource/2" } },
138
+ ];
139
+ const result = filterObjectById(objects, "ref", "/resource/2");
140
+ expect(result).to.have.length(1);
141
+ expect(result[0].name).to.equal("Resource 2");
142
+ });
143
+
144
+ it("should handle objects with undefined property", () => {
145
+ const objects = [
146
+ { name: "Resource 1" },
147
+ { name: "Resource 2", ref: { "@id": "/resource/2" } },
148
+ ];
149
+ const result = filterObjectById(objects, "ref", "/resource/2");
150
+ expect(result).to.have.length(1);
151
+ expect(result[0].name).to.equal("Resource 2");
152
+ });
153
+
154
+ it("should handle objects with empty array property", () => {
155
+ const objects = [
156
+ { name: "Project 1", members: [] },
157
+ { name: "Project 2", members: [{ "@id": "/user/1" }] },
158
+ ];
159
+ const result = filterObjectById(objects, "members", "/user/1");
160
+ expect(result).to.have.length(1);
161
+ expect(result[0].name).to.equal("Project 2");
162
+ });
163
+
164
+ it("should handle array with non-object elements", () => {
165
+ const objects = [
166
+ { name: "Project 1", tags: ["tag1", "tag2"] },
167
+ { name: "Project 2", tags: ["tag3"] },
168
+ ];
169
+ const result = filterObjectById(objects, "tags", "/nonexistent");
170
+ expect(result).to.have.length(0);
171
+ });
172
+ });
173
+
174
+ describe("Mixed scenarios", () => {
175
+ it("should handle mix of objects with and without @id in arrays", () => {
176
+ const objects = [
177
+ {
178
+ name: "Project 1",
179
+ members: [{ "@id": "/user/1" }, { name: "Anonymous" }],
180
+ },
181
+ { name: "Project 2", members: [{ "@id": "/user/2" }] },
182
+ ];
183
+ const result = filterObjectById(objects, "members", "/user/1");
184
+ expect(result).to.have.length(1);
185
+ expect(result[0].name).to.equal("Project 1");
186
+ });
187
+
188
+ it("should handle nested object with @id at leaf", () => {
189
+ const objects = [
190
+ { name: "Alice", profile: { user: { "@id": "/user/1" } } },
191
+ { name: "Bob", profile: { user: { "@id": "/user/2" } } },
192
+ ];
193
+ const result = filterObjectById(objects, "profile.user", "/user/1");
194
+ expect(result).to.have.length(1);
195
+ expect(result[0].name).to.equal("Alice");
196
+ });
197
+
198
+ it("should return multiple matches when multiple objects have same @id", () => {
199
+ const objects = [
200
+ { name: "Project 1", team: { "@id": "/team/1" } },
201
+ { name: "Project 2", team: { "@id": "/team/1" } },
202
+ { name: "Project 3", team: { "@id": "/team/2" } },
203
+ ];
204
+ const result = filterObjectById(objects, "team", "/team/1");
205
+ expect(result).to.have.length(2);
206
+ expect(result.map((r) => r.name)).to.deep.equal([
207
+ "Project 1",
208
+ "Project 2",
209
+ ]);
210
+ });
211
+ });
212
+
213
+ describe("Invalid property paths", () => {
214
+ it("should handle malformed dot notation", () => {
215
+ const objects = [{ name: "Alice", team: { "@id": "/team/1" } }];
216
+ const result = filterObjectById(objects, "team..@id", "/team/1");
217
+ expect(result).to.have.length(0);
218
+ });
219
+
220
+ it("should handle trailing dot in path", () => {
221
+ const objects = [{ name: "Alice", team: { "@id": "/team/1" } }];
222
+ const result = filterObjectById(objects, "team.", "/team/1");
223
+ expect(result).to.have.length(0);
224
+ });
225
+
226
+ it("should handle leading dot in path", () => {
227
+ const objects = [{ name: "Alice", team: { "@id": "/team/1" } }];
228
+ const result = filterObjectById(objects, ".team.@id", "/team/1");
229
+ expect(result).to.have.length(0);
230
+ });
231
+ });
232
+
233
+ describe("Real-world scenarios", () => {
234
+ it("should filter projects by organization ID", () => {
235
+ const projects = [
236
+ {
237
+ "@id": "/project/1",
238
+ name: "Website",
239
+ organization: { "@id": "/org/1", name: "Acme" },
240
+ },
241
+ {
242
+ "@id": "/project/2",
243
+ name: "App",
244
+ organization: { "@id": "/org/2", name: "Beta" },
245
+ },
246
+ {
247
+ "@id": "/project/3",
248
+ name: "API",
249
+ organization: { "@id": "/org/1", name: "Acme" },
250
+ },
251
+ ];
252
+ const result = filterObjectById(projects, "organization", "/org/1");
253
+ expect(result).to.have.length(2);
254
+ expect(result.map((p) => p.name)).to.deep.equal(["Website", "API"]);
255
+ });
256
+
257
+ it("should filter tasks by assignee", () => {
258
+ const tasks = [
259
+ {
260
+ "@id": "/task/1",
261
+ title: "Design",
262
+ assignees: [{ "@id": "/user/1" }, { "@id": "/user/2" }],
263
+ },
264
+ {
265
+ "@id": "/task/2",
266
+ title: "Develop",
267
+ assignees: [{ "@id": "/user/3" }],
268
+ },
269
+ { "@id": "/task/3", title: "Test", assignees: [{ "@id": "/user/1" }] },
270
+ ];
271
+ const result = filterObjectById(tasks, "assignees", "/user/1");
272
+ expect(result).to.have.length(2);
273
+ expect(result.map((t) => t.title)).to.deep.equal(["Design", "Test"]);
274
+ });
275
+ });
276
+ });
@@ -0,0 +1,237 @@
1
+ import filterObjectByInterval from "@helpers/datas/filterObjectByInterval";
2
+
3
+ describe("filterObjectByInterval helper function", () => {
4
+ describe("Numeric intervals", () => {
5
+ it("should filter objects by numeric property within interval", () => {
6
+ const objects = [
7
+ { name: "Item 1", value: 5 },
8
+ { name: "Item 2", value: 10 },
9
+ { name: "Item 3", value: 15 },
10
+ ];
11
+ const result = filterObjectByInterval(objects, "value", "8/12");
12
+ expect(result).to.have.length(1);
13
+ expect(result[0].name).to.equal("Item 2");
14
+ });
15
+
16
+ it("should include objects with value equal to start of interval", () => {
17
+ const objects = [
18
+ { name: "Item 1", value: 5 },
19
+ { name: "Item 2", value: 10 },
20
+ ];
21
+ const result = filterObjectByInterval(objects, "value", "5/10");
22
+ expect(result).to.have.length(2);
23
+ });
24
+
25
+ it("should include objects with value equal to end of interval", () => {
26
+ const objects = [
27
+ { name: "Item 1", value: 10 },
28
+ { name: "Item 2", value: 15 },
29
+ ];
30
+ const result = filterObjectByInterval(objects, "value", "5/10");
31
+ expect(result).to.have.length(1);
32
+ expect(result[0].name).to.equal("Item 1");
33
+ });
34
+
35
+ it("should return all objects when propName is empty", () => {
36
+ const objects = [
37
+ { name: "Item 1", value: 5 },
38
+ { name: "Item 2", value: 10 },
39
+ ];
40
+ const result = filterObjectByInterval(objects, "", "5/10");
41
+ expect(result).to.have.length(2);
42
+ });
43
+
44
+ it("should return all objects when interval is empty", () => {
45
+ const objects = [
46
+ { name: "Item 1", value: 5 },
47
+ { name: "Item 2", value: 10 },
48
+ ];
49
+ const result = filterObjectByInterval(objects, "value", "");
50
+ expect(result).to.have.length(2);
51
+ });
52
+
53
+ it("should return all objects when interval is not a string", () => {
54
+ const objects = [
55
+ { name: "Item 1", value: 5 },
56
+ { name: "Item 2", value: 10 },
57
+ ];
58
+ const result = filterObjectByInterval(objects, "value", null as any);
59
+ expect(result).to.have.length(2);
60
+ });
61
+
62
+ it("should return all objects when interval contains non-numbers", () => {
63
+ const objects = [
64
+ { name: "Item 1", value: 5 },
65
+ { name: "Item 2", value: 10 },
66
+ ];
67
+ const result = filterObjectByInterval(objects, "value", "abc/xyz");
68
+ expect(result).to.have.length(2);
69
+ });
70
+
71
+ it("should return all objects when start > end in interval", () => {
72
+ const objects = [
73
+ { name: "Item 1", value: 5 },
74
+ { name: "Item 2", value: 10 },
75
+ ];
76
+ const result = filterObjectByInterval(objects, "value", "10/5");
77
+ expect(result).to.have.length(2);
78
+ });
79
+
80
+ it("should handle single value interval", () => {
81
+ const objects = [
82
+ { name: "Item 1", value: 5 },
83
+ { name: "Item 2", value: 10 },
84
+ { name: "Item 3", value: 15 },
85
+ ];
86
+ const result = filterObjectByInterval(objects, "value", "10");
87
+ expect(result).to.have.length(0);
88
+ });
89
+
90
+ it("should filter negative numbers", () => {
91
+ const objects = [
92
+ { name: "Item 1", value: -10 },
93
+ { name: "Item 2", value: 0 },
94
+ { name: "Item 3", value: 10 },
95
+ ];
96
+ const result = filterObjectByInterval(objects, "value", "-5/5");
97
+ expect(result).to.have.length(1);
98
+ expect(result[0].value).to.equal(0);
99
+ });
100
+
101
+ it("should filter decimal numbers", () => {
102
+ const objects = [
103
+ { name: "Item 1", value: 5.5 },
104
+ { name: "Item 2", value: 7.5 },
105
+ { name: "Item 3", value: 10.0 },
106
+ ];
107
+ const result = filterObjectByInterval(objects, "value", "6/8");
108
+ expect(result).to.have.length(1);
109
+ expect(result[0].value).to.equal(7.5);
110
+ });
111
+ });
112
+
113
+ describe("Nested property handling", () => {
114
+ it("should filter by nested numeric property", () => {
115
+ const objects = [
116
+ { name: "Project 1", stats: { score: 85 } },
117
+ { name: "Project 2", stats: { score: 92 } },
118
+ { name: "Project 3", stats: { score: 78 } },
119
+ ];
120
+ const result = filterObjectByInterval(objects, "stats.score", "80/90");
121
+ expect(result).to.have.length(1);
122
+ expect(result[0].name).to.equal("Project 1");
123
+ });
124
+
125
+ it("should filter by deeply nested numeric property", () => {
126
+ const objects = [
127
+ { name: "User 1", data: { profile: { level: 5 } } },
128
+ { name: "User 2", data: { profile: { level: 10 } } },
129
+ ];
130
+ const result = filterObjectByInterval(
131
+ objects,
132
+ "data.profile.level",
133
+ "7/12",
134
+ );
135
+ expect(result).to.have.length(1);
136
+ expect(result[0].name).to.equal("User 2");
137
+ });
138
+
139
+ it("should search within arrays", () => {
140
+ const objects = [
141
+ { name: "Project 1", scores: [85, 90, 95] },
142
+ { name: "Project 2", scores: [70, 75, 80] },
143
+ ];
144
+ const result = filterObjectByInterval(objects, "scores", "85/95");
145
+ expect(result).to.have.length(0);
146
+ });
147
+ });
148
+
149
+ describe("Edge cases", () => {
150
+ it("should handle empty array", () => {
151
+ const result = filterObjectByInterval([], "value", "5/10");
152
+ expect(result).to.deep.equal([]);
153
+ });
154
+
155
+ it("should handle objects without the property", () => {
156
+ const objects = [
157
+ { name: "Item 1", value: 5 },
158
+ { name: "Item 2" },
159
+ { name: "Item 3", value: 15 },
160
+ ];
161
+ const result = filterObjectByInterval(objects, "value", "5/10");
162
+ expect(result).to.have.length(1);
163
+ expect(result[0].name).to.equal("Item 1");
164
+ });
165
+
166
+ it("should handle objects with null property", () => {
167
+ const objects = [
168
+ { name: "Item 1", value: null },
169
+ { name: "Item 2", value: 10 },
170
+ ];
171
+ const result = filterObjectByInterval(objects, "value", "5/15");
172
+ expect(result).to.have.length(1);
173
+ expect(result[0].name).to.equal("Item 2");
174
+ });
175
+
176
+ it("should handle objects with undefined property", () => {
177
+ const objects = [
178
+ { name: "Item 1", value: undefined },
179
+ { name: "Item 2", value: 10 },
180
+ ];
181
+ const result = filterObjectByInterval(objects, "value", "5/15");
182
+ expect(result).to.have.length(1);
183
+ expect(result[0].name).to.equal("Item 2");
184
+ });
185
+
186
+ it("should handle objects with non-numeric property", () => {
187
+ const objects = [
188
+ { name: "Item 1", value: "not a number" },
189
+ { name: "Item 2", value: 10 },
190
+ ];
191
+ const result = filterObjectByInterval(objects, "value", "5/15");
192
+ expect(result).to.have.length(1);
193
+ expect(result[0].name).to.equal("Item 2");
194
+ });
195
+ });
196
+
197
+ describe("Real-world scenarios", () => {
198
+ it("should filter products by price range", () => {
199
+ const products = [
200
+ { name: "Product A", price: 25 },
201
+ { name: "Product B", price: 50 },
202
+ { name: "Product C", price: 75 },
203
+ { name: "Product D", price: 100 },
204
+ ];
205
+ const result = filterObjectByInterval(products, "price", "40/80");
206
+ expect(result).to.have.length(2);
207
+ expect(result.map((p) => p.name)).to.deep.equal([
208
+ "Product B",
209
+ "Product C",
210
+ ]);
211
+ });
212
+
213
+ it("should filter users by age range", () => {
214
+ const users = [
215
+ { name: "Alice", age: 25 },
216
+ { name: "Bob", age: 30 },
217
+ { name: "Charlie", age: 35 },
218
+ { name: "Diana", age: 40 },
219
+ ];
220
+ const result = filterObjectByInterval(users, "age", "30/35");
221
+ expect(result).to.have.length(2);
222
+ expect(result.map((u) => u.name)).to.deep.equal(["Bob", "Charlie"]);
223
+ });
224
+
225
+ it("should filter tasks by priority score range", () => {
226
+ const tasks = [
227
+ { name: "Task 1", priority: 1 },
228
+ { name: "Task 2", priority: 5 },
229
+ { name: "Task 3", priority: 8 },
230
+ { name: "Task 4", priority: 10 },
231
+ ];
232
+ const result = filterObjectByInterval(tasks, "priority", "5/8");
233
+ expect(result).to.have.length(2);
234
+ expect(result.map((t) => t.name)).to.deep.equal(["Task 2", "Task 3"]);
235
+ });
236
+ });
237
+ });