@startinblox/boilerplate 4.3.1 → 6.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 (53) hide show
  1. package/.gitlab-ci.yml +3 -3
  2. package/AGENTS.md +518 -0
  3. package/README.md +16 -19
  4. package/biome.json +1 -1
  5. package/cypress/component/sample-object.cy.ts +816 -0
  6. package/cypress/component/solid-boilerplate.cy.ts +894 -5
  7. package/cypress/e2e/helpers/components/setupCacheInvalidation.cy.ts +512 -0
  8. package/cypress/e2e/helpers/components/setupCacheOnResourceReady.cy.ts +497 -0
  9. package/cypress/e2e/helpers/components/setupComponentSubscriptions.cy.ts +239 -0
  10. package/cypress/e2e/helpers/components/setupOnSaveReset.cy.ts +393 -0
  11. package/cypress/e2e/helpers/datas/checkValueInIntervalRecursive.cy.ts +563 -0
  12. package/cypress/e2e/helpers/datas/dataBuilder.cy.ts +508 -0
  13. package/cypress/e2e/helpers/datas/filterGenerator.cy.ts +285 -0
  14. package/cypress/e2e/helpers/datas/filterObjectByDateAfter.cy.ts +389 -0
  15. package/cypress/e2e/helpers/datas/filterObjectByDateInterval.cy.ts +613 -0
  16. package/cypress/e2e/helpers/datas/filterObjectById.cy.ts +276 -0
  17. package/cypress/e2e/helpers/datas/filterObjectByInterval.cy.ts +237 -0
  18. package/cypress/e2e/helpers/datas/filterObjectByNamedValue.cy.ts +299 -0
  19. package/cypress/e2e/helpers/datas/filterObjectByType.cy.ts +307 -0
  20. package/cypress/e2e/helpers/datas/filterObjectByValue.cy.ts +375 -0
  21. package/cypress/e2e/helpers/datas/sort.cy.ts +293 -0
  22. package/cypress/e2e/helpers/ui/formatDate.cy.ts +233 -0
  23. package/cypress/e2e/helpers/utils/requestNavigation.cy.ts +257 -0
  24. package/cypress/e2e/helpers/utils/uniq.cy.ts +160 -0
  25. package/cypress/support/e2e.ts +1 -0
  26. package/cypress.config.ts +2 -0
  27. package/dist/index.js +614 -646
  28. package/package.json +17 -15
  29. package/scripts/init.js +355 -0
  30. package/src/components/solid-boilerplate.ts +3 -6
  31. package/src/helpers/components/componentObjectHandler.ts +5 -7
  32. package/src/helpers/components/componentObjectsHandler.ts +8 -3
  33. package/src/helpers/components/orbitComponent.ts +106 -57
  34. package/src/helpers/components/setupCacheInvalidation.ts +50 -23
  35. package/src/helpers/components/setupCacheOnResourceReady.ts +42 -23
  36. package/src/helpers/components/setupComponentSubscriptions.ts +10 -9
  37. package/src/helpers/components/setupOnSaveReset.ts +27 -5
  38. package/src/helpers/datas/checkValueInIntervalRecursive.ts +66 -0
  39. package/src/helpers/datas/dataBuilder.ts +4 -4
  40. package/src/helpers/datas/filterGenerator.ts +13 -10
  41. package/src/helpers/datas/filterObjectByDateAfter.ts +3 -3
  42. package/src/helpers/datas/filterObjectByDateInterval.ts +44 -0
  43. package/src/helpers/datas/filterObjectById.ts +7 -6
  44. package/src/helpers/datas/filterObjectByInterval.ts +6 -110
  45. package/src/helpers/datas/filterObjectByNamedValue.ts +35 -33
  46. package/src/helpers/datas/filterObjectByType.ts +3 -3
  47. package/src/helpers/datas/filterObjectByValue.ts +17 -16
  48. package/src/helpers/datas/sort.ts +50 -23
  49. package/src/helpers/index.ts +6 -4
  50. package/src/helpers/ui/formatDate.ts +14 -1
  51. package/src/helpers/utils/requestNavigation.ts +5 -2
  52. package/src/helpers/utils/uniq.ts +1 -1
  53. package/src/index.ts +2 -2
@@ -1,9 +1,898 @@
1
- import { html } from "lit";
1
+ import type { LiveOrbit, PropertiesPicker, Resource } from "@src/component";
2
+ import { orbit, sibRouter, sibStore } from "@src/mocks/orbit.mock";
3
+ import { user } from "@src/mocks/user.mock";
4
+ import { html, nothing } from "lit";
2
5
 
