@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.
Files changed (49) 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 +1102 -1002
  25. package/package.json +10 -10
  26. package/src/components/solid-boilerplate.ts +76 -0
  27. package/src/helpers/components/componentObjectHandler.ts +5 -7
  28. package/src/helpers/components/componentObjectsHandler.ts +8 -3
  29. package/src/helpers/components/orbitComponent.ts +87 -68
  30. package/src/helpers/components/setupCacheInvalidation.ts +50 -23
  31. package/src/helpers/components/setupCacheOnResourceReady.ts +42 -23
  32. package/src/helpers/components/setupComponentSubscriptions.ts +10 -9
  33. package/src/helpers/components/setupOnSaveReset.ts +27 -5
  34. package/src/helpers/datas/checkValueInIntervalRecursive.ts +66 -0
  35. package/src/helpers/datas/dataBuilder.ts +4 -4
  36. package/src/helpers/datas/filterGenerator.ts +13 -10
  37. package/src/helpers/datas/filterObjectByDateAfter.ts +3 -3
  38. package/src/helpers/datas/filterObjectByDateInterval.ts +44 -0
  39. package/src/helpers/datas/filterObjectById.ts +7 -6
  40. package/src/helpers/datas/filterObjectByInterval.ts +6 -110
  41. package/src/helpers/datas/filterObjectByNamedValue.ts +35 -33
  42. package/src/helpers/datas/filterObjectByType.ts +3 -3
  43. package/src/helpers/datas/filterObjectByValue.ts +17 -16
  44. package/src/helpers/datas/sort.ts +50 -23
  45. package/src/helpers/index.ts +2 -0
  46. package/src/helpers/ui/formatDate.ts +14 -1
  47. package/src/helpers/utils/requestNavigation.ts +5 -2
  48. package/src/helpers/utils/uniq.ts +1 -1
  49. package/cypress/component/solid-boilerplate.cy.ts +0 -9
