@scality/data-browser-library 1.0.0-preview.11 → 1.0.0-preview.13

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 (40) hide show
  1. package/dist/components/DataBrowserUI.d.ts +20 -0
  2. package/dist/components/DataBrowserUI.js +64 -0
  3. package/dist/components/__tests__/BucketDetails.test.d.ts +1 -0
  4. package/dist/components/__tests__/BucketDetails.test.js +421 -0
  5. package/dist/components/__tests__/BucketList.test.js +389 -164
  6. package/dist/components/__tests__/BucketOverview.test.js +19 -63
  7. package/dist/components/__tests__/ObjectList.test.js +719 -219
  8. package/dist/components/buckets/BucketDetails.d.ts +40 -0
  9. package/dist/components/buckets/BucketDetails.js +194 -86
  10. package/dist/components/buckets/BucketList.d.ts +5 -6
  11. package/dist/components/buckets/BucketList.js +152 -97
  12. package/dist/components/buckets/BucketOverview.d.ts +6 -0
  13. package/dist/components/buckets/BucketOverview.js +363 -179
  14. package/dist/components/buckets/BucketPage.js +1 -5
  15. package/dist/components/buckets/BucketVersioning.js +3 -0
  16. package/dist/components/buckets/EmptyBucketButton.js +1 -1
  17. package/dist/components/index.d.ts +2 -1
  18. package/dist/components/index.js +2 -1
  19. package/dist/components/layouts/ArrowNavigation.js +20 -8
  20. package/dist/components/objects/CreateFolderButton.js +1 -1
  21. package/dist/components/objects/ObjectDetails/ObjectSummary.js +287 -157
  22. package/dist/components/objects/ObjectDetails/__tests__/ObjectDetails.test.d.ts +1 -0
  23. package/dist/components/objects/ObjectDetails/__tests__/ObjectDetails.test.js +516 -0
  24. package/dist/components/objects/ObjectDetails/__tests__/ObjectSummary.test.d.ts +1 -0
  25. package/dist/components/objects/ObjectDetails/__tests__/ObjectSummary.test.js +813 -0
  26. package/dist/components/objects/ObjectDetails/index.d.ts +16 -0
  27. package/dist/components/objects/ObjectDetails/index.js +132 -46
  28. package/dist/components/objects/ObjectList.d.ts +7 -5
  29. package/dist/components/objects/ObjectList.js +566 -286
  30. package/dist/components/objects/UploadButton.js +1 -1
  31. package/dist/config/types.d.ts +117 -0
  32. package/dist/contexts/DataBrowserUICustomizationContext.d.ts +27 -0
  33. package/dist/contexts/DataBrowserUICustomizationContext.js +13 -0
  34. package/dist/test/testUtils.d.ts +64 -0
  35. package/dist/test/testUtils.js +100 -1
  36. package/dist/types/index.d.ts +5 -3
  37. package/dist/utils/constants.d.ts +7 -0
  38. package/dist/utils/constants.js +8 -1
  39. package/dist/utils/useFeatures.js +1 -1
  40. package/package.json +2 -2