3
- describe("<solid-boilerplate>", () => {
4
- it("should mount", () => {
5
- cy.mount(html`<solid-boilerplate></solid-boilerplate>`);
6
+ /*
7
+ Testing OrbitComponent via solid-boilerplate
8
+ */
6
9
 
7
- cy.get("solid-boilerplate").should("exist");
10
+ // Interface for type checking in tests
11
+ interface MockedSolidBoilerplate extends HTMLElement {
12
+ ready: boolean;
13
+ defaultDataSrc?: string;
14
+ dataSrc?: string;
15
+ nestedField?: string;
16
+ uniq?: string;
17
+ route?: string;
18
+ cherryPickedProperties: PropertiesPicker[];
19
+ orbit?: LiveOrbit;
20
+ currentRoute: string;
21
+ objects?: Resource[];
22
+ datas?: Resource[];
23
+ hasCachedDatas?: boolean;
24
+ oldDataSrc?: string;
25
+ noRouter?: boolean;
26
+ component?: any;
27
+ _getResource?: any;
28
+
29
+ _attach(
30
+ defaultRoute?: boolean,
31
+ setupSubscriptions?: boolean,
32
+ ignoreRouter?: boolean,
33
+ ): Promise<boolean>;
34
+ _afterAttach(): Promise<void>;
35
+ _navigate(e: Event): void;
36
+ _normalizeLdpContains(value: Resource[] | Resource | null): Resource[];
37
+ _expandContainer(
38
+ value: Resource[],
39
+ recursive?: boolean,
40
+ targetProperties?: PropertiesPicker[],
41
+ ): Promise<Resource[]>;
42
+ _getProperties(
43
+ resource: Resource,
44
+ recursive?: boolean,
45
+ targetProperties?: PropertiesPicker[],
46
+ ): Promise<Resource>;
47
+ _hasCherryPickedProperties(resource: Resource): Promise<boolean>;
48
+ _getProxyValue(
49
+ resource: string | Resource | any,
50
+ recursive?: boolean,
51
+ targetProperties?: PropertiesPicker[],
52
+ ): Promise<any>;
53
+ _responseAdaptator(response: Resource): Promise<Resource>;
54
+ gatekeeper(): symbol;
55
+ hasType(type: string, objs?: Resource[]): boolean;
56
+ render(): any;
57
+ }
58
+
59
+ describe("<solid-boilerplate> OrbitComponent methods", () => {
60
+ beforeEach(() => {
61
+ cy.window().then((win) => {
62
+ win.orbit = orbit;
63
+ win.sibStore = sibStore;
64
+ win.sibRouter = sibRouter;
65
+ });
66
+ });
67
+
68
+ describe("Properties", () => {
69
+ it("should have ready property", () => {
70
+ cy.mount(html`<solid-boilerplate></solid-boilerplate>`);
71
+
72
+ cy.get("solid-boilerplate").then(($el) => {
73
+ const component = $el[0] as unknown as MockedSolidBoilerplate;
74
+ expect(component.ready).to.be.a("boolean");
75
+ });
76
+ });
77
+
78
+ it("should have defaultDataSrc property", () => {
79
+ cy.mount(
80
+ html`<solid-boilerplate
81
+ default-data-src="https://example.com/data"
82
+ ></solid-boilerplate>`,
83
+ );
84
+
85
+ cy.get("solid-boilerplate").then(($el) => {
86
+ const component = $el[0] as unknown as MockedSolidBoilerplate;
87
+ expect(component.defaultDataSrc).to.equal("https://example.com/data");
88
+ });
89
+ });
90
+
91
+ it("should have dataSrc property", () => {
92
+ cy.mount(
93
+ html`<solid-boilerplate
94
+ data-src="https://example.com/data"
95
+ ></solid-boilerplate>`,
96
+ );
97
+
98
+ cy.get("solid-boilerplate").then(($el) => {
99
+ const component = $el[0] as unknown as MockedSolidBoilerplate;
100
+ expect(component.dataSrc).to.equal("https://example.com/data");
101
+ });
102
+ });
103
+
104
+ it("should have nestedField property", () => {
105
+ cy.mount(
106
+ html`<solid-boilerplate nested-field="items"></solid-boilerplate>`,
107
+ );
108
+
109
+ cy.get("solid-boilerplate").then(($el) => {
110
+ const component = $el[0] as unknown as MockedSolidBoilerplate;
111
+ expect(component.nestedField).to.equal("items");
112
+ });
113
+ });
114
+
115
+ it("should have uniq property", () => {
116
+ cy.mount(html`<solid-boilerplate uniq="unique-id"></solid-boilerplate>`);
117
+
118
+ cy.get("solid-boilerplate").then(($el) => {
119
+ const component = $el[0] as unknown as MockedSolidBoilerplate;
120
+ expect(component.uniq).to.equal("unique-id");
121
+ });
122
+ });
123
+
124
+ it("should have route property", () => {
125
+ cy.mount(html`<solid-boilerplate route="/my-route"></solid-boilerplate>`);
126
+
127
+ cy.get("solid-boilerplate").then(($el) => {
128
+ const component = $el[0] as unknown as MockedSolidBoilerplate;
129
+ expect(component.route).to.equal("/my-route");
130
+ });
131
+ });
132
+
133
+ it("should have cherryPickedProperties", () => {
134
+ cy.mount(html`<solid-boilerplate></solid-boilerplate>`);
135
+
136
+ cy.get("solid-boilerplate").then(($el) => {
137
+ const component = $el[0] as unknown as MockedSolidBoilerplate;
138
+ expect(component.cherryPickedProperties).to.be.an("array");
139
+ expect(component.cherryPickedProperties[0]).to.have.property("key");
140
+ expect(component.cherryPickedProperties[0]).to.have.property("value");
141
+ });
142
+ });
143
+
144
+ it("should have orbit property", () => {
145
+ cy.mount(html`<solid-boilerplate></solid-boilerplate>`);
146
+
147
+ cy.get("solid-boilerplate").then(($el) => {
148
+ const component = $el[0] as unknown as MockedSolidBoilerplate;
149
+ expect(component.orbit).to.exist;
150
+ });
151
+ });
152
+
153
+ it("should have currentRoute property", () => {
154
+ cy.mount(html`<solid-boilerplate></solid-boilerplate>`);
155
+
156
+ cy.get("solid-boilerplate").then(($el) => {
157
+ const component = $el[0] as unknown as MockedSolidBoilerplate;
158
+ expect(component.currentRoute).to.be.a("string");
159
+ });
160
+ });
161
+
162
+ it("should have objects property", () => {
163
+ cy.mount(html`<solid-boilerplate></solid-boilerplate>`);
164
+
165
+ cy.get("solid-boilerplate").then(($el) => {
166
+ const component = $el[0] as unknown as MockedSolidBoilerplate;
167
+ expect(component.objects).to.be.an("array");
168
+ });
169
+ });
170
+ });
171
+
172
+ describe("_attach method", () => {
173
+ it("should attach to orbit when available", () => {
174
+ cy.mount(html`<solid-boilerplate></solid-boilerplate>`);
175
+
176
+ cy.get("solid-boilerplate").then(($el) => {
177
+ const component = $el[0] as unknown as MockedSolidBoilerplate;
178
+ expect(component.orbit).to.exist;
179
+ });
180
+ });
181
+
182
+ it("should set ready to true after attach", () => {
183
+ cy.mount(html`<solid-boilerplate></solid-boilerplate>`);
184
+
185
+ cy.wait(100)
186
+ .get("solid-boilerplate")
187
+ .then(($el) => {
188
+ const component = $el[0] as unknown as MockedSolidBoilerplate;
189
+ expect(component.ready).to.be.true;
190
+ });
191
+ });
192
+
193
+ it("should dispatch component-ready event", () => {
194
+ cy.mount(html`<solid-boilerplate></solid-boilerplate>`);
195
+
196
+ cy.get("solid-boilerplate").then(($el) => {
197
+ const component = $el[0] as unknown as MockedSolidBoilerplate;
198
+ expect(component.ready).to.be.true;
199
+ });
200
+ });
201
+ });
202
+
203
+ describe("_afterAttach method", () => {
204
+ it("should call _afterAttach after mount", () => {
205
+ cy.mount(html`<solid-boilerplate></solid-boilerplate>`);
206
+
207
+ cy.get("solid-boilerplate")
208
+ .then(($el) => {
209
+ const component = $el[0] as unknown as MockedSolidBoilerplate;
210
+ return component._afterAttach();
211
+ })
212
+ .then(() => {
213
+ expect(true).to.be.true;
214
+ });
215
+ });
216
+
217
+ it("should setup cache invalidation", () => {
218
+ cy.mount(html`<solid-boilerplate></solid-boilerplate>`);
219
+
220
+ cy.get("solid-boilerplate").then(($el) => {
221
+ const component = $el[0] as unknown as MockedSolidBoilerplate;
222
+ expect(component._afterAttach).to.exist;
223
+ });
224
+ });
225
+ });
226
+
227
+ describe("_navigate method", () => {
228
+ it("should handle navigation event", () => {
229
+ cy.mount(html`<solid-boilerplate></solid-boilerplate>`);
230
+
231
+ cy.get("solid-boilerplate").then(($el) => {
232
+ const component = $el[0] as unknown as MockedSolidBoilerplate;
233
+ const mockEvent = {
234
+ preventDefault: cy.stub(),
235
+ target: {
236
+ closest: cy.stub().returns({
237
+ getAttribute: cy.stub().callsFake((attr) => {
238
+ if (attr === "navigation-target") return "/target";
239
+ if (attr === "navigation-resource") return "resource-id";
240
+ return null;
241
+ }),
242
+ }),
243
+ },
244
+ } as any;
245
+
246
+ component._navigate(mockEvent);
247
+ expect(mockEvent.preventDefault).to.be.called;
248
+ });
249
+ });
250
+
251
+ it("should handle navigation with rdf-type", () => {
252
+ cy.mount(html`<solid-boilerplate></solid-boilerplate>`);
253
+
254
+ cy.get("solid-boilerplate").then(($el) => {
255
+ const component = $el[0] as unknown as MockedSolidBoilerplate;
256
+ const mockEvent = {
257
+ preventDefault: cy.stub(),
258
+ target: {
259
+ closest: cy.stub().returns({
260
+ getAttribute: cy.stub().callsFake((attr) => {
261
+ if (attr === "navigation-rdf-type") return "foaf:user";
262
+ if (attr === "navigation-resource") return "resource-id";
263
+ return null;
264
+ }),
265
+ }),
266
+ },
267
+ } as any;
268
+
269
+ component._navigate(mockEvent);
270
+ expect(mockEvent.preventDefault).to.be.called;
271
+ });
272
+ });
273
+
274
+ it("should handle navigation with subrouter", () => {
275
+ cy.mount(html`<solid-boilerplate></solid-boilerplate>`);
276
+
277
+ cy.get("solid-boilerplate").then(($el) => {
278
+ const component = $el[0] as unknown as MockedSolidBoilerplate;
279
+ const mockEvent = {
280
+ preventDefault: cy.stub(),
281
+ target: {
282
+ closest: cy.stub().returns({
283
+ getAttribute: cy.stub().callsFake((attr) => {
284
+ if (attr === "navigation-target") return "/target";
285
+ if (attr === "navigation-subrouter") return "sub";
286
+ if (attr === "navigation-resource") return "resource-id";
287
+ return null;
288
+ }),
289
+ }),
290
+ },
291
+ } as any;
292
+
293
+ component._navigate(mockEvent);
294
+ expect(mockEvent.preventDefault).to.be.called;
295
+ });
296
+ });
297
+ });
298
+
299
+ describe("_normalizeLdpContains method", () => {
300
+ it("should normalize single resource to array", () => {
301
+ cy.mount(html`<solid-boilerplate></solid-boilerplate>`);
302
+
303
+ cy.get("solid-boilerplate").then(($el) => {
304
+ const component = $el[0] as unknown as MockedSolidBoilerplate;
305
+ const result = component._normalizeLdpContains(user);
306
+ expect(result).to.be.an("array");
307
+ expect(result).to.have.length(1);
308
+ expect(result[0]).to.equal(user);
309
+ });
310
+ });
311
+
312
+ it("should return array unchanged", () => {
313
+ cy.mount(html`<solid-boilerplate></solid-boilerplate>`);
314
+
315
+ cy.get("solid-boilerplate").then(($el) => {
316
+ const component = $el[0] as unknown as MockedSolidBoilerplate;
317
+ const arr = [user];
318
+ const result = component._normalizeLdpContains(arr);
319
+ expect(result).to.equal(arr);
320
+ });
321
+ });
322
+
323
+ it("should return empty array for null", () => {
324
+ cy.mount(html`<solid-boilerplate></solid-boilerplate>`);
325
+
326
+ cy.get("solid-boilerplate").then(($el) => {
327
+ const component = $el[0] as unknown as MockedSolidBoilerplate;
328
+ const result = component._normalizeLdpContains(null);
329
+ expect(result).to.be.an("array");
330
+ expect(result).to.have.length(0);
331
+ });
332
+ });
333
+ });
334
+
335
+ describe("_expandContainer method", () => {
336
+ it("should expand container with resources", () => {
337
+ cy.mount(html`<solid-boilerplate></solid-boilerplate>`);
338
+
339
+ cy.get("solid-boilerplate")
340
+ .then(($el) => {
341
+ const component = $el[0] as unknown as MockedSolidBoilerplate;
342
+ const resources = [user, user];
343
+ return component._expandContainer(resources);
344
+ })
345
+ .then(() => {
346
+ expect(true).to.be.true;
347
+ });
348
+ });
349
+
350
+ it("should expand container with recursive false", () => {
351
+ cy.mount(html`<solid-boilerplate></solid-boilerplate>`);
352
+
353
+ cy.get("solid-boilerplate")
354
+ .then(($el) => {
355
+ const component = $el[0] as unknown as MockedSolidBoilerplate;
356
+ const resources = [user];
357
+ return component._expandContainer(resources, false);
358
+ })
359
+ .then(() => {
360
+ expect(true).to.be.true;
361
+ });
362
+ });
363
+
364
+ it("should expand container with custom targetProperties", () => {
365
+ cy.mount(html`<solid-boilerplate></solid-boilerplate>`);
366
+
367
+ cy.get("solid-boilerplate")
368
+ .then(($el) => {
369
+ const component = $el[0] as unknown as MockedSolidBoilerplate;
370
+ const resources = [user];
371
+ const targetProperties: PropertiesPicker[] = [
372
+ { key: "name", value: "name" },
373
+ ];
374
+ return component._expandContainer(resources, true, targetProperties);
375
+ })
376
+ .then(() => {
377
+ expect(true).to.be.true;
378
+ });
379
+ });
380
+ });
381
+
382
+ describe("_getProperties method", () => {
383
+ it("should get properties from resource", () => {
384
+ cy.mount(html`<solid-boilerplate></solid-boilerplate>`);
385
+
386
+ cy.get("solid-boilerplate")
387
+ .then(($el) => {
388
+ const component = $el[0] as unknown as MockedSolidBoilerplate;
389
+ const mockResource = {
390
+ "@id": "https://example.com/resource",
391
+ "@type": "foaf:user",
392
+ properties: Promise.resolve(["name", "email"]),
393
+ get: (key: string) => {
394
+ if (key === "name") return Promise.resolve("John Doe");
395
+ if (key === "email") return Promise.resolve("john@example.com");
396
+ return Promise.resolve(undefined);
397
+ },
398
+ } as any;
399
+
400
+ const cherryPickedProperties: PropertiesPicker[] = [
401
+ { key: "name", value: "name" },
402
+ { key: "email", value: "email" },
403
+ ];
404
+
405
+ return component._getProperties(
406
+ mockResource,
407
+ true,
408
+ cherryPickedProperties,
409
+ );
410
+ })
411
+ .then(() => {
412
+ expect(true).to.be.true;
413
+ });
414
+ });
415
+
416
+ it("should expand nested properties", () => {
417
+ cy.mount(html`<solid-boilerplate></solid-boilerplate>`);
418
+
419
+ cy.get("solid-boilerplate")
420
+ .then(($el) => {
421
+ const component = $el[0] as unknown as MockedSolidBoilerplate;
422
+ const mockNestedResource = {
423
+ "@id": "https://example.com/nested",
424
+ "@type": "foaf:user",
425
+ };
426
+ const mockResource = {
427
+ "@id": "https://example.com/resource",
428
+ "@type": "foaf:user",
429
+ properties: Promise.resolve(["nested"]),
430
+ get: (key: string) => {
431
+ if (key === "nested") return Promise.resolve(mockNestedResource);
432
+ return Promise.resolve(undefined);
433
+ },
434
+ } as any;
435
+
436
+ const cherryPickedProperties: PropertiesPicker[] = [
437
+ { key: "nested", value: "nested", expand: true },
438
+ ];
439
+
440
+ return component._getProperties(
441
+ mockResource,
442
+ true,
443
+ cherryPickedProperties,
444
+ );
445
+ })
446
+ .then(() => {
447
+ expect(true).to.be.true;
448
+ });
449
+ });
450
+
451
+ it("should cast property values", () => {
452
+ cy.mount(html`<solid-boilerplate></solid-boilerplate>`);
453
+
454
+ cy.get("solid-boilerplate").then(($el) => {
455
+ const component = $el[0] as unknown as MockedSolidBoilerplate;
456
+ const mockResource = {
457
+ "@id": "https://example.com/resource",
458
+ "@type": "foaf:user",
459
+ properties: Promise.resolve(["date"]),
460
+ get: () => Promise.resolve("2024-01-01"),
461
+ } as any;
462
+
463
+ const cherryPickedProperties: PropertiesPicker[] = [
464
+ {
465
+ key: "date",
466
+ value: "formattedDate",
467
+ cast: (val: any) => `CAST: ${val}`,
468
+ },
469
+ ];
470
+
471
+ cy.wrap(
472
+ component._getProperties(mockResource, true, cherryPickedProperties),
473
+ ).then((result) => {
474
+ const typedResult = result as Resource;
475
+ expect(typedResult).to.have.property("formattedDate");
476
+ expect(typedResult.formattedDate).to.equal("CAST: 2024-01-01");
477
+ });
478
+ });
479
+ });
480
+ });
481
+
482
+ describe("_hasCherryPickedProperties method", () => {
483
+ it("should return true if resource has cherry picked properties", () => {
484
+ cy.mount(html`<solid-boilerplate></solid-boilerplate>`);
485
+
486
+ cy.get("solid-boilerplate")
487
+ .then(($el) => {
488
+ const component = $el[0] as unknown as MockedSolidBoilerplate;
489
+ const mockResource = {
490
+ "@id": "https://example.com/resource",
491
+ properties: Promise.resolve(["name", "email"]),
492
+ } as any;
493
+
494
+ return component._hasCherryPickedProperties(mockResource);
495
+ })
496
+ .then((result) => {
497
+ expect(result).to.be.true;
498
+ });
499
+ });
500
+
501
+ it("should return false if resource has no cherry picked properties", () => {
502
+ cy.mount(html`<solid-boilerplate></solid-boilerplate>`);
503
+
504
+ cy.get("solid-boilerplate")
505
+ .then(($el) => {
506
+ const component = $el[0] as unknown as MockedSolidBoilerplate;
507
+ const mockResource = {
508
+ "@id": "https://example.com/resource",
509
+ properties: Promise.resolve(["other", "stuff"]),
510
+ } as any;
511
+
512
+ return component._hasCherryPickedProperties(mockResource);
513
+ })
514
+ .then((result) => {
515
+ expect(result).to.be.false;
516
+ });
517
+ });
518
+ });
519
+
520
+ describe("_getProxyValue method", () => {
521
+ it("should get proxy value from URL string", () => {
522
+ cy.mount(html`<solid-boilerplate></solid-boilerplate>`);
523
+
524
+ cy.get("solid-boilerplate")
525
+ .then(($el) => {
526
+ const component = $el[0] as unknown as MockedSolidBoilerplate;
527
+ return component._getProxyValue("https://example.com/resource");
528
+ })
529
+ .then(() => {
530
+ expect(true).to.be.true;
531
+ });
532
+ });
533
+
534
+ it("should get proxy value from resource object", () => {
535
+ cy.mount(html`<solid-boilerplate></solid-boilerplate>`);
536
+
537
+ cy.get("solid-boilerplate")
538
+ .then(($el) => {
539
+ const component = $el[0] as unknown as MockedSolidBoilerplate;
540
+ const mockResource = {
541
+ "@id": "https://example.com/resource",
542
+ "@type": "foaf:user",
543
+ isFullResource: () => true,
544
+ properties: Promise.resolve(["name"]),
545
+ get: () => Promise.resolve("John"),
546
+ } as any;
547
+
548
+ return component._getProxyValue(mockResource);
549
+ })
550
+ .then(() => {
551
+ expect(true).to.be.true;
552
+ });
553
+ });
554
+
555
+ it("should handle container resources", () => {
556
+ cy.mount(html`<solid-boilerplate></solid-boilerplate>`);
557
+
558
+ cy.get("solid-boilerplate")
559
+ .then(($el) => {
560
+ const component = $el[0] as unknown as MockedSolidBoilerplate;
561
+ const mockContainer = {
562
+ "@id": "https://example.com/container",
563
+ "@type": "ldp:Container",
564
+ isContainer: () => true,
565
+ "ldp:contains": Promise.resolve([user]),
566
+ } as any;
567
+
568
+ return component._getProxyValue(mockContainer);
569
+ })
570
+ .then(() => {
571
+ expect(true).to.be.true;
572
+ });
573
+ });
574
+
575
+ it("should handle recursive parameter", () => {
576
+ cy.mount(html`<solid-boilerplate></solid-boilerplate>`);
577
+
578
+ cy.get("solid-boilerplate")
579
+ .then(($el) => {
580
+ const component = $el[0] as unknown as MockedSolidBoilerplate;
581
+ const mockResource = {
582
+ "@id": "https://example.com/resource",
583
+ isFullResource: () => true,
584
+ } as any;
585
+
586
+ return component._getProxyValue(mockResource, false);
587
+ })
588
+ .then(() => {
589
+ expect(true).to.be.true;
590
+ });
591
+ });
592
+
593
+ it("should handle custom targetProperties", () => {
594
+ cy.mount(html`<solid-boilerplate></solid-boilerplate>`);
595
+
596
+ cy.get("solid-boilerplate")
597
+ .then(($el) => {
598
+ const component = $el[0] as unknown as MockedSolidBoilerplate;
599
+ const mockResource = {
600
+ "@id": "https://example.com/resource",
601
+ isFullResource: () => true,
602
+ } as any;
603
+
604
+ const targetProperties: PropertiesPicker[] = [
605
+ { key: "custom", value: "custom" },
606
+ ];
607
+
608
+ return component._getProxyValue(mockResource, true, targetProperties);
609
+ })
610
+ .then(() => {
611
+ expect(true).to.be.true;
612
+ });
613
+ });
614
+ });
615
+
616
+ describe("_responseAdaptator method", () => {
617
+ it("should adapt response", () => {
618
+ cy.mount(html`<solid-boilerplate></solid-boilerplate>`);
619
+
620
+ cy.get("solid-boilerplate")
621
+ .then(($el) => {
622
+ const component = $el[0] as unknown as MockedSolidBoilerplate;
623
+ const mockResponse = {
624
+ "@id": "https://example.com/resource",
625
+ name: "Test",
626
+ } as Resource;
627
+
628
+ return component._responseAdaptator(mockResponse);
629
+ })
630
+ .then(() => {
631
+ expect(true).to.be.true;
632
+ });
633
+ });
634
+
635
+ it("should allow override in subclass", () => {
636
+ cy.mount(html`<solid-boilerplate></solid-boilerplate>`);
637
+
638
+ cy.get("solid-boilerplate").then(($el) => {
639
+ const component = $el[0] as unknown as MockedSolidBoilerplate;
640
+ expect(component._responseAdaptator).to.be.a("function");
641
+ });
642
+ });
643
+ });
644
+
645
+ describe("gatekeeper method", () => {
646
+ it("should return nothing when orbit is not available", () => {
647
+ cy.window().then((win) => {
648
+ (win as any).orbit = undefined;
649
+ });
650
+
651
+ cy.mount(html`<solid-boilerplate></solid-boilerplate>`);
652
+
653
+ cy.get("solid-boilerplate").then(($el) => {
654
+ const component = $el[0] as unknown as MockedSolidBoilerplate;
655
+ const result = component.gatekeeper();
656
+ expect(result).to.equal(nothing);
657
+ });
658
+ });
659
+
660
+ it("should return nothing when dataSrc is not set", () => {
661
+ cy.mount(html`<solid-boilerplate></solid-boilerplate>`);
662
+
663
+ cy.get("solid-boilerplate").then(($el) => {
664
+ const component = $el[0] as unknown as MockedSolidBoilerplate;
665
+ const result = component.gatekeeper();
666
+ expect(result).to.equal(nothing);
667
+ });
668
+ });
669
+
670
+ it("should allow render when route starts with currentRoute", () => {
671
+ cy.mount(
672
+ html`<solid-boilerplate
673
+ data-src="https://example.com/data"
674
+ route="/my-route"
675
+ ></solid-boilerplate>`,
676
+ );
677
+
678
+ cy.get("solid-boilerplate").then(($el) => {
679
+ const component = $el[0] as unknown as MockedSolidBoilerplate;
680
+ component.currentRoute = "/my";
681
+ const result = component.gatekeeper();
682
+ expect(result).to.be.undefined;
683
+ });
684
+ });
685
+
686
+ it("should allow render when route equals currentRoute", () => {
687
+ cy.mount(
688
+ html`<solid-boilerplate
689
+ data-src="https://example.com/data"
690
+ route="/my-route"
691
+ ></solid-boilerplate>`,
692
+ );
693
+
694
+ cy.get("solid-boilerplate").then(($el) => {
695
+ const component = $el[0] as unknown as MockedSolidBoilerplate;
696
+ component.currentRoute = "/my-route";
697
+ const result = component.gatekeeper();
698
+ expect(result).to.be.undefined;
699
+ });
700
+ });
701
+ });
702
+
703
+ describe("hasType method (from ComponentObjectsHandler)", () => {
704
+ it("should return true if objects contain type", () => {
705
+ cy.mount(html`<solid-boilerplate></solid-boilerplate>`);
706
+
707
+ cy.get("solid-boilerplate").then(($el) => {
708
+ const component = $el[0] as unknown as MockedSolidBoilerplate;
709
+ component.objects = [user];
710
+ const result = component.hasType("foaf:user");
711
+ expect(result).to.be.true;
712
+ });
713
+ });
714
+
715
+ it("should return false if objects don't contain type", () => {
716
+ cy.mount(html`<solid-boilerplate></solid-boilerplate>`);
717
+
718
+ cy.get("solid-boilerplate").then(($el) => {
719
+ const component = $el[0] as unknown as MockedSolidBoilerplate;
720
+ component.objects = [user];
721
+ const result = component.hasType("foaf:group");
722
+ expect(result).to.be.false;
723
+ });
724
+ });
725
+
726
+ it("should work with array types", () => {
727
+ cy.mount(html`<solid-boilerplate></solid-boilerplate>`);
728
+
729
+ cy.get("solid-boilerplate").then(($el) => {
730
+ const component = $el[0] as unknown as MockedSolidBoilerplate;
731
+ const multiTypeUser = {
732
+ ...user,
733
+ "@type": ["foaf:user", "schema:Person"],
734
+ };
735
+ component.objects = [multiTypeUser];
736
+ expect(component.hasType("schema:Person")).to.be.true;
737
+ expect(component.hasType("foaf:group")).to.be.false;
738
+ });
739
+ });
740
+
741
+ it("should accept custom objects parameter", () => {
742
+ cy.mount(html`<solid-boilerplate></solid-boilerplate>`);
743
+
744
+ cy.get("solid-boilerplate").then(($el) => {
745
+ const component = $el[0] as unknown as MockedSolidBoilerplate;
746
+ const customObjects = [user];
747
+ const result = component.hasType("foaf:user", customObjects);
748
+ expect(result).to.be.true;
749
+ });
750
+ });
751
+
752
+ it("should handle empty objects array", () => {
753
+ cy.mount(html`<solid-boilerplate></solid-boilerplate>`);
754
+
755
+ cy.get("solid-boilerplate").then(($el) => {
756
+ const component = $el[0] as unknown as MockedSolidBoilerplate;
757
+ component.objects = [];
758
+ const result = component.hasType("foaf:user");
759
+ expect(result).to.be.false;
760
+ });
761
+ });
762
+ });
763
+
764
+ describe("Integration tests", () => {
765
+ it("should mount component", () => {
766
+ cy.mount(html`<solid-boilerplate></solid-boilerplate>`);
767
+
768
+ cy.get("solid-boilerplate").should("exist");
769
+ });
770
+
771
+ it("should have red background div", () => {
772
+ cy.mount(
773
+ html`<solid-boilerplate
774
+ data-src="https://example.com/data"
775
+ no-router
776
+ route="/data"
777
+ ></solid-boilerplate>`,
778
+ );
779
+
780
+ cy.get("solid-boilerplate").then(($el) => {
781
+ const component = $el[0] as unknown as MockedSolidBoilerplate;
782
+ component.datas = [user];
783
+ component.currentRoute = "/data";
784
+ (component as any).requestUpdate();
785
+ });
786
+
787
+ cy.get("solid-boilerplate")
788
+ .shadow()
789
+ .find("div")
790
+ .should("have.css", "background-color")
791
+ .and("eq", "rgb(255, 0, 0)");
792
+ });
793
+
794
+ it("should show loader when loading", () => {
795
+ cy.mount(
796
+ html`<solid-boilerplate
797
+ data-src="https://example.com/data"
798
+ no-router
799
+ route="/data"
800
+ ></solid-boilerplate>`,
801
+ );
802
+
803
+ cy.get("solid-boilerplate").then(($el) => {
804
+ const component = $el[0] as unknown as MockedSolidBoilerplate;
805
+ cy.stub(component._getResource, "render").callsFake((obj: any) => {
806
+ return obj.pending();
807
+ });
808
+ component.currentRoute = "/data";
809
+ (component as any).requestUpdate();
810
+ });
811
+
812
+ cy.get("solid-boilerplate").shadow().find("solid-loader").should("exist");
813
+ });
814
+
815
+ it("should render sample-objects when data is loaded", () => {
816
+ cy.mount(
817
+ html`<solid-boilerplate
818
+ data-src="https://example.com/data"
819
+ no-router
820
+ route="/data"
821
+ ></solid-boilerplate>`,
822
+ );
823
+
824
+ cy.get("solid-boilerplate").then(($el) => {
825
+ const component = $el[0] as unknown as MockedSolidBoilerplate;
826
+ component.datas = [user];
827
+ component.currentRoute = "/data";
828
+ (component as any).requestUpdate();
829
+ });
830
+
831
+ cy.get("solid-boilerplate")
832
+ .shadow()
833
+ .find("sample-objects")
834
+ .should("exist");
835
+ });
836
+ });
837
+
838
+ describe("Orbit integration", () => {
839
+ it("should get component from orbit via route", () => {
840
+ cy.window().then((win) => {
841
+ const mockOrbit = {
842
+ ...orbit,
843
+ components: [
844
+ {
845
+ uniq: "test-component",
846
+ route: "/test",
847
+ parameters: {},
848
+ },
849
+ ],
850
+ getComponentFromRoute: (route: string) => {
851
+ return mockOrbit.components?.find((c) => c.route === route);
852
+ },
853
+ };
854
+ win.orbit = mockOrbit as any;
855
+ });
856
+
857
+ cy.mount(html`<solid-boilerplate route="/test"></solid-boilerplate>`);
858
+
859
+ cy.get("solid-boilerplate").then(($el) => {
860
+ const component = $el[0] as unknown as MockedSolidBoilerplate;
861
+ expect(component.orbit?.getComponentFromRoute("/test")).to.exist;
862
+ });
863
+ });
864
+ });
865
+
866
+ describe("Error handling", () => {
867
+ it("should handle invalid resource gracefully", () => {
868
+ cy.mount(html`<solid-boilerplate></solid-boilerplate>`);
869
+
870
+ cy.get("solid-boilerplate")
871
+ .then(($el) => {
872
+ const component = $el[0] as unknown as MockedSolidBoilerplate;
873
+ return component._getProxyValue(null);
874
+ })
875
+ .then(() => {
876
+ expect(true).to.be.true;
877
+ });
878
+ });
879
+
880
+ it("should handle missing properties", () => {
881
+ cy.mount(html`<solid-boilerplate></solid-boilerplate>`);
882
+
883
+ cy.get("solid-boilerplate")
884
+ .then(($el) => {
885
+ const component = $el[0] as unknown as MockedSolidBoilerplate;
886
+ const mockResource = {
887
+ "@id": "https://example.com/resource",
888
+ properties: Promise.resolve([]),
889
+ } as any;
890
+
891
+ return component._getProperties(mockResource);
892
+ })
893
+ .then(() => {
894
+ expect(true).to.be.true;
895
+ });
896
+ });
8
897
  });
9
898
  });