@@ -0,0 +1,285 @@
1
+ import filterGenerator from "@helpers/datas/filterGenerator";
2
+
3
+ describe("filterGenerator helper function", () => {
4
+ describe("Basic functionality", () => {
5
+ it("should generate filter options from array of objects", () => {
6
+ const objects = [
7
+ { name: "Alice", category: "Engineering" },
8
+ { name: "Bob", category: "Marketing" },
9
+ ];
10
+ const result = filterGenerator(objects, "category");
11
+ expect(result).to.have.length(2);
12
+ expect(result[0]).to.deep.equal({
13
+ label: "Engineering",
14
+ value: "Engineering",
15
+ });
16
+ expect(result[1]).to.deep.equal({
17
+ label: "Marketing",
18
+ value: "Marketing",
19
+ });
20
+ });
21
+
22
+ it("should extract label and value from nested objects", () => {
23
+ const objects = [
24
+ { name: "Alice", category: { name: "Engineering", "@id": "/cat/1" } },
25
+ { name: "Bob", category: { name: "Marketing", "@id": "/cat/2" } },
26
+ ];
27
+ const result = filterGenerator(objects, "category");
28
+ expect(result).to.have.length(2);
29
+ expect(result[0]).to.deep.equal({
30
+ label: "Engineering",
31
+ value: "/cat/1",
32
+ });
33
+ expect(result[1]).to.deep.equal({ label: "Marketing", value: "/cat/2" });
34
+ });
35
+ });
36
+
37
+ describe("Array field handling", () => {
38
+ it("should handle array fields by flattening", () => {
39
+ const objects = [
40
+ { name: "Alice", tags: ["engineering", "frontend"] },
41
+ { name: "Bob", tags: ["engineering", "backend"] },
42
+ ];
43
+ const result = filterGenerator(objects, "tags");
44
+ expect(result).to.have.length(3);
45
+ expect(result).to.deep.include.members([
46
+ { label: "engineering", value: "engineering" },
47
+ { label: "frontend", value: "frontend" },
48
+ { label: "backend", value: "backend" },
49
+ ]);
50
+ });
51
+
52
+ it("should extract nested objects from array fields", () => {
53
+ const objects = [
54
+ {
55
+ name: "Alice",
56
+ tags: [
57
+ { name: "Engineering", "@id": "/tag/1" },
58
+ { name: "Frontend", "@id": "/tag/2" },
59
+ ],
60
+ },
61
+ { name: "Bob", tags: [{ name: "Backend", "@id": "/tag/3" }] },
62
+ ];
63
+ const result = filterGenerator(objects, "tags");
64
+ expect(result).to.have.length(3);
65
+ expect(result).to.deep.include.members([
66
+ { label: "Engineering", value: "/tag/1" },
67
+ { label: "Frontend", value: "/tag/2" },
68
+ { label: "Backend", value: "/tag/3" },
69
+ ]);
70
+ });
71
+ });
72
+
73
+ describe("Duplicate handling", () => {
74
+ it("should remove duplicate values", () => {
75
+ const objects = [
76
+ { name: "Alice", category: "Engineering" },
77
+ { name: "Bob", category: "Engineering" },
78
+ { name: "Charlie", category: "Engineering" },
79
+ ];
80
+ const result = filterGenerator(objects, "category");
81
+ expect(result).to.have.length(1);
82
+ expect(result[0]).to.deep.equal({
83
+ label: "Engineering",
84
+ value: "Engineering",
85
+ });
86
+ });
87
+
88
+ it("should remove duplicate nested objects by @id", () => {
89
+ const objects = [
90
+ { name: "Alice", category: { name: "Engineering", "@id": "/cat/1" } },
91
+ { name: "Bob", category: { name: "Engineering", "@id": "/cat/1" } },
92
+ ];
93
+ const result = filterGenerator(objects, "category");
94
+ expect(result).to.have.length(1);
95
+ expect(result[0]).to.deep.equal({
96
+ label: "Engineering",
97
+ value: "/cat/1",
98
+ });
99
+ });
100
+
101
+ it("should handle mixed duplicates across simple and array values", () => {
102
+ const objects = [
103
+ { name: "Alice", tags: ["engineering", "frontend"] },
104
+ { name: "Bob", tags: ["engineering"] },
105
+ ];
106
+ const result = filterGenerator(objects, "tags");
107
+ expect(result).to.have.length(2);
108
+ expect(result).to.deep.include.members([
109
+ { label: "engineering", value: "engineering" },
110
+ { label: "frontend", value: "frontend" },
111
+ ]);
112
+ });
113
+ });
114
+
115
+ describe("Filtering", () => {
116
+ it("should filter out objects without the specified field", () => {
117
+ const objects = [
118
+ { name: "Alice", category: "Engineering" },
119
+ { name: "Bob" },
120
+ { name: "Charlie", category: "Marketing" },
121
+ ];
122
+ const result = filterGenerator(objects, "category");
123
+ expect(result).to.have.length(2);
124
+ expect(result.every((item) => item?.label)).to.be.true;
125
+ });
126
+
127
+ it("should filter out items without label or value", () => {
128
+ const objects = [
129
+ { name: "Alice", category: null },
130
+ { name: "Bob", category: undefined },
131
+ { name: "Charlie", category: "" },
132
+ ];
133
+ const result = filterGenerator(objects, "category");
134
+ expect(result).to.have.length(0);
135
+ });
136
+
137
+ it("should filter out array elements with null/undefined values", () => {
138
+ const objects = [
139
+ { name: "Alice", tags: ["engineering", null, undefined, "frontend"] },
140
+ ];
141
+ const result = filterGenerator(objects, "tags");
142
+ expect(result).to.have.length(2);
143
+ expect(result.every((item) => item?.label && item?.value)).to.be.true;
144
+ });
145
+ });
146
+
147
+ describe("Edge cases", () => {
148
+ it("should handle empty array", () => {
149
+ const result = filterGenerator([], "category");
150
+ expect(result).to.deep.equal([]);
151
+ });
152
+
153
+ it("should handle field not present in any object", () => {
154
+ const objects = [{ name: "Alice" }, { name: "Bob" }];
155
+ const result = filterGenerator(objects, "category");
156
+ expect(result).to.deep.equal([]);
157
+ });
158
+
159
+ it("should handle objects with empty array field", () => {
160
+ const objects = [
161
+ { name: "Alice", tags: [] },
162
+ { name: "Bob", tags: ["engineering"] },
163
+ ];
164
+ const result = filterGenerator(objects, "tags");
165
+ expect(result).to.have.length(1);
166
+ expect(result[0]).to.deep.equal({
167
+ label: "engineering",
168
+ value: "engineering",
169
+ });
170
+ });
171
+
172
+ it("should handle nested object with only @id", () => {
173
+ const objects = [{ name: "Alice", category: { "@id": "/cat/1" } }];
174
+ const result = filterGenerator(objects, "category");
175
+ expect(result).to.have.length(1);
176
+ expect(result[0]).to.deep.equal({
177
+ label: { "@id": "/cat/1" },
178
+ value: "/cat/1",
179
+ });
180
+ });
181
+
182
+ it("should handle nested object with only name", () => {
183
+ const objects = [{ name: "Alice", category: { name: "Engineering" } }];
184
+ const result = filterGenerator(objects, "category");
185
+ expect(result).to.have.length(1);
186
+ expect(result[0]).to.deep.equal({
187
+ label: "Engineering",
188
+ value: { name: "Engineering" },
189
+ });
190
+ });
191
+
192
+ it("should handle array with null elements", () => {
193
+ const objects = [{ name: "Alice", tags: [null, "engineering"] }];
194
+ const result = filterGenerator(objects, "tags");
195
+ expect(result).to.have.length(1);
196
+ expect(result[0]).to.deep.equal({
197
+ label: "engineering",
198
+ value: "engineering",
199
+ });
200
+ });
201
+
202
+ it("should handle zero as valid value", () => {
203
+ const objects = [
204
+ { name: "Alice", level: 0 },
205
+ { name: "Bob", level: 1 },
206
+ ];
207
+ const result = filterGenerator(objects, "level");
208
+ expect(result).to.have.length(1);
209
+ expect(result[0]).to.deep.equal({ label: 1, value: 1 });
210
+ });
211
+
212
+ it("should handle false as valid value", () => {
213
+ const objects = [
214
+ { name: "Alice", active: false },
215
+ { name: "Bob", active: true },
216
+ ];
217
+ const result = filterGenerator(objects, "active");
218
+ expect(result).to.have.length(1);
219
+ expect(result[0]).to.deep.equal({ label: true, value: true });
220
+ });
221
+ });
222
+
223
+ describe("Label extraction", () => {
224
+ it("should prefer name property over direct value for label", () => {
225
+ const objects = [{ category: { name: "Engineering", "@id": "/cat/1" } }];
226
+ const result = filterGenerator(objects, "category");
227
+ expect(result[0]?.label).to.equal("Engineering");
228
+ });
229
+
230
+ it("should use direct value when name property is absent", () => {
231
+ const objects = [{ category: "Engineering" }];
232
+ const result = filterGenerator(objects, "category");
233
+ expect(result[0]?.label).to.equal("Engineering");
234
+ });
235
+
236
+ it("should prefer @id property over direct value for value", () => {
237
+ const objects = [{ category: { name: "Engineering", "@id": "/cat/1" } }];
238
+ const result = filterGenerator(objects, "category");
239
+ expect(result[0]?.value).to.equal("/cat/1");
240
+ });
241
+
242
+ it("should use direct value when @id property is absent", () => {
243
+ const objects = [{ category: "Engineering" }];
244
+ const result = filterGenerator(objects, "category");
245
+ expect(result[0]?.value).to.equal("Engineering");
246
+ });
247
+ });
248
+
249
+ describe("Complex scenarios", () => {
250
+ it("should handle mixed field types across objects", () => {
251
+ const objects = [
252
+ { name: "Alice", category: "Engineering" },
253
+ { name: "Bob", category: { name: "Marketing", "@id": "/cat/2" } },
254
+ ];
255
+ const result = filterGenerator(objects, "category");
256
+ expect(result).to.have.length(2);
257
+ expect(result).to.deep.include.members([
258
+ { label: "Engineering", value: "Engineering" },
259
+ { label: "Marketing", value: "/cat/2" },
260
+ ]);
261
+ });
262
+
263
+ it("should handle deeply nested structures in arrays", () => {
264
+ const objects = [
265
+ {
266
+ name: "Alice",
267
+ tags: [
268
+ { name: "Engineering", "@id": "/tag/1" },
269
+ { name: "Frontend", "@id": "/tag/2" },
270
+ ],
271
+ },
272
+ {
273
+ name: "Bob",
274
+ tags: [
275
+ { name: "Backend", "@id": "/tag/3" },
276
+ { name: "Engineering", "@id": "/tag/1" },
277
+ ],
278
+ },
279
+ ];
280
+ const result = filterGenerator(objects, "tags");
281
+ expect(result).to.have.length(3);
282
+ expect(result.every((item) => item?.label && item?.value)).to.be.true;
283
+ });
284
+ });
285
+ });
@@ -0,0 +1,389 @@
1
+ import filterObjectByDateAfter from "@helpers/datas/filterObjectByDateAfter";
2
+
3
+ describe("filterObjectByDateAfter helper function", () => {
4
+ describe("Basic functionality", () => {
5
+ it("should filter objects by date property after threshold date", () => {
6
+ const objects = [
7
+ { name: "Event 1", date: "2023-01-15" },
8
+ { name: "Event 2", date: "2023-02-15" },
9
+ { name: "Event 3", date: "2023-03-15" },
10
+ ];
11
+ const result = filterObjectByDateAfter(objects, "date", "2023-02-01");
12
+ expect(result).to.have.length(2);
13
+ expect(result.map((r) => r.name)).to.deep.equal(["Event 2", "Event 3"]);
14
+ });
15
+
16
+ it("should exclude objects with date equal to threshold", () => {
17
+ const objects = [
18
+ { name: "Event 1", date: "2023-02-01" },
19
+ { name: "Event 2", date: "2023-02-15" },
20
+ ];
21
+ const result = filterObjectByDateAfter(objects, "date", "2023-02-01");
22
+ expect(result).to.have.length(1);
23
+ expect(result[0].name).to.equal("Event 2");
24
+ });
25
+
26
+ it("should return all objects when propName is empty", () => {
27
+ const objects = [
28
+ { name: "Event 1", date: "2023-01-15" },
29
+ { name: "Event 2", date: "2023-02-15" },
30
+ ];
31
+ const result = filterObjectByDateAfter(objects, "", "2023-02-01");
32
+ expect(result).to.have.length(2);
33
+ });
34
+
35
+ it("should return all objects when thresholdDateString is empty", () => {
36
+ const objects = [
37
+ { name: "Event 1", date: "2023-01-15" },
38
+ { name: "Event 2", date: "2023-02-15" },
39
+ ];
40
+ const result = filterObjectByDateAfter(objects, "date", "");
41
+ expect(result).to.have.length(2);
42
+ });
43
+
44
+ it("should return all objects when thresholdDateString is only whitespace", () => {
45
+ const objects = [
46
+ { name: "Event 1", date: "2023-01-15" },
47
+ { name: "Event 2", date: "2023-02-15" },
48
+ ];
49
+ const result = filterObjectByDateAfter(objects, "date", " ");
50
+ expect(result).to.have.length(2);
51
+ });
52
+
53
+ it("should return all objects when thresholdDateString is not a string", () => {
54
+ const objects = [
55
+ { name: "Event 1", date: "2023-01-15" },
56
+ { name: "Event 2", date: "2023-02-15" },
57
+ ];
58
+ const result = filterObjectByDateAfter(objects, "date", null as any);
59
+ expect(result).to.have.length(2);
60
+ });
61
+
62
+ it("should return all objects when threshold date is invalid", () => {
63
+ const objects = [
64
+ { name: "Event 1", date: "2023-01-15" },
65
+ { name: "Event 2", date: "2023-02-15" },
66
+ ];
67
+ const result = filterObjectByDateAfter(objects, "date", "invalid-date");
68
+ expect(result).to.have.length(2);
69
+ });
70
+ });
71
+
72
+ describe("Date format handling", () => {
73
+ it("should handle ISO date strings", () => {
74
+ const objects = [
75
+ { name: "Event 1", date: "2023-02-15T10:30:00Z" },
76
+ { name: "Event 2", date: "2023-03-15T10:30:00Z" },
77
+ ];
78
+ const result = filterObjectByDateAfter(objects, "date", "2023-02-01");
79
+ expect(result).to.have.length(2);
80
+ });
81
+
82
+ it("should handle ISO date strings with timezone", () => {
83
+ const objects = [
84
+ { name: "Event 1", date: "2023-02-15T10:30:00+05:00" },
85
+ { name: "Event 2", date: "2023-01-15T10:30:00+05:00" },
86
+ ];
87
+ const result = filterObjectByDateAfter(objects, "date", "2023-02-01");
88
+ expect(result).to.have.length(1);
89
+ expect(result[0].name).to.equal("Event 1");
90
+ });
91
+
92
+ it("should handle timestamp numbers", () => {
93
+ const objects = [
94
+ { name: "Event 1", date: "2023-01-15" },
95
+ { name: "Event 2", date: "2023-02-15" },
96
+ ];
97
+ const result = filterObjectByDateAfter(objects, "date", "2023-02-01");
98
+ expect(result).to.have.length(1);
99
+ expect(result[0].name).to.equal("Event 2");
100
+ });
101
+
102
+ it("should handle Date objects", () => {
103
+ const objects = [
104
+ { name: "Event 1", date: new Date("2023-02-15") },
105
+ { name: "Event 2", date: new Date("2023-01-15") },
106
+ ];
107
+ const result = filterObjectByDateAfter(objects, "date", "2023-02-01");
108
+ expect(result).to.have.length(1);
109
+ expect(result[0].name).to.equal("Event 1");
110
+ });
111
+
112
+ it("should handle various date formats", () => {
113
+ const objects = [
114
+ { name: "Event 1", date: "2023/02/15" },
115
+ { name: "Event 2", date: "2023-03-15" },
116
+ ];
117
+ const result = filterObjectByDateAfter(objects, "date", "2023-02-01");
118
+ expect(result).to.have.length(2);
119
+ });
120
+ });
121
+
122
+ describe("Nested property handling", () => {
123
+ it("should filter by nested date property", () => {
124
+ const objects = [
125
+ { name: "Project 1", metadata: { createdAt: "2023-02-15" } },
126
+ { name: "Project 2", metadata: { createdAt: "2023-01-15" } },
127
+ ];
128
+ const result = filterObjectByDateAfter(
129
+ objects,
130
+ "metadata.createdAt",
131
+ "2023-02-01",
132
+ );
133
+ expect(result).to.have.length(1);
134
+ expect(result[0].name).to.equal("Project 1");
135
+ });
136
+
137
+ it("should filter by deeply nested date property", () => {
138
+ const objects = [
139
+ { name: "User 1", data: { profile: { joined: "2023-02-15" } } },
140
+ { name: "User 2", data: { profile: { joined: "2023-01-15" } } },
141
+ ];
142
+ const result = filterObjectByDateAfter(
143
+ objects,
144
+ "data.profile.joined",
145
+ "2023-02-01",
146
+ );
147
+ expect(result).to.have.length(1);
148
+ expect(result[0].name).to.equal("User 1");
149
+ });
150
+
151
+ it("should search within arrays", () => {
152
+ const objects = [
153
+ {
154
+ name: "Project 1",
155
+ milestones: [{ date: "2023-02-15" }, { date: "2023-03-15" }],
156
+ },
157
+ { name: "Project 2", milestones: [{ date: "2023-01-15" }] },
158
+ ];
159
+ const result = filterObjectByDateAfter(
160
+ objects,
161
+ "milestones",
162
+ "2023-02-01",
163
+ );
164
+ expect(result).to.have.length(0);
165
+ });
166
+
167
+ it("should return empty array when nested property does not exist", () => {
168
+ const objects = [
169
+ { name: "Event 1", metadata: { createdAt: "2023-02-15" } },
170
+ { name: "Event 2", metadata: { createdAt: "2023-01-15" } },
171
+ ];
172
+ const result = filterObjectByDateAfter(
173
+ objects,
174
+ "nonexistent.property",
175
+ "2023-02-01",
176
+ );
177
+ expect(result).to.have.length(0);
178
+ });
179
+ });
180
+
181
+ describe("Edge cases", () => {
182
+ it("should handle empty array", () => {
183
+ const result = filterObjectByDateAfter([], "date", "2023-02-01");
184
+ expect(result).to.deep.equal([]);
185
+ });
186
+
187
+ it("should handle objects without the property", () => {
188
+ const objects = [
189
+ { name: "Event 1", date: "2023-02-15" },
190
+ { name: "Event 2" },
191
+ { name: "Event 3", date: "2023-03-15" },
192
+ ];
193
+ const result = filterObjectByDateAfter(objects, "date", "2023-02-01");
194
+ expect(result).to.have.length(2);
195
+ expect(result.map((r) => r.name)).to.deep.equal(["Event 1", "Event 3"]);
196
+ });
197
+
198
+ it("should handle objects with null property", () => {
199
+ const objects = [
200
+ { name: "Event 1", date: null },
201
+ { name: "Event 2", date: "2023-02-15" },
202
+ ];
203
+ const result = filterObjectByDateAfter(objects, "date", "2023-02-01");
204
+ expect(result).to.have.length(1);
205
+ expect(result[0].name).to.equal("Event 2");
206
+ });
207
+
208
+ it("should handle objects with undefined property", () => {
209
+ const objects = [
210
+ { name: "Event 1", date: undefined },
211
+ { name: "Event 2", date: "2023-02-15" },
212
+ ];
213
+ const result = filterObjectByDateAfter(objects, "date", "2023-02-01");
214
+ expect(result).to.have.length(1);
215
+ expect(result[0].name).to.equal("Event 2");
216
+ });
217
+
218
+ it("should handle objects with invalid date string", () => {
219
+ const objects = [
220
+ { name: "Event 1", date: "not a date" },
221
+ { name: "Event 2", date: "2023-02-15" },
222
+ ];
223
+ const result = filterObjectByDateAfter(objects, "date", "2023-02-01");
224
+ expect(result).to.have.length(1);
225
+ expect(result[0].name).to.equal("Event 2");
226
+ });
227
+
228
+ it("should handle invalid date values", () => {
229
+ const objects = [
230
+ { name: "Event 1", date: Number.NaN },
231
+ { name: "Event 2", date: "2023-02-15" },
232
+ ];
233
+ const result = filterObjectByDateAfter(objects, "date", "2023-02-01");
234
+ expect(result).to.have.length(1);
235
+ expect(result[0].name).to.equal("Event 2");
236
+ });
237
+
238
+ it("should handle empty string date values", () => {
239
+ const objects = [
240
+ { name: "Event 1", date: "" },
241
+ { name: "Event 2", date: "2023-02-15" },
242
+ ];
243
+ const result = filterObjectByDateAfter(objects, "date", "2023-02-01");
244
+ expect(result).to.have.length(1);
245
+ expect(result[0].name).to.equal("Event 2");
246
+ });
247
+
248
+ it("should return empty array when no dates are after threshold", () => {
249
+ const objects = [
250
+ { name: "Event 1", date: "2023-01-15" },
251
+ { name: "Event 2", date: "2023-01-20" },
252
+ ];
253
+ const result = filterObjectByDateAfter(objects, "date", "2023-02-01");
254
+ expect(result).to.have.length(0);
255
+ });
256
+
257
+ it("should return all objects when all dates are after threshold", () => {
258
+ const objects = [
259
+ { name: "Event 1", date: "2023-03-15" },
260
+ { name: "Event 2", date: "2023-04-15" },
261
+ ];
262
+ const result = filterObjectByDateAfter(objects, "date", "2023-02-01");
263
+ expect(result).to.have.length(2);
264
+ });
265
+ });
266
+
267
+ describe("Precision handling", () => {
268
+ it("should compare dates at millisecond precision", () => {
269
+ const objects = [
270
+ { name: "Event 1", date: "2023-02-01T00:00:00.000Z" },
271
+ { name: "Event 2", date: "2023-02-01T00:00:00.001Z" },
272
+ ];
273
+ const result = filterObjectByDateAfter(
274
+ objects,
275
+ "date",
276
+ "2023-02-01T00:00:00.000Z",
277
+ );
278
+ expect(result).to.have.length(1);
279
+ expect(result[0].name).to.equal("Event 2");
280
+ });
281
+
282
+ it("should handle dates with time components", () => {
283
+ const objects = [
284
+ { name: "Event 1", date: "2023-02-01T08:00:00Z" },
285
+ { name: "Event 2", date: "2023-02-01T12:00:00Z" },
286
+ { name: "Event 3", date: "2023-02-01T16:00:00Z" },
287
+ ];
288
+ const result = filterObjectByDateAfter(
289
+ objects,
290
+ "date",
291
+ "2023-02-01T10:00:00Z",
292
+ );
293
+ expect(result).to.have.length(2);
294
+ expect(result.map((r) => r.name)).to.deep.equal(["Event 2", "Event 3"]);
295
+ });
296
+ });
297
+
298
+ describe("Real-world scenarios", () => {
299
+ it("should filter projects by creation date after a threshold", () => {
300
+ const projects = [
301
+ { name: "Project A", createdAt: "2023-01-15" },
302
+ { name: "Project B", createdAt: "2023-02-15" },
303
+ { name: "Project C", createdAt: "2023-03-15" },
304
+ { name: "Project D", createdAt: "2023-04-15" },
305
+ ];
306
+ const result = filterObjectByDateAfter(
307
+ projects,
308
+ "createdAt",
309
+ "2023-02-01",
310
+ );
311
+ expect(result).to.have.length(3);
312
+ expect(result.map((p) => p.name)).to.deep.equal([
313
+ "Project B",
314
+ "Project C",
315
+ "Project D",
316
+ ]);
317
+ });
318
+
319
+ it("should filter events by date after today", () => {
320
+ const today = new Date().toISOString().split("T")[0];
321
+ const tomorrow = new Date(Date.now() + 86400000)
322
+ .toISOString()
323
+ .split("T")[0];
324
+
325
+ const events = [
326
+ { name: "Past Event", date: "2023-01-01" },
327
+ { name: "Future Event", date: tomorrow },
328
+ ];
329
+ const result = filterObjectByDateAfter(events, "date", today);
330
+ expect(result).to.have.length(1);
331
+ expect(result[0].name).to.equal("Future Event");
332
+ });
333
+
334
+ it("should filter tasks by due date", () => {
335
+ const tasks = [
336
+ { name: "Task 1", dueDate: "2023-05-01" },
337
+ { name: "Task 2", dueDate: "2023-06-01" },
338
+ { name: "Task 3", dueDate: "2023-04-01" },
339
+ ];
340
+ const result = filterObjectByDateAfter(tasks, "dueDate", "2023-05-01");
341
+ expect(result).to.have.length(1);
342
+ expect(result[0].name).to.equal("Task 2");
343
+ });
344
+
345
+ it("should filter users by last login", () => {
346
+ const users = [
347
+ { name: "Alice", lastLogin: "2023-05-15T10:00:00Z" },
348
+ { name: "Bob", lastLogin: "2023-06-15T10:00:00Z" },
349
+ { name: "Charlie", lastLogin: "2023-04-15T10:00:00Z" },
350
+ ];
351
+ const result = filterObjectByDateAfter(
352
+ users,
353
+ "lastLogin",
354
+ "2023-05-01T00:00:00Z",
355
+ );
356
+ expect(result).to.have.length(2);
357
+ expect(result.map((u) => u.name)).to.deep.equal(["Alice", "Bob"]);
358
+ });
359
+ });
360
+
361
+ describe("Complex nested structures", () => {
362
+ it("should find dates in deeply nested structures", () => {
363
+ const objects = [
364
+ {
365
+ name: "Project1",
366
+ data: { history: { entries: [{ date: "2023-02-15" }] } },
367
+ },
368
+ {
369
+ name: "Project2",
370
+ data: { history: { entries: [{ date: "2023-01-15" }] } },
371
+ },
372
+ ];
373
+ const result = filterObjectByDateAfter(objects, "data", "2023-02-01");
374
+ expect(result).to.have.length(0);
375
+ });
376
+
377
+ it("should handle mixed date types in nested arrays", () => {
378
+ const objects = [
379
+ {
380
+ name: "Project 1",
381
+ events: ["2023-02-15", "2023-03-15", { date: "2023-04-15" }],
382
+ },
383
+ { name: "Project 2", events: ["2023-01-15"] },
384
+ ];
385
+ const result = filterObjectByDateAfter(objects, "events", "2023-02-01");
386
+ expect(result).to.have.length(0);
387
+ });
388
+ });
389
+ });