@@ -0,0 +1,516 @@
1
+ import * as __WEBPACK_EXTERNAL_MODULE__index_js_95fdb65a__ from "../index.js";
2
+ import { jsx } from "react/jsx-runtime";
3
+ import { cleanup, render, screen } from "@testing-library/react";
4
+ import { MemoryRouter, Route, Routes } from "react-router-dom";
5
+ import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
6
+ import { DataBrowserUICustomizationProvider } from "../../../../contexts/DataBrowserUICustomizationContext.js";
7
+ var __webpack_modules__ = {
8
+ "../index": function(module) {
9
+ module.exports = __WEBPACK_EXTERNAL_MODULE__index_js_95fdb65a__;
10
+ }
11
+ };
12
+ var __webpack_module_cache__ = {};
13
+ function __webpack_require__(moduleId) {
14
+ var cachedModule = __webpack_module_cache__[moduleId];
15
+ if (void 0 !== cachedModule) return cachedModule.exports;
16
+ var module = __webpack_module_cache__[moduleId] = {
17
+ exports: {}
18
+ };
19
+ __webpack_modules__[moduleId](module, module.exports, __webpack_require__);
20
+ return module.exports;
21
+ }
22
+ var external_index_js_ = __webpack_require__("../index");
23
+ jest.mock("../ObjectSummary", ()=>({
24
+ ObjectSummary: ()=>/*#__PURE__*/ jsx("div", {
25
+ "data-testid": "object-summary",
26
+ children: "ObjectSummary"
27
+ })
28
+ }));
29
+ jest.mock("../ObjectMetadata", ()=>({
30
+ ObjectMetadata: ()=>/*#__PURE__*/ jsx("div", {
31
+ "data-testid": "object-metadata",
32
+ children: "ObjectMetadata"
33
+ })
34
+ }));
35
+ jest.mock("../ObjectTags", ()=>({
36
+ ObjectTags: ()=>/*#__PURE__*/ jsx("div", {
37
+ "data-testid": "object-tags",
38
+ children: "ObjectTags"
39
+ })
40
+ }));
41
+ const createMockObjectItem = (overrides)=>({
42
+ Key: "test-object.txt",
43
+ LastModified: new Date("2024-01-01"),
44
+ Size: 1024,
45
+ type: "object",
46
+ displayName: "test-object.txt",
47
+ ...overrides
48
+ });
49
+ const createMockVersionItem = ()=>({
50
+ Key: "test-object.txt",
51
+ VersionId: "version-123",
52
+ LastModified: new Date("2024-01-01"),
53
+ Size: 1024,
54
+ type: "version",
55
+ displayName: "test-object.txt",
56
+ IsLatest: true
57
+ });
58
+ const createMockFolderItem = ()=>({
59
+ Key: "test-folder/",
60
+ type: "folder",
61
+ displayName: "test-folder/"
62
+ });
63
+ const createMockDeleteMarkerItem = ()=>({
64
+ Key: "deleted-object.txt",
65
+ VersionId: "delete-marker-123",
66
+ LastModified: new Date("2024-01-01"),
67
+ type: "deleteMarker",
68
+ displayName: "deleted-object.txt",
69
+ IsLatest: true,
70
+ isDeleteMarker: true
71
+ });
72
+ const renderWithProviders = (ui, { initialRoute = "/buckets/test-bucket/objects", customizationConfig = {} } = {})=>{
73
+ const queryClient = new QueryClient({
74
+ defaultOptions: {
75
+ queries: {
76
+ retry: false
77
+ },
78
+ mutations: {
79
+ retry: false
80
+ }
81
+ }
82
+ });
83
+ return render(/*#__PURE__*/ jsx(QueryClientProvider, {
84
+ client: queryClient,
85
+ children: /*#__PURE__*/ jsx(DataBrowserUICustomizationProvider, {
86
+ config: customizationConfig,
87
+ children: /*#__PURE__*/ jsx(MemoryRouter, {
88
+ initialEntries: [
89
+ initialRoute
90
+ ],
91
+ children: /*#__PURE__*/ jsx(Routes, {
92
+ children: /*#__PURE__*/ jsx(Route, {
93
+ path: "/buckets/:bucketName/objects",
94
+ element: ui
95
+ })
96
+ })
97
+ })
98
+ })
99
+ }));
100
+ };
101
+ describe("ObjectDetails", ()=>{
102
+ describe("Default Tabs", ()=>{
103
+ it("should render three default tabs", ()=>{
104
+ const item = createMockObjectItem();
105
+ renderWithProviders(/*#__PURE__*/ jsx(external_index_js_.ObjectDetails, {
106
+ item: item
107
+ }));
108
+ expect(screen.getByRole("tab", {
109
+ name: /summary/i
110
+ })).toBeInTheDocument();
111
+ expect(screen.getByRole("tab", {
112
+ name: /metadata/i
113
+ })).toBeInTheDocument();
114
+ expect(screen.getByRole("tab", {
115
+ name: /tags/i
116
+ })).toBeInTheDocument();
117
+ });
118
+ it("should render Summary tab content by default", ()=>{
119
+ const item = createMockObjectItem();
120
+ renderWithProviders(/*#__PURE__*/ jsx(external_index_js_.ObjectDetails, {
121
+ item: item
122
+ }));
123
+ expect(screen.getByTestId("object-summary")).toBeInTheDocument();
124
+ });
125
+ it("should render child components when valid item is provided", ()=>{
126
+ const item = createMockObjectItem({
127
+ Key: "my-file.txt"
128
+ });
129
+ renderWithProviders(/*#__PURE__*/ jsx(external_index_js_.ObjectDetails, {
130
+ item: item
131
+ }));
132
+ expect(screen.getByTestId("object-summary")).toBeInTheDocument();
133
+ });
134
+ });
135
+ describe("Version ID handling", ()=>{
136
+ it("should pass versionId when item is a version", ()=>{
137
+ const versionItem = createMockVersionItem();
138
+ renderWithProviders(/*#__PURE__*/ jsx(external_index_js_.ObjectDetails, {
139
+ item: versionItem
140
+ }));
141
+ expect(screen.getByTestId("object-summary")).toBeInTheDocument();
142
+ });
143
+ it("should not pass versionId for regular objects", ()=>{
144
+ const item = createMockObjectItem();
145
+ renderWithProviders(/*#__PURE__*/ jsx(external_index_js_.ObjectDetails, {
146
+ item: item
147
+ }));
148
+ expect(screen.getByTestId("object-summary")).toBeInTheDocument();
149
+ });
150
+ });
151
+ describe("Placeholder States", ()=>{
152
+ it("should show placeholder when no item is selected", ()=>{
153
+ renderWithProviders(/*#__PURE__*/ jsx(external_index_js_.ObjectDetails, {
154
+ item: null
155
+ }));
156
+ expect(screen.getByText(/select an object to view details/i)).toBeInTheDocument();
157
+ });
158
+ it("should show placeholder for folder items", ()=>{
159
+ const folderItem = createMockFolderItem();
160
+ renderWithProviders(/*#__PURE__*/ jsx(external_index_js_.ObjectDetails, {
161
+ item: folderItem
162
+ }));
163
+ expect(screen.getByText(/a "folder" is selected/i)).toBeInTheDocument();
164
+ });
165
+ it("should show placeholder for delete marker items", ()=>{
166
+ const deleteMarkerItem = createMockDeleteMarkerItem();
167
+ renderWithProviders(/*#__PURE__*/ jsx(external_index_js_.ObjectDetails, {
168
+ item: deleteMarkerItem
169
+ }));
170
+ expect(screen.getByText(/a "delete marker" is selected/i)).toBeInTheDocument();
171
+ });
172
+ it("should show placeholder when item has no Key", ()=>{
173
+ const item = createMockObjectItem({
174
+ Key: void 0
175
+ });
176
+ renderWithProviders(/*#__PURE__*/ jsx(external_index_js_.ObjectDetails, {
177
+ item: item
178
+ }));
179
+ expect(screen.getByText(/select an object to view details/i)).toBeInTheDocument();
180
+ });
181
+ it("should show placeholder when item has empty Key", ()=>{
182
+ const item = createMockObjectItem({
183
+ Key: ""
184
+ });
185
+ renderWithProviders(/*#__PURE__*/ jsx(external_index_js_.ObjectDetails, {
186
+ item: item
187
+ }));
188
+ expect(screen.getByText(/select an object to view details/i)).toBeInTheDocument();
189
+ });
190
+ it("should render tabs even in placeholder state", ()=>{
191
+ renderWithProviders(/*#__PURE__*/ jsx(external_index_js_.ObjectDetails, {
192
+ item: null
193
+ }));
194
+ expect(screen.getByRole("tab", {
195
+ name: /summary/i
196
+ })).toBeInTheDocument();
197
+ expect(screen.getByRole("tab", {
198
+ name: /metadata/i
199
+ })).toBeInTheDocument();
200
+ expect(screen.getByRole("tab", {
201
+ name: /tags/i
202
+ })).toBeInTheDocument();
203
+ });
204
+ });
205
+ describe("Custom Tabs", ()=>{
206
+ it("should render extra custom tabs", ()=>{
207
+ const item = createMockObjectItem();
208
+ const customConfig = {
209
+ extraObjectTabs: [
210
+ {
211
+ id: "custom-tab",
212
+ title: "Custom Tab",
213
+ render: ()=>/*#__PURE__*/ jsx("div", {
214
+ "data-testid": "custom-tab-content",
215
+ children: "Custom Content"
216
+ })
217
+ }
218
+ ]
219
+ };
220
+ renderWithProviders(/*#__PURE__*/ jsx(external_index_js_.ObjectDetails, {
221
+ item: item
222
+ }), {
223
+ customizationConfig: customConfig
224
+ });
225
+ expect(screen.getByRole("tab", {
226
+ name: /custom tab/i
227
+ })).toBeInTheDocument();
228
+ });
229
+ it("should render custom tab in tab list", ()=>{
230
+ const item = createMockObjectItem();
231
+ const customConfig = {
232
+ extraObjectTabs: [
233
+ {
234
+ id: "versions",
235
+ title: "Versions",
236
+ render: ()=>/*#__PURE__*/ jsx("div", {
237
+ "data-testid": "versions-tab",
238
+ children: "Version History"
239
+ })
240
+ }
241
+ ]
242
+ };
243
+ renderWithProviders(/*#__PURE__*/ jsx(external_index_js_.ObjectDetails, {
244
+ item: item
245
+ }), {
246
+ customizationConfig: customConfig
247
+ });
248
+ const versionsTab = screen.getByRole("tab", {
249
+ name: /versions/i
250
+ });
251
+ expect(versionsTab).toBeInTheDocument();
252
+ });
253
+ it("should replace default tabs when custom tab has same ID", ()=>{
254
+ const item = createMockObjectItem();
255
+ const customConfig = {
256
+ extraObjectTabs: [
257
+ {
258
+ id: "summary",
259
+ title: "Custom Summary",
260
+ render: ()=>/*#__PURE__*/ jsx("div", {
261
+ "data-testid": "custom-summary",
262
+ children: "Custom Summary Content"
263
+ })
264
+ }
265
+ ]
266
+ };
267
+ renderWithProviders(/*#__PURE__*/ jsx(external_index_js_.ObjectDetails, {
268
+ item: item
269
+ }), {
270
+ customizationConfig: customConfig
271
+ });
272
+ expect(screen.getByRole("tab", {
273
+ name: /custom summary/i
274
+ })).toBeInTheDocument();
275
+ expect(screen.queryByRole("tab", {
276
+ name: /^summary$/i
277
+ })).not.toBeInTheDocument();
278
+ });
279
+ it("should support multiple custom tabs", ()=>{
280
+ const item = createMockObjectItem();
281
+ const customConfig = {
282
+ extraObjectTabs: [
283
+ {
284
+ id: "versions",
285
+ title: "Versions",
286
+ render: ()=>/*#__PURE__*/ jsx("div", {
287
+ children: "Versions"
288
+ })
289
+ },
290
+ {
291
+ id: "permissions",
292
+ title: "Permissions",
293
+ render: ()=>/*#__PURE__*/ jsx("div", {
294
+ children: "Permissions"
295
+ })
296
+ },
297
+ {
298
+ id: "activity",
299
+ title: "Activity",
300
+ render: ()=>/*#__PURE__*/ jsx("div", {
301
+ children: "Activity"
302
+ })
303
+ }
304
+ ]
305
+ };
306
+ renderWithProviders(/*#__PURE__*/ jsx(external_index_js_.ObjectDetails, {
307
+ item: item
308
+ }), {
309
+ customizationConfig: customConfig
310
+ });
311
+ expect(screen.getByRole("tab", {
312
+ name: /versions/i
313
+ })).toBeInTheDocument();
314
+ expect(screen.getByRole("tab", {
315
+ name: /permissions/i
316
+ })).toBeInTheDocument();
317
+ expect(screen.getByRole("tab", {
318
+ name: /activity/i
319
+ })).toBeInTheDocument();
320
+ });
321
+ it("should support withoutPadding option for custom tabs", ()=>{
322
+ const item = createMockObjectItem();
323
+ const customConfig = {
324
+ extraObjectTabs: [
325
+ {
326
+ id: "full-width",
327
+ title: "Full Width",
328
+ withoutPadding: true,
329
+ render: ()=>/*#__PURE__*/ jsx("div", {
330
+ "data-testid": "full-width-content",
331
+ children: "Full Width"
332
+ })
333
+ }
334
+ ]
335
+ };
336
+ renderWithProviders(/*#__PURE__*/ jsx(external_index_js_.ObjectDetails, {
337
+ item: item
338
+ }), {
339
+ customizationConfig: customConfig
340
+ });
341
+ expect(screen.getByRole("tab", {
342
+ name: /full width/i
343
+ })).toBeInTheDocument();
344
+ });
345
+ });
346
+ describe("Tab Ordering", ()=>{
347
+ it("should maintain default tab order", ()=>{
348
+ const item = createMockObjectItem();
349
+ renderWithProviders(/*#__PURE__*/ jsx(external_index_js_.ObjectDetails, {
350
+ item: item
351
+ }));
352
+ const tabs = screen.getAllByRole("tab");
353
+ expect(tabs[0]).toHaveTextContent(/summary/i);
354
+ expect(tabs[1]).toHaveTextContent(/metadata/i);
355
+ expect(tabs[2]).toHaveTextContent(/tags/i);
356
+ });
357
+ it("should append custom tabs after default tabs", ()=>{
358
+ const item = createMockObjectItem();
359
+ const customConfig = {
360
+ extraObjectTabs: [
361
+ {
362
+ id: "custom1",
363
+ title: "Custom 1",
364
+ render: ()=>/*#__PURE__*/ jsx("div", {
365
+ children: "Custom 1"
366
+ })
367
+ },
368
+ {
369
+ id: "custom2",
370
+ title: "Custom 2",
371
+ render: ()=>/*#__PURE__*/ jsx("div", {
372
+ children: "Custom 2"
373
+ })
374
+ }
375
+ ]
376
+ };
377
+ renderWithProviders(/*#__PURE__*/ jsx(external_index_js_.ObjectDetails, {
378
+ item: item
379
+ }), {
380
+ customizationConfig: customConfig
381
+ });
382
+ const tabs = screen.getAllByRole("tab");
383
+ expect(tabs[0]).toHaveTextContent(/summary/i);
384
+ expect(tabs[1]).toHaveTextContent(/metadata/i);
385
+ expect(tabs[2]).toHaveTextContent(/tags/i);
386
+ expect(tabs[3]).toHaveTextContent(/custom 1/i);
387
+ expect(tabs[4]).toHaveTextContent(/custom 2/i);
388
+ });
389
+ });
390
+ describe("Context Provider", ()=>{
391
+ it("should render child components when context is provided", ()=>{
392
+ const item = createMockObjectItem({
393
+ Key: "test-file.txt"
394
+ });
395
+ renderWithProviders(/*#__PURE__*/ jsx(external_index_js_.ObjectDetails, {
396
+ item: item
397
+ }));
398
+ expect(screen.getByTestId("object-summary")).toBeInTheDocument();
399
+ });
400
+ it("should throw error when useObjectDetailsContext is used outside provider", ()=>{
401
+ const { useObjectDetailsContext } = __webpack_require__("../index");
402
+ const TestComponent = ()=>{
403
+ useObjectDetailsContext();
404
+ return null;
405
+ };
406
+ const originalError = console.error;
407
+ console.error = jest.fn();
408
+ expect(()=>{
409
+ render(/*#__PURE__*/ jsx(QueryClientProvider, {
410
+ client: new QueryClient(),
411
+ children: /*#__PURE__*/ jsx(TestComponent, {})
412
+ }));
413
+ }).toThrow("ObjectDetails components must be used within ObjectDetails");
414
+ console.error = originalError;
415
+ });
416
+ it("should provide correct context values to nested components", ()=>{
417
+ const item = createMockObjectItem({
418
+ Key: "context-test.txt"
419
+ });
420
+ renderWithProviders(/*#__PURE__*/ jsx(external_index_js_.ObjectDetails, {
421
+ item: item
422
+ }));
423
+ expect(screen.getByTestId("object-summary")).toBeInTheDocument();
424
+ });
425
+ });
426
+ describe("Edge Cases", ()=>{
427
+ it("should handle missing bucketName in route", ()=>{
428
+ const item = createMockObjectItem();
429
+ const queryClient = new QueryClient();
430
+ render(/*#__PURE__*/ jsx(QueryClientProvider, {
431
+ client: queryClient,
432
+ children: /*#__PURE__*/ jsx(DataBrowserUICustomizationProvider, {
433
+ config: {},
434
+ children: /*#__PURE__*/ jsx(MemoryRouter, {
435
+ initialEntries: [
436
+ "/invalid-route"
437
+ ],
438
+ children: /*#__PURE__*/ jsx(Routes, {
439
+ children: /*#__PURE__*/ jsx(Route, {
440
+ path: "/invalid-route",
441
+ element: /*#__PURE__*/ jsx(external_index_js_.ObjectDetails, {
442
+ item: item
443
+ })
444
+ })
445
+ })
446
+ })
447
+ })
448
+ }));
449
+ expect(screen.getByText(/select an object to view details/i)).toBeInTheDocument();
450
+ });
451
+ it("should handle item type changes", ()=>{
452
+ renderWithProviders(/*#__PURE__*/ jsx(external_index_js_.ObjectDetails, {
453
+ item: createMockObjectItem()
454
+ }));
455
+ expect(screen.getByTestId("object-summary")).toBeInTheDocument();
456
+ cleanup();
457
+ renderWithProviders(/*#__PURE__*/ jsx(external_index_js_.ObjectDetails, {
458
+ item: createMockFolderItem()
459
+ }));
460
+ expect(screen.getByText(/a "folder" is selected/i)).toBeInTheDocument();
461
+ });
462
+ it("should memoize tabs content efficiently", ()=>{
463
+ const item = createMockObjectItem();
464
+ renderWithProviders(/*#__PURE__*/ jsx(external_index_js_.ObjectDetails, {
465
+ item: item
466
+ }));
467
+ screen.getByTestId("object-summary");
468
+ cleanup();
469
+ renderWithProviders(/*#__PURE__*/ jsx(external_index_js_.ObjectDetails, {
470
+ item: item
471
+ }));
472
+ expect(screen.getByTestId("object-summary")).toBeInTheDocument();
473
+ });
474
+ });
475
+ describe("Performance", ()=>{
476
+ it("should not recreate context value unnecessarily", ()=>{
477
+ const item = createMockObjectItem({
478
+ Key: "same-key.txt"
479
+ });
480
+ renderWithProviders(/*#__PURE__*/ jsx(external_index_js_.ObjectDetails, {
481
+ item: item
482
+ }));
483
+ screen.getByTestId("object-summary");
484
+ cleanup();
485
+ const sameKeyItem = createMockObjectItem({
486
+ Key: "same-key.txt"
487
+ });
488
+ renderWithProviders(/*#__PURE__*/ jsx(external_index_js_.ObjectDetails, {
489
+ item: sameKeyItem
490
+ }));
491
+ expect(screen.getByTestId("object-summary")).toBeInTheDocument();
492
+ });
493
+ it("should handle rapid item changes", ()=>{
494
+ renderWithProviders(/*#__PURE__*/ jsx(external_index_js_.ObjectDetails, {
495
+ item: createMockObjectItem({
496
+ Key: "file1.txt"
497
+ })
498
+ }));
499
+ expect(screen.getByTestId("object-summary")).toBeInTheDocument();
500
+ cleanup();
501
+ renderWithProviders(/*#__PURE__*/ jsx(external_index_js_.ObjectDetails, {
502
+ item: createMockObjectItem({
503
+ Key: "file2.txt"
504
+ })
505
+ }));
506
+ expect(screen.getByTestId("object-summary")).toBeInTheDocument();
507
+ cleanup();
508
+ renderWithProviders(/*#__PURE__*/ jsx(external_index_js_.ObjectDetails, {
509
+ item: createMockObjectItem({
510
+ Key: "file3.txt"
511
+ })
512
+ }));
513
+ expect(screen.getByTestId("object-summary")).toBeInTheDocument();
514
+ });
515
+ });
516
+ });