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

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 (212) hide show
  1. package/dist/components/DataBrowserUI.d.ts +27 -0
  2. package/dist/components/DataBrowserUI.js +88 -0
  3. package/dist/components/Editor.d.ts +1 -1
  4. package/dist/components/Editor.js +3 -3
  5. package/dist/components/__tests__/BucketCreate.test.js +102 -102
  6. package/dist/components/__tests__/BucketDetails.test.d.ts +1 -0
  7. package/dist/components/__tests__/BucketDetails.test.js +420 -0
  8. package/dist/components/__tests__/BucketLifecycleFormPage.test.js +177 -177
  9. package/dist/components/__tests__/BucketLifecycleList.test.js +85 -85
  10. package/dist/components/__tests__/BucketList.test.js +463 -239
  11. package/dist/components/__tests__/BucketNotificationCreatePage.test.js +84 -84
  12. package/dist/components/__tests__/BucketOverview.test.js +273 -261
  13. package/dist/components/__tests__/BucketPolicyPage.test.js +62 -62
  14. package/dist/components/__tests__/BucketReplicationFormPage.test.js +542 -542
  15. package/dist/components/__tests__/BucketReplicationList.test.js +106 -106
  16. package/dist/components/__tests__/CreateFolderButton.test.js +56 -56
  17. package/dist/components/__tests__/DeleteBucketButton.test.js +62 -62
  18. package/dist/components/__tests__/DeleteBucketConfigRuleButton.test.js +47 -47
  19. package/dist/components/__tests__/DeleteObjectButton.test.js +63 -63
  20. package/dist/components/__tests__/EmptyBucketButton.test.js +56 -56
  21. package/dist/components/__tests__/MetadataSearch.test.js +65 -65
  22. package/dist/components/__tests__/ObjectList.test.js +739 -238
  23. package/dist/components/__tests__/UploadButton.test.js +45 -45
  24. package/dist/components/buckets/BucketCreate.d.ts +2 -2
  25. package/dist/components/buckets/BucketCreate.js +41 -41
  26. package/dist/components/buckets/BucketDetails.d.ts +40 -0
  27. package/dist/components/buckets/BucketDetails.js +208 -88
  28. package/dist/components/buckets/BucketLifecycleFormPage.js +161 -160
  29. package/dist/components/buckets/BucketLifecycleList.d.ts +2 -2
  30. package/dist/components/buckets/BucketLifecycleList.js +46 -46
  31. package/dist/components/buckets/BucketList.d.ts +7 -8
  32. package/dist/components/buckets/BucketList.js +156 -100
  33. package/dist/components/buckets/BucketLocation.js +3 -3
  34. package/dist/components/buckets/BucketOverview.d.ts +7 -1
  35. package/dist/components/buckets/BucketOverview.js +366 -182
  36. package/dist/components/buckets/BucketPage.js +20 -16
  37. package/dist/components/buckets/BucketPolicyButton.js +2 -2
  38. package/dist/components/buckets/BucketPolicyPage.js +27 -25
  39. package/dist/components/buckets/BucketReplicationFormPage.js +133 -132
  40. package/dist/components/buckets/BucketReplicationList.d.ts +2 -2
  41. package/dist/components/buckets/BucketReplicationList.js +41 -41
  42. package/dist/components/buckets/BucketVersioning.js +13 -10
  43. package/dist/components/buckets/DeleteBucketButton.js +5 -5
  44. package/dist/components/buckets/DeleteBucketConfigRuleButton.d.ts +2 -2
  45. package/dist/components/buckets/DeleteBucketConfigRuleButton.js +1 -1
  46. package/dist/components/buckets/EmptyBucketButton.js +20 -20
  47. package/dist/components/buckets/EmptyBucketSummary.d.ts +1 -1
  48. package/dist/components/buckets/EmptyBucketSummary.js +1 -1
  49. package/dist/components/buckets/EmptyBucketSummaryList.js +22 -22
  50. package/dist/components/buckets/__tests__/BucketVersioning.test.js +45 -45
  51. package/dist/components/buckets/notifications/BucketNotificationCreatePage.js +34 -33
  52. package/dist/components/buckets/notifications/EventsSection.js +144 -28
  53. package/dist/components/buckets/notifications/__tests__/events.test.d.ts +1 -0
  54. package/dist/components/buckets/notifications/__tests__/events.test.js +56 -0
  55. package/dist/components/buckets/notifications/events.d.ts +71 -7
  56. package/dist/components/buckets/notifications/events.js +98 -16
  57. package/dist/components/index.d.ts +23 -21
  58. package/dist/components/index.js +4 -2
  59. package/dist/components/layouts/ArrowNavigation.d.ts +1 -2
  60. package/dist/components/layouts/ArrowNavigation.js +22 -10
  61. package/dist/components/layouts/BrowserPageLayout.d.ts +2 -3
  62. package/dist/components/layouts/BrowserPageLayout.js +1 -1
  63. package/dist/components/objects/CreateFolderButton.d.ts +2 -2
  64. package/dist/components/objects/CreateFolderButton.js +10 -10
  65. package/dist/components/objects/DeleteObjectButton.d.ts +1 -1
  66. package/dist/components/objects/DeleteObjectButton.js +20 -20
  67. package/dist/components/objects/ObjectDetails/ObjectMetadata.d.ts +1 -1
  68. package/dist/components/objects/ObjectDetails/ObjectMetadata.js +56 -56
  69. package/dist/components/objects/ObjectDetails/ObjectSummary.d.ts +1 -1
  70. package/dist/components/objects/ObjectDetails/ObjectSummary.js +294 -164
  71. package/dist/components/objects/ObjectDetails/ObjectTags.d.ts +1 -1
  72. package/dist/components/objects/ObjectDetails/ObjectTags.js +25 -25
  73. package/dist/components/objects/ObjectDetails/__tests__/ObjectDetails.test.d.ts +1 -0
  74. package/dist/components/objects/ObjectDetails/__tests__/ObjectDetails.test.js +516 -0
  75. package/dist/components/objects/ObjectDetails/__tests__/ObjectSummary.test.d.ts +1 -0
  76. package/dist/components/objects/ObjectDetails/__tests__/ObjectSummary.test.js +813 -0
  77. package/dist/components/objects/ObjectDetails/index.d.ts +17 -1
  78. package/dist/components/objects/ObjectDetails/index.js +136 -50
  79. package/dist/components/objects/ObjectList.d.ts +11 -9
  80. package/dist/components/objects/ObjectList.js +576 -295
  81. package/dist/components/objects/ObjectLock/EditRetentionButton.js +3 -3
  82. package/dist/components/objects/ObjectLock/ObjectLockRetentionSettings.js +14 -14
  83. package/dist/components/objects/ObjectLock/ObjectLockSettings.d.ts +1 -1
  84. package/dist/components/objects/ObjectLock/ObjectLockSettings.js +29 -28
  85. package/dist/components/objects/ObjectLock/ObjectLockSettingsUtils.d.ts +1 -1
  86. package/dist/components/objects/ObjectLock/ObjectLockSettingsUtils.js +6 -6
  87. package/dist/components/objects/ObjectLock/__tests__/EditRetentionButton.test.js +50 -50
  88. package/dist/components/objects/ObjectLock/__tests__/ObjectLockSettings.test.js +77 -77
  89. package/dist/components/objects/ObjectPage.js +5 -4
  90. package/dist/components/objects/UploadButton.d.ts +3 -3
  91. package/dist/components/objects/UploadButton.js +6 -6
  92. package/dist/components/providers/DataBrowserProvider.d.ts +15 -4
  93. package/dist/components/providers/DataBrowserProvider.js +33 -11
  94. package/dist/components/search/MetadataSearch.js +26 -25
  95. package/dist/components/search/SearchHints.js +1 -1
  96. package/dist/components/ui/ArrayFieldActions.js +4 -4
  97. package/dist/components/ui/ConfirmDeleteRuleModal.d.ts +1 -1
  98. package/dist/components/ui/ConfirmDeleteRuleModal.js +1 -1
  99. package/dist/components/ui/DeleteObjectModalContent.d.ts +1 -1
  100. package/dist/components/ui/DeleteObjectModalContent.js +12 -12
  101. package/dist/components/ui/FilterFormSection.d.ts +2 -2
  102. package/dist/components/ui/FilterFormSection.js +29 -29
  103. package/dist/components/ui/Search.elements.d.ts +1 -1
  104. package/dist/components/ui/Search.elements.js +7 -7
  105. package/dist/components/ui/Table.elements.js +5 -5
  106. package/dist/config/factory.d.ts +23 -10
  107. package/dist/config/factory.js +22 -7
  108. package/dist/config/types.d.ts +134 -0
  109. package/dist/contexts/DataBrowserUICustomizationContext.d.ts +27 -0
  110. package/dist/contexts/DataBrowserUICustomizationContext.js +13 -0
  111. package/dist/hooks/__tests__/useISVBucketDetection.test.js +41 -41
  112. package/dist/hooks/__tests__/useIsBucketEmpty.test.js +25 -25
  113. package/dist/hooks/bucketConfiguration.d.ts +1 -1
  114. package/dist/hooks/bucketConfiguration.js +48 -48
  115. package/dist/hooks/bucketOperations.d.ts +1 -1
  116. package/dist/hooks/bucketOperations.js +6 -6
  117. package/dist/hooks/factories/__tests__/useCreateS3FunctionMutationHook.test.js +78 -78
  118. package/dist/hooks/factories/__tests__/useCreateS3InfiniteQueryHook.test.js +78 -78
  119. package/dist/hooks/factories/__tests__/useCreateS3LoginHook.test.js +42 -42
  120. package/dist/hooks/factories/__tests__/useCreateS3MutationHook.test.js +61 -61
  121. package/dist/hooks/factories/__tests__/useCreateS3QueryHook.test.js +63 -63
  122. package/dist/hooks/factories/index.d.ts +4 -4
  123. package/dist/hooks/factories/useCreateS3InfiniteQueryHook.d.ts +2 -2
  124. package/dist/hooks/factories/useCreateS3InfiniteQueryHook.js +15 -12
  125. package/dist/hooks/factories/useCreateS3LoginHook.d.ts +2 -2
  126. package/dist/hooks/factories/useCreateS3MutationHook.d.ts +3 -3
  127. package/dist/hooks/factories/useCreateS3MutationHook.js +6 -1
  128. package/dist/hooks/factories/useCreateS3QueryHook.d.ts +2 -2
  129. package/dist/hooks/factories/useCreateS3QueryHook.js +8 -5
  130. package/dist/hooks/index.d.ts +14 -13
  131. package/dist/hooks/index.js +2 -1
  132. package/dist/hooks/loginOperations.d.ts +1 -1
  133. package/dist/hooks/loginOperations.js +1 -1
  134. package/dist/hooks/objectOperations.d.ts +2 -2
  135. package/dist/hooks/objectOperations.js +49 -49
  136. package/dist/hooks/presignedOperations.d.ts +2 -2
  137. package/dist/hooks/presignedOperations.js +3 -3
  138. package/dist/hooks/useBatchObjectLegalHold.js +7 -4
  139. package/dist/hooks/useDataBrowserNavigate.d.ts +14 -0
  140. package/dist/hooks/useDataBrowserNavigate.js +24 -0
  141. package/dist/hooks/useDeleteBucketConfigRule.d.ts +2 -2
  142. package/dist/hooks/useDeleteBucketConfigRule.js +4 -4
  143. package/dist/hooks/useEmptyBucket.js +10 -10
  144. package/dist/hooks/useISVBucketDetection.js +3 -3
  145. package/dist/hooks/useIsBucketEmpty.js +4 -4
  146. package/dist/hooks/useLoginMutation.d.ts +1 -1
  147. package/dist/hooks/useLoginMutation.js +1 -1
  148. package/dist/hooks/useS3Client.d.ts +5 -0
  149. package/dist/hooks/useS3Client.js +3 -2
  150. package/dist/hooks/useS3ConfigSwitch.d.ts +11 -0
  151. package/dist/hooks/useS3ConfigSwitch.js +37 -0
  152. package/dist/index.d.ts +6 -6
  153. package/dist/test/msw/handlers/deleteBucket.d.ts +1 -1
  154. package/dist/test/msw/handlers/deleteBucket.js +20 -10
  155. package/dist/test/msw/handlers/getBucketAcl.d.ts +1 -1
  156. package/dist/test/msw/handlers/getBucketAcl.js +29 -17
  157. package/dist/test/msw/handlers/getBucketLocation.d.ts +1 -1
  158. package/dist/test/msw/handlers/getBucketLocation.js +29 -15
  159. package/dist/test/msw/handlers/getBucketPolicy.d.ts +1 -1
  160. package/dist/test/msw/handlers/getBucketPolicy.js +52 -32
  161. package/dist/test/msw/handlers/headObject.d.ts +1 -1
  162. package/dist/test/msw/handlers/headObject.js +31 -13
  163. package/dist/test/msw/handlers/listBuckets.d.ts +1 -1
  164. package/dist/test/msw/handlers/listBuckets.js +5 -3
  165. package/dist/test/msw/handlers/listObjectVersions.d.ts +1 -1
  166. package/dist/test/msw/handlers/listObjectVersions.js +38 -26
  167. package/dist/test/msw/handlers/listObjects.d.ts +1 -1
  168. package/dist/test/msw/handlers/listObjects.js +35 -23
  169. package/dist/test/msw/handlers/objectLegalHold.d.ts +1 -1
  170. package/dist/test/msw/handlers/objectLegalHold.js +31 -16
  171. package/dist/test/msw/handlers/objectRetention.d.ts +1 -1
  172. package/dist/test/msw/handlers/objectRetention.js +31 -17
  173. package/dist/test/msw/handlers/putBucketAcl.d.ts +1 -1
  174. package/dist/test/msw/handlers/putBucketAcl.js +29 -14
  175. package/dist/test/msw/handlers/putObject.d.ts +1 -1
  176. package/dist/test/msw/handlers/putObject.js +27 -12
  177. package/dist/test/msw/handlers.d.ts +3 -3
  178. package/dist/test/msw/handlers.js +72 -49
  179. package/dist/test/msw/index.d.ts +2 -2
  180. package/dist/test/msw/server.d.ts +1 -1
  181. package/dist/test/msw/server.js +1 -1
  182. package/dist/test/msw/utils.js +2 -2
  183. package/dist/test/setup.d.ts +1 -1
  184. package/dist/test/setup.js +19 -19
  185. package/dist/test/testUtils.d.ts +70 -12
  186. package/dist/test/testUtils.js +160 -75
  187. package/dist/test/utils/errorHandling.test.js +119 -119
  188. package/dist/types/index.d.ts +8 -31
  189. package/dist/utils/__tests__/s3ConfigIdentifier.test.d.ts +1 -0
  190. package/dist/utils/__tests__/s3ConfigIdentifier.test.js +429 -0
  191. package/dist/utils/constants.d.ts +7 -0
  192. package/dist/utils/constants.js +16 -9
  193. package/dist/utils/deletion/index.d.ts +2 -2
  194. package/dist/utils/deletion/messages.d.ts +1 -1
  195. package/dist/utils/deletion/messages.js +4 -4
  196. package/dist/utils/errorHandling.d.ts +3 -3
  197. package/dist/utils/errorHandling.js +6 -6
  198. package/dist/utils/hooks.js +8 -8
  199. package/dist/utils/index.d.ts +5 -4
  200. package/dist/utils/index.js +2 -0
  201. package/dist/utils/proxyMiddleware.d.ts +1 -1
  202. package/dist/utils/proxyMiddleware.js +6 -11
  203. package/dist/utils/s3Client.d.ts +2 -2
  204. package/dist/utils/s3Client.js +1 -1
  205. package/dist/utils/s3ConfigIdentifier.d.ts +68 -0
  206. package/dist/utils/s3ConfigIdentifier.js +55 -0
  207. package/dist/utils/s3RuleUtils.d.ts +5 -5
  208. package/dist/utils/s3RuleUtils.js +17 -17
  209. package/dist/utils/useFeatures.js +1 -1
  210. package/dist/utils/useSupportedNotificationEvents.d.ts +6 -0
  211. package/dist/utils/useSupportedNotificationEvents.js +7 -0
  212. package/package.json +3 -3
@@ -1,32 +1,14 @@
1
- import * as __WEBPACK_EXTERNAL_MODULE_react_router_dom_5358f3fe__ from "react-router-dom";
2
1
  import { jsx, jsxs } from "react/jsx-runtime";
2
+ import "react";
3
3
  import { fireEvent, render, screen } from "@testing-library/react";
4
+ import { MemoryRouter } from "react-router";
4
5
  import { useGetBucketAcl, useGetBucketCors, useGetBucketLocation, useGetBucketObjectLockConfiguration, useGetBucketPolicy, useGetBucketTagging, useGetBucketVersioning, useISVBucketStatus } from "../../hooks/index.js";
5
- import { createTestWrapper } from "../../test/testUtils.js";
6
- import { BucketOverview } from "../buckets/BucketOverview.js";
6
+ import { applyBucketMocks, createTestWrapper } from "../../test/testUtils.js";
7
+ import { BucketOverview, useBucketOverviewContext } from "../buckets/BucketOverview.js";
7
8
  import { useFeatures } from "../../utils/useFeatures.js";
8
- var __webpack_modules__ = {
9
- "react-router-dom": function(module) {
10
- module.exports = __WEBPACK_EXTERNAL_MODULE_react_router_dom_5358f3fe__;
11
- }
12
- };
13
- var __webpack_module_cache__ = {};
14
- function __webpack_require__(moduleId) {
15
- var cachedModule = __webpack_module_cache__[moduleId];
16
- if (void 0 !== cachedModule) return cachedModule.exports;
17
- var module = __webpack_module_cache__[moduleId] = {
18
- exports: {}
19
- };
20
- __webpack_modules__[moduleId](module, module.exports, __webpack_require__);
21
- return module.exports;
22
- }
23
- var external_react_router_dom_ = __webpack_require__("react-router-dom");
24
- jest.mock("../../hooks");
25
- jest.mock("../../utils/useFeatures");
26
- jest.mock("react-router-dom", ()=>({
27
- ...jest.requireActual("react-router-dom"),
28
- useNavigate: jest.fn()
29
- }));
9
+ import * as __WEBPACK_EXTERNAL_MODULE__contexts_DataBrowserUICustomizationContext_js_f267b01c__ from "../../contexts/DataBrowserUICustomizationContext.js";
10
+ jest.mock('../../hooks');
11
+ jest.mock('../../utils/useFeatures');
30
12
  const mockUseGetBucketVersioning = jest.mocked(useGetBucketVersioning);
31
13
  const mockUseGetBucketAcl = jest.mocked(useGetBucketAcl);
32
14
  const mockUseGetBucketLocation = jest.mocked(useGetBucketLocation);
@@ -36,12 +18,13 @@ const mockUseGetBucketPolicy = jest.mocked(useGetBucketPolicy);
36
18
  const mockUseGetBucketTagging = jest.mocked(useGetBucketTagging);
37
19
  const mockUseISVBucketStatus = jest.mocked(useISVBucketStatus);
38
20
  const mockUseFeatures = jest.mocked(useFeatures);
21
+ const mockUseDataBrowserUICustomization = (config = {})=>{
22
+ jest.spyOn(__WEBPACK_EXTERNAL_MODULE__contexts_DataBrowserUICustomizationContext_js_f267b01c__, 'useDataBrowserUICustomization').mockReturnValue(config);
23
+ };
39
24
  const renderBucketOverview = (props = {})=>{
40
- const { bucketName = "test-bucket", onEmptyBucket, onDeleteBucket, onEditPolicy, renderEmptyButton, renderDeleteButton, isEmptyBucketDisabled, isDeleteBucketDisabled } = props;
25
+ const { bucketName = 'test-bucket', onEmptyBucket, onDeleteBucket, onEditPolicy, renderEmptyButton, renderDeleteButton, isEmptyBucketDisabled, isDeleteBucketDisabled } = props;
41
26
  const Wrapper = createTestWrapper();
42
- const mockNavigate = jest.fn();
43
- __webpack_require__("react-router-dom").useNavigate.mockReturnValue(mockNavigate);
44
- return render(/*#__PURE__*/ jsx(external_react_router_dom_.MemoryRouter, {
27
+ return render(/*#__PURE__*/ jsx(MemoryRouter, {
45
28
  children: /*#__PURE__*/ jsx(Wrapper, {
46
29
  children: /*#__PURE__*/ jsxs(BucketOverview, {
47
30
  bucketName: bucketName,
@@ -68,622 +51,651 @@ const renderBucketOverview = (props = {})=>{
68
51
  })
69
52
  }));
70
53
  };
71
- const mockHookDefaults = ()=>{
72
- mockUseGetBucketVersioning.mockReturnValue({
73
- data: {
74
- Status: "Enabled"
75
- },
76
- status: "success"
77
- });
78
- mockUseGetBucketAcl.mockReturnValue({
79
- data: {
80
- Owner: {
81
- DisplayName: "test-owner"
82
- },
83
- Grants: [
84
- {
85
- Grantee: {
86
- DisplayName: "test-grantee"
87
- }
88
- }
89
- ]
90
- },
91
- status: "success"
92
- });
93
- mockUseGetBucketLocation.mockReturnValue({
94
- data: {
95
- LocationConstraint: "us-west-2"
96
- },
97
- status: "success"
98
- });
99
- mockUseGetBucketCors.mockReturnValue({
100
- data: {
101
- CORSRules: []
102
- },
103
- status: "success"
104
- });
105
- mockUseGetBucketObjectLockConfiguration.mockReturnValue({
106
- data: {
107
- ObjectLockConfiguration: {
108
- ObjectLockEnabled: "Disabled"
109
- }
110
- },
111
- status: "success"
112
- });
113
- mockUseGetBucketPolicy.mockReturnValue({
114
- data: void 0,
115
- error: null,
116
- status: "success"
117
- });
118
- mockUseGetBucketTagging.mockReturnValue({
119
- data: {
120
- TagSet: []
121
- },
122
- status: "success"
123
- });
124
- mockUseISVBucketStatus.mockReturnValue({
125
- isVeeamBucket: false,
126
- isCommvaultBucket: false,
127
- isISVManaged: false,
128
- isvApplication: void 0,
129
- isLoading: false,
130
- bucketTagsStatus: "success"
131
- });
132
- mockUseFeatures.mockReturnValue(false);
54
+ const mockHookDefaults = (overrides = {})=>{
55
+ applyBucketMocks({
56
+ useGetBucketVersioning: mockUseGetBucketVersioning,
57
+ useGetBucketAcl: mockUseGetBucketAcl,
58
+ useGetBucketLocation: mockUseGetBucketLocation,
59
+ useGetBucketCors: mockUseGetBucketCors,
60
+ useGetBucketObjectLockConfiguration: mockUseGetBucketObjectLockConfiguration,
61
+ useGetBucketPolicy: mockUseGetBucketPolicy,
62
+ useGetBucketTagging: mockUseGetBucketTagging,
63
+ useISVBucketStatus: mockUseISVBucketStatus,
64
+ useFeatures: mockUseFeatures
65
+ }, overrides);
133
66
  };
134
- describe("BucketOverview", ()=>{
67
+ describe('BucketOverview', ()=>{
135
68
  beforeEach(()=>{
136
69
  jest.clearAllMocks();
137
70
  mockHookDefaults();
71
+ mockUseDataBrowserUICustomization({});
138
72
  });
139
- it("renders bucket overview with all sections", ()=>{
73
+ it('renders bucket overview with all sections', ()=>{
140
74
  renderBucketOverview();
141
- expect(screen.getByText("General")).toBeInTheDocument();
142
- expect(screen.getByText("Data protection")).toBeInTheDocument();
143
- expect(screen.getByText("Permissions")).toBeInTheDocument();
75
+ expect(screen.getByText('General')).toBeInTheDocument();
76
+ expect(screen.getByText('Data protection')).toBeInTheDocument();
77
+ expect(screen.getByText('Permissions')).toBeInTheDocument();
144
78
  });
145
- it("displays bucket name correctly", ()=>{
79
+ it('displays bucket name correctly', ()=>{
146
80
  renderBucketOverview({
147
- bucketName: "my-test-bucket"
81
+ bucketName: 'my-test-bucket'
148
82
  });
149
- expect(screen.getByText("my-test-bucket")).toBeInTheDocument();
83
+ expect(screen.getByText('my-test-bucket')).toBeInTheDocument();
150
84
  });
151
- it("shows versioning status when enabled", ()=>{
85
+ it('shows versioning status when enabled', ()=>{
152
86
  mockUseGetBucketVersioning.mockReturnValue({
153
87
  data: {
154
- Status: "Enabled"
88
+ Status: 'Enabled'
155
89
  },
156
- status: "success"
90
+ status: 'success'
157
91
  });
158
92
  renderBucketOverview();
159
- expect(screen.getByText("Active")).toBeInTheDocument();
93
+ expect(screen.getByText('Active')).toBeInTheDocument();
160
94
  });
161
- it("shows versioning status when disabled", ()=>{
95
+ it('shows versioning status when disabled', ()=>{
162
96
  mockUseGetBucketVersioning.mockReturnValue({
163
97
  data: {
164
- Status: "Suspended"
98
+ Status: 'Suspended'
165
99
  },
166
- status: "success"
100
+ status: 'success'
167
101
  });
168
102
  renderBucketOverview();
169
- expect(screen.getByText("Inactive")).toBeInTheDocument();
103
+ expect(screen.getByText('Inactive')).toBeInTheDocument();
170
104
  });
171
- it("displays bucket location", ()=>{
105
+ it('displays bucket location', ()=>{
172
106
  mockUseGetBucketLocation.mockReturnValue({
173
107
  data: {
174
- LocationConstraint: "eu-west-1"
108
+ LocationConstraint: 'eu-west-1'
175
109
  },
176
- status: "success"
110
+ status: 'success'
177
111
  });
178
112
  renderBucketOverview();
179
- expect(screen.getByText("eu-west-1")).toBeInTheDocument();
113
+ expect(screen.getByText('eu-west-1')).toBeInTheDocument();
180
114
  });
181
- it("shows default location when LocationConstraint is null", ()=>{
115
+ it('shows default location when LocationConstraint is null', ()=>{
182
116
  mockUseGetBucketLocation.mockReturnValue({
183
117
  data: {
184
118
  LocationConstraint: null
185
119
  },
186
- status: "success"
120
+ status: 'success'
187
121
  });
188
122
  renderBucketOverview();
189
- expect(screen.getByText("us-east-1")).toBeInTheDocument();
123
+ expect(screen.getByText('us-east-1')).toBeInTheDocument();
190
124
  });
191
- it("shows object-lock enabled status", ()=>{
125
+ it('shows object-lock enabled status', ()=>{
192
126
  mockUseGetBucketObjectLockConfiguration.mockReturnValue({
193
127
  data: {
194
128
  ObjectLockConfiguration: {
195
- ObjectLockEnabled: "Enabled"
129
+ ObjectLockEnabled: 'Enabled'
196
130
  }
197
131
  },
198
- status: "success"
132
+ status: 'success'
199
133
  });
200
134
  renderBucketOverview();
201
- expect(screen.getByText("Enabled")).toBeInTheDocument();
135
+ expect(screen.getByText('Enabled')).toBeInTheDocument();
202
136
  });
203
- it("shows object-lock disabled status", ()=>{
137
+ it('shows object-lock disabled status', ()=>{
204
138
  mockUseGetBucketObjectLockConfiguration.mockReturnValue({
205
139
  data: {
206
140
  ObjectLockConfiguration: {
207
- ObjectLockEnabled: "Disabled"
141
+ ObjectLockEnabled: 'Disabled'
208
142
  }
209
143
  },
210
- status: "success"
144
+ status: 'success'
211
145
  });
212
146
  renderBucketOverview();
213
- expect(screen.getByText("Disabled")).toBeInTheDocument();
147
+ expect(screen.getByText('Disabled')).toBeInTheDocument();
214
148
  });
215
- it("shows default retention as Inactive when not configured", ()=>{
149
+ it('shows default retention as Inactive when not configured', ()=>{
216
150
  mockUseGetBucketObjectLockConfiguration.mockReturnValue({
217
151
  data: {
218
152
  ObjectLockConfiguration: {
219
- ObjectLockEnabled: "Enabled"
153
+ ObjectLockEnabled: 'Enabled'
220
154
  }
221
155
  },
222
- status: "success"
156
+ status: 'success'
223
157
  });
224
158
  renderBucketOverview();
225
- expect(screen.getByText("Inactive")).toBeInTheDocument();
159
+ expect(screen.getByText('Inactive')).toBeInTheDocument();
226
160
  });
227
- it("shows default retention with days in Governance mode", ()=>{
161
+ it('shows default retention with days in Governance mode', ()=>{
228
162
  mockUseGetBucketObjectLockConfiguration.mockReturnValue({
229
163
  data: {
230
164
  ObjectLockConfiguration: {
231
- ObjectLockEnabled: "Enabled",
165
+ ObjectLockEnabled: 'Enabled',
232
166
  Rule: {
233
167
  DefaultRetention: {
234
- Mode: "GOVERNANCE",
168
+ Mode: 'GOVERNANCE',
235
169
  Days: 30
236
170
  }
237
171
  }
238
172
  }
239
173
  },
240
- status: "success"
174
+ status: 'success'
241
175
  });
242
176
  renderBucketOverview();
243
- expect(screen.getByText("Governance - 30 days")).toBeInTheDocument();
177
+ expect(screen.getByText('Governance - 30 days')).toBeInTheDocument();
244
178
  });
245
- it("shows default retention with single day", ()=>{
179
+ it('shows default retention with single day', ()=>{
246
180
  mockUseGetBucketObjectLockConfiguration.mockReturnValue({
247
181
  data: {
248
182
  ObjectLockConfiguration: {
249
- ObjectLockEnabled: "Enabled",
183
+ ObjectLockEnabled: 'Enabled',
250
184
  Rule: {
251
185
  DefaultRetention: {
252
- Mode: "COMPLIANCE",
186
+ Mode: 'COMPLIANCE',
253
187
  Days: 1
254
188
  }
255
189
  }
256
190
  }
257
191
  },
258
- status: "success"
192
+ status: 'success'
259
193
  });
260
194
  renderBucketOverview();
261
- expect(screen.getByText("Compliance - 1 day")).toBeInTheDocument();
195
+ expect(screen.getByText('Compliance - 1 day')).toBeInTheDocument();
262
196
  });
263
- it("shows default retention with years in Compliance mode", ()=>{
197
+ it('shows default retention with years in Compliance mode', ()=>{
264
198
  mockUseGetBucketObjectLockConfiguration.mockReturnValue({
265
199
  data: {
266
200
  ObjectLockConfiguration: {
267
- ObjectLockEnabled: "Enabled",
201
+ ObjectLockEnabled: 'Enabled',
268
202
  Rule: {
269
203
  DefaultRetention: {
270
- Mode: "COMPLIANCE",
204
+ Mode: 'COMPLIANCE',
271
205
  Years: 7
272
206
  }
273
207
  }
274
208
  }
275
209
  },
276
- status: "success"
210
+ status: 'success'
277
211
  });
278
212
  renderBucketOverview();
279
- expect(screen.getByText("Compliance - 7 years")).toBeInTheDocument();
213
+ expect(screen.getByText('Compliance - 7 years')).toBeInTheDocument();
280
214
  });
281
- it("shows default retention with single year", ()=>{
215
+ it('shows default retention with single year', ()=>{
282
216
  mockUseGetBucketObjectLockConfiguration.mockReturnValue({
283
217
  data: {
284
218
  ObjectLockConfiguration: {
285
- ObjectLockEnabled: "Enabled",
219
+ ObjectLockEnabled: 'Enabled',
286
220
  Rule: {
287
221
  DefaultRetention: {
288
- Mode: "GOVERNANCE",
222
+ Mode: 'GOVERNANCE',
289
223
  Years: 1
290
224
  }
291
225
  }
292
226
  }
293
227
  },
294
- status: "success"
228
+ status: 'success'
295
229
  });
296
230
  renderBucketOverview();
297
- expect(screen.getByText("Governance - 1 year")).toBeInTheDocument();
231
+ expect(screen.getByText('Governance - 1 year')).toBeInTheDocument();
298
232
  });
299
- it("shows edit retention button when object lock is enabled", ()=>{
233
+ it('shows edit retention button when object lock is enabled', ()=>{
300
234
  mockUseGetBucketObjectLockConfiguration.mockReturnValue({
301
235
  data: {
302
236
  ObjectLockConfiguration: {
303
- ObjectLockEnabled: "Enabled",
237
+ ObjectLockEnabled: 'Enabled',
304
238
  Rule: {
305
239
  DefaultRetention: {
306
- Mode: "GOVERNANCE",
240
+ Mode: 'GOVERNANCE',
307
241
  Days: 30
308
242
  }
309
243
  }
310
244
  }
311
245
  },
312
- status: "success"
246
+ status: 'success'
313
247
  });
314
248
  renderBucketOverview();
315
- const editButton = screen.getByRole("button", {
249
+ const editButton = screen.getByRole('button', {
316
250
  name: /edit default retention/i
317
251
  });
318
252
  expect(editButton).toBeInTheDocument();
319
253
  });
320
- it("does not show edit retention button when object lock is disabled", ()=>{
254
+ it('does not show edit retention button when object lock is disabled', ()=>{
321
255
  mockUseGetBucketObjectLockConfiguration.mockReturnValue({
322
256
  data: {
323
257
  ObjectLockConfiguration: {
324
- ObjectLockEnabled: "Disabled"
258
+ ObjectLockEnabled: 'Disabled'
325
259
  }
326
260
  },
327
- status: "success"
261
+ status: 'success'
328
262
  });
329
263
  renderBucketOverview();
330
- const editButton = screen.queryByRole("button", {
264
+ const editButton = screen.queryByRole('button', {
331
265
  name: /edit default retention/i
332
266
  });
333
267
  expect(editButton).not.toBeInTheDocument();
334
268
  });
335
- it("displays bucket owner from ACL", ()=>{
269
+ it('displays bucket owner from ACL', ()=>{
336
270
  mockUseGetBucketAcl.mockReturnValue({
337
271
  data: {
338
272
  Owner: {
339
- DisplayName: "bucket-owner"
273
+ DisplayName: 'bucket-owner'
340
274
  },
341
275
  Grants: []
342
276
  },
343
- status: "success"
277
+ status: 'success'
344
278
  });
345
279
  renderBucketOverview();
346
- expect(screen.getByText("bucket-owner")).toBeInTheDocument();
280
+ expect(screen.getByText('bucket-owner')).toBeInTheDocument();
347
281
  });
348
- it("shows ACL grantees count", ()=>{
282
+ it('shows ACL grantees count', ()=>{
349
283
  mockUseGetBucketAcl.mockReturnValue({
350
284
  data: {
351
285
  Owner: {
352
- DisplayName: "owner"
286
+ DisplayName: 'owner'
353
287
  },
354
288
  Grants: [
355
289
  {
356
290
  Grantee: {
357
- DisplayName: "user1"
291
+ DisplayName: 'user1'
358
292
  }
359
293
  },
360
294
  {
361
295
  Grantee: {
362
- DisplayName: "user2"
296
+ DisplayName: 'user2'
363
297
  }
364
298
  },
365
299
  {
366
300
  Grantee: {
367
- DisplayName: "user3"
301
+ DisplayName: 'user3'
368
302
  }
369
303
  }
370
304
  ]
371
305
  },
372
- status: "success"
306
+ status: 'success'
373
307
  });
374
308
  renderBucketOverview();
375
- expect(screen.getByText("3 Grantees")).toBeInTheDocument();
309
+ expect(screen.getByText('3 Grantees')).toBeInTheDocument();
376
310
  });
377
- it("shows single grantee without plural", ()=>{
311
+ it('shows single grantee without plural', ()=>{
378
312
  mockUseGetBucketAcl.mockReturnValue({
379
313
  data: {
380
314
  Owner: {
381
- DisplayName: "owner"
315
+ DisplayName: 'owner'
382
316
  },
383
317
  Grants: [
384
318
  {
385
319
  Grantee: {
386
- DisplayName: "user1"
320
+ DisplayName: 'user1'
387
321
  }
388
322
  }
389
323
  ]
390
324
  },
391
- status: "success"
325
+ status: 'success'
392
326
  });
393
327
  renderBucketOverview();
394
- expect(screen.getByText("1 Grantee")).toBeInTheDocument();
328
+ expect(screen.getByText('1 Grantee')).toBeInTheDocument();
395
329
  });
396
- it("shows CORS enabled when rules exist", ()=>{
330
+ it('shows CORS enabled when rules exist', ()=>{
397
331
  mockUseGetBucketCors.mockReturnValue({
398
332
  data: {
399
333
  CORSRules: [
400
334
  {
401
335
  AllowedMethods: [
402
- "GET"
336
+ 'GET'
403
337
  ],
404
338
  AllowedOrigins: [
405
- "*"
339
+ '*'
406
340
  ]
407
341
  }
408
342
  ]
409
343
  },
410
- status: "success"
344
+ status: 'success'
411
345
  });
412
346
  renderBucketOverview();
413
- expect(screen.getByText("Yes")).toBeInTheDocument();
347
+ expect(screen.getByText('Yes')).toBeInTheDocument();
414
348
  });
415
- it("shows CORS disabled when no rules exist", ()=>{
349
+ it('shows CORS disabled when no rules exist', ()=>{
416
350
  mockUseGetBucketCors.mockReturnValue({
417
351
  data: {
418
352
  CORSRules: []
419
353
  },
420
- status: "success"
354
+ status: 'success'
421
355
  });
422
356
  renderBucketOverview();
423
- const corsValues = screen.getAllByText("No");
357
+ const corsValues = screen.getAllByText('No');
424
358
  expect(corsValues.length).toBeGreaterThan(0);
425
359
  });
426
- it("detects public bucket from ACL grants", ()=>{
360
+ it('detects public bucket from ACL grants', ()=>{
427
361
  mockUseGetBucketAcl.mockReturnValue({
428
362
  data: {
429
363
  Owner: {
430
- DisplayName: "owner"
364
+ DisplayName: 'owner'
431
365
  },
432
366
  Grants: [
433
367
  {
434
368
  Grantee: {
435
- URI: "http://acs.amazonaws.com/groups/global/AllUsers"
369
+ URI: 'http://acs.amazonaws.com/groups/global/AllUsers'
436
370
  },
437
- Permission: "READ"
371
+ Permission: 'READ'
438
372
  }
439
373
  ]
440
374
  },
441
- status: "success"
375
+ status: 'success'
442
376
  });
443
377
  renderBucketOverview();
444
- expect(screen.getByText("Yes")).toBeInTheDocument();
378
+ expect(screen.getByText('Yes')).toBeInTheDocument();
445
379
  });
446
- it("shows non-public bucket when no public grants", ()=>{
380
+ it('shows non-public bucket when no public grants', ()=>{
447
381
  mockUseGetBucketAcl.mockReturnValue({
448
382
  data: {
449
383
  Owner: {
450
- DisplayName: "owner"
384
+ DisplayName: 'owner'
451
385
  },
452
386
  Grants: [
453
387
  {
454
388
  Grantee: {
455
- DisplayName: "private-user"
389
+ DisplayName: 'private-user'
456
390
  },
457
- Permission: "READ"
391
+ Permission: 'READ'
458
392
  }
459
393
  ]
460
394
  },
461
- status: "success"
395
+ status: 'success'
462
396
  });
463
397
  renderBucketOverview();
464
- const publicValues = screen.getAllByText("No");
398
+ const publicValues = screen.getAllByText('No');
465
399
  expect(publicValues.length).toBeGreaterThan(0);
466
400
  });
467
- it("shows loading states while data is being fetched", ()=>{
401
+ it('shows loading states while data is being fetched', ()=>{
468
402
  mockUseGetBucketVersioning.mockReturnValue({
469
403
  data: void 0,
470
- status: "pending"
404
+ status: 'pending'
471
405
  });
472
406
  mockUseGetBucketAcl.mockReturnValue({
473
407
  data: void 0,
474
- status: "pending"
408
+ status: 'pending'
475
409
  });
476
410
  renderBucketOverview();
477
411
  const loaders = document.querySelectorAll('[data-testid="loader"], .loader, [class*="loader"]');
478
412
  expect(loaders.length).toBeGreaterThan(0);
479
413
  });
480
- it("shows error states when API calls fail", ()=>{
414
+ it('shows error states when API calls fail', ()=>{
481
415
  mockUseGetBucketVersioning.mockReturnValue({
482
416
  data: void 0,
483
- status: "error"
417
+ status: 'error'
484
418
  });
485
419
  mockUseGetBucketLocation.mockReturnValue({
486
420
  data: void 0,
487
- status: "error"
421
+ status: 'error'
488
422
  });
489
423
  renderBucketOverview();
490
- const errorElements = screen.getAllByText("Error");
424
+ const errorElements = screen.getAllByText('Error');
491
425
  expect(errorElements.length).toBeGreaterThan(0);
492
426
  });
493
- it("handles empty bucket button click", ()=>{
427
+ it('handles empty bucket button click', ()=>{
494
428
  const onEmptyBucket = jest.fn();
495
429
  renderBucketOverview({
496
430
  onEmptyBucket,
497
431
  isEmptyBucketDisabled: false
498
432
  });
499
- const emptyButton = screen.getByRole("button", {
433
+ const emptyButton = screen.getByRole('button', {
500
434
  name: /empty bucket/i
501
435
  });
502
436
  fireEvent.click(emptyButton);
503
437
  expect(onEmptyBucket).toHaveBeenCalled();
504
438
  });
505
- it("handles delete bucket button click", ()=>{
439
+ it('handles delete bucket button click', ()=>{
506
440
  const onDeleteBucket = jest.fn();
507
441
  renderBucketOverview({
508
442
  onDeleteBucket
509
443
  });
510
- const deleteButton = screen.getByRole("button", {
444
+ const deleteButton = screen.getByRole('button', {
511
445
  name: /delete bucket/i
512
446
  });
513
447
  fireEvent.click(deleteButton);
514
448
  expect(onDeleteBucket).toHaveBeenCalled();
515
449
  });
516
- it("disables empty button when specified", ()=>{
450
+ it('disables empty button when specified', ()=>{
517
451
  renderBucketOverview({
518
452
  isEmptyBucketDisabled: true
519
453
  });
520
- const emptyButton = screen.getByRole("button", {
454
+ const emptyButton = screen.getByRole('button', {
521
455
  name: /empty bucket/i
522
456
  });
523
457
  expect(emptyButton).toBeDisabled();
524
458
  });
525
- it("disables delete button when specified", ()=>{
459
+ it('disables delete button when specified', ()=>{
526
460
  renderBucketOverview({
527
461
  isDeleteBucketDisabled: true
528
462
  });
529
- const deleteButton = screen.getByRole("button", {
463
+ const deleteButton = screen.getByRole('button', {
530
464
  name: /delete bucket/i
531
465
  });
532
466
  expect(deleteButton).toBeDisabled();
533
467
  });
534
- it("renders custom empty button when provided", ()=>{
468
+ it('renders custom empty button when provided', ()=>{
535
469
  const renderEmptyButton = jest.fn(()=>/*#__PURE__*/ jsx("button", {
536
470
  children: "Custom Empty Button"
537
471
  }));
538
472
  renderBucketOverview({
539
473
  renderEmptyButton
540
474
  });
541
- expect(screen.getByText("Custom Empty Button")).toBeInTheDocument();
542
- expect(renderEmptyButton).toHaveBeenCalledWith("test-bucket");
475
+ expect(screen.getByText('Custom Empty Button')).toBeInTheDocument();
476
+ expect(renderEmptyButton).toHaveBeenCalledWith('test-bucket');
543
477
  });
544
- it("renders custom delete button when provided", ()=>{
478
+ it('renders custom delete button when provided', ()=>{
545
479
  const renderDeleteButton = jest.fn(()=>/*#__PURE__*/ jsx("button", {
546
480
  children: "Custom Delete Button"
547
481
  }));
548
482
  renderBucketOverview({
549
483
  renderDeleteButton
550
484
  });
551
- expect(screen.getByText("Custom Delete Button")).toBeInTheDocument();
552
- expect(renderDeleteButton).toHaveBeenCalledWith("test-bucket");
485
+ expect(screen.getByText('Custom Delete Button')).toBeInTheDocument();
486
+ expect(renderDeleteButton).toHaveBeenCalledWith('test-bucket');
553
487
  });
554
- it("works when no callbacks are provided", ()=>{
488
+ it('works when no callbacks are provided', ()=>{
555
489
  expect(()=>{
556
490
  renderBucketOverview();
557
- const emptyButton = screen.getByRole("button", {
491
+ const emptyButton = screen.getByRole('button', {
558
492
  name: /empty bucket/i
559
493
  });
560
- const deleteButton = screen.getByRole("button", {
494
+ const deleteButton = screen.getByRole('button', {
561
495
  name: /delete bucket/i
562
496
  });
563
497
  fireEvent.click(emptyButton);
564
498
  fireEvent.click(deleteButton);
565
499
  }).not.toThrow();
566
500
  });
567
- it("handles missing ACL data gracefully", ()=>{
501
+ it('handles missing ACL data gracefully', ()=>{
568
502
  mockUseGetBucketAcl.mockReturnValue({
569
503
  data: void 0,
570
- status: "success"
504
+ status: 'success'
571
505
  });
572
506
  renderBucketOverview();
573
- const naElements = screen.getAllByText("N/A");
507
+ const naElements = screen.getAllByText('N/A');
574
508
  expect(naElements.length).toBeGreaterThan(0);
575
509
  });
576
- it("handles missing versioning data gracefully", ()=>{
510
+ it('handles missing versioning data gracefully', ()=>{
577
511
  mockUseGetBucketVersioning.mockReturnValue({
578
512
  data: void 0,
579
- status: "success"
513
+ status: 'success'
580
514
  });
581
515
  renderBucketOverview();
582
- expect(screen.getByText("Inactive")).toBeInTheDocument();
516
+ expect(screen.getByText('Inactive')).toBeInTheDocument();
583
517
  });
584
- it("handles CORS error state", ()=>{
518
+ it('handles CORS error state', ()=>{
585
519
  mockUseGetBucketCors.mockReturnValue({
586
520
  data: void 0,
587
- status: "error"
521
+ status: 'error'
588
522
  });
589
523
  renderBucketOverview();
590
- const corsValues = screen.getAllByText("No");
524
+ const corsValues = screen.getAllByText('No');
591
525
  expect(corsValues.length).toBeGreaterThan(0);
592
526
  });
593
- it("handles object lock error state (404 - not configured)", ()=>{
594
- const notFoundError = new Error("Object Lock configuration does not exist");
595
- notFoundError.name = "NoSuchBucketObjectLockConfiguration";
527
+ it('handles object lock error state (404 - not configured)', ()=>{
528
+ const notFoundError = new Error('Object Lock configuration does not exist');
529
+ notFoundError.name = 'NoSuchBucketObjectLockConfiguration';
596
530
  notFoundError.$metadata = {
597
531
  httpStatusCode: 404
598
532
  };
599
533
  mockUseGetBucketObjectLockConfiguration.mockReturnValue({
600
534
  data: void 0,
601
- status: "error",
535
+ status: 'error',
602
536
  error: notFoundError
603
537
  });
604
538
  renderBucketOverview();
605
- expect(screen.getByText("Disabled")).toBeInTheDocument();
539
+ expect(screen.getByText('Disabled')).toBeInTheDocument();
606
540
  });
607
- it("handles object lock real error state (non-404)", ()=>{
608
- const accessDeniedError = new Error("Access Denied");
609
- accessDeniedError.name = "AccessDenied";
541
+ it('handles object lock real error state (non-404)', ()=>{
542
+ const accessDeniedError = new Error('Access Denied');
543
+ accessDeniedError.name = 'AccessDenied';
610
544
  accessDeniedError.$metadata = {
611
545
  httpStatusCode: 403
612
546
  };
613
547
  mockUseGetBucketObjectLockConfiguration.mockReturnValue({
614
548
  data: void 0,
615
- status: "error",
549
+ status: 'error',
616
550
  error: accessDeniedError
617
551
  });
618
552
  renderBucketOverview();
619
- expect(screen.getByText("Error")).toBeInTheDocument();
553
+ expect(screen.getByText('Error')).toBeInTheDocument();
620
554
  });
621
- describe("Bucket Policy", ()=>{
555
+ describe('Bucket Policy', ()=>{
622
556
  it("shows 'Configured' when policy exists", ()=>{
623
557
  mockUseGetBucketPolicy.mockReturnValue({
624
558
  data: {
625
559
  Policy: '{"Version":"2012-10-17","Statement":[]}'
626
560
  },
627
561
  error: null,
628
- status: "success"
562
+ status: 'success'
629
563
  });
630
564
  renderBucketOverview();
631
- expect(screen.getByText("Configured")).toBeInTheDocument();
565
+ expect(screen.getByText('Configured')).toBeInTheDocument();
632
566
  });
633
567
  it("shows 'Not configured' when no policy exists", ()=>{
634
568
  mockUseGetBucketPolicy.mockReturnValue({
635
569
  data: void 0,
636
570
  error: null,
637
- status: "success"
571
+ status: 'success'
638
572
  });
639
573
  renderBucketOverview();
640
- expect(screen.getByText("Not configured")).toBeInTheDocument();
574
+ expect(screen.getByText('Not configured')).toBeInTheDocument();
641
575
  });
642
576
  it("shows 'Error' when policy fetch fails with non-NoSuchBucketPolicy error", ()=>{
643
- const genericError = new Error("Network error");
577
+ const genericError = new Error('Network error');
644
578
  mockUseGetBucketPolicy.mockReturnValue({
645
579
  data: void 0,
646
580
  error: genericError,
647
- status: "error"
581
+ status: 'error'
648
582
  });
649
583
  renderBucketOverview();
650
- const errorElements = screen.getAllByText("Error");
584
+ const errorElements = screen.getAllByText('Error');
651
585
  expect(errorElements.length).toBeGreaterThan(0);
652
586
  });
653
587
  it("shows 'Not configured' when policy does not exist (NoSuchBucketPolicy)", ()=>{
654
- const noSuchPolicyError = new Error("Policy does not exist");
655
- noSuchPolicyError.name = "NoSuchBucketPolicy";
588
+ const noSuchPolicyError = new Error('Policy does not exist');
589
+ noSuchPolicyError.name = 'NoSuchBucketPolicy';
656
590
  mockUseGetBucketPolicy.mockReturnValue({
657
591
  data: void 0,
658
592
  error: noSuchPolicyError,
659
- status: "error"
593
+ status: 'error'
660
594
  });
661
595
  renderBucketOverview();
662
- expect(screen.getByText("Not configured")).toBeInTheDocument();
596
+ expect(screen.getByText('Not configured')).toBeInTheDocument();
663
597
  });
664
- it("calls onEditPolicy when edit button is clicked", ()=>{
598
+ it('calls onEditPolicy when edit button is clicked', ()=>{
665
599
  const onEditPolicy = jest.fn();
666
600
  mockUseGetBucketPolicy.mockReturnValue({
667
601
  data: {
668
602
  Policy: '{"Version":"2012-10-17","Statement":[]}'
669
603
  },
670
604
  error: null,
671
- status: "success"
605
+ status: 'success'
672
606
  });
673
607
  renderBucketOverview({
674
608
  onEditPolicy
675
609
  });
676
- const editButton = screen.getByRole("button", {
610
+ const editButton = screen.getByRole('button', {
677
611
  name: /edit/i
678
612
  });
679
613
  fireEvent.click(editButton);
680
- expect(onEditPolicy).toHaveBeenCalledWith("test-bucket");
614
+ expect(onEditPolicy).toHaveBeenCalledWith('test-bucket');
615
+ });
616
+ });
617
+ describe('Extra Sections', ()=>{
618
+ it('renders extra sections between General and Data Protection', ()=>{
619
+ const Wrapper = createTestWrapper();
620
+ const extraSections = [
621
+ {
622
+ id: 'custom-section',
623
+ title: 'Custom Section',
624
+ render: ()=>/*#__PURE__*/ jsx("div", {
625
+ children: "Custom content"
626
+ })
627
+ }
628
+ ];
629
+ render(/*#__PURE__*/ jsx(MemoryRouter, {
630
+ children: /*#__PURE__*/ jsx(Wrapper, {
631
+ children: /*#__PURE__*/ jsxs(BucketOverview, {
632
+ bucketName: "test-bucket",
633
+ children: [
634
+ /*#__PURE__*/ jsx(BucketOverview.Actions, {}),
635
+ /*#__PURE__*/ jsxs(BucketOverview.Sections, {
636
+ children: [
637
+ /*#__PURE__*/ jsx(BucketOverview.GeneralSection, {}),
638
+ extraSections.map((section)=>/*#__PURE__*/ jsx(BucketOverview.Section, {
639
+ title: section.title,
640
+ children: section.render()
641
+ }, section.id)),
642
+ /*#__PURE__*/ jsx(BucketOverview.DataProtectionSection, {}),
643
+ /*#__PURE__*/ jsx(BucketOverview.PermissionsSection, {})
644
+ ]
645
+ })
646
+ ]
647
+ })
648
+ })
649
+ }));
650
+ expect(screen.getByText('Custom Section')).toBeInTheDocument();
651
+ expect(screen.getByText('Custom content')).toBeInTheDocument();
652
+ });
653
+ it('extra sections have access to BucketOverview context', ()=>{
654
+ const CustomSectionContent = ()=>{
655
+ const { bucketName } = useBucketOverviewContext();
656
+ return /*#__PURE__*/ jsxs("div", {
657
+ children: [
658
+ "Bucket name from context: ",
659
+ bucketName
660
+ ]
661
+ });
662
+ };
663
+ const Wrapper = createTestWrapper();
664
+ const extraSections = [
665
+ {
666
+ id: 'context-section',
667
+ title: 'Context Test',
668
+ render: ()=>/*#__PURE__*/ jsx(CustomSectionContent, {})
669
+ }
670
+ ];
671
+ render(/*#__PURE__*/ jsx(MemoryRouter, {
672
+ children: /*#__PURE__*/ jsx(Wrapper, {
673
+ children: /*#__PURE__*/ jsxs(BucketOverview, {
674
+ bucketName: "my-custom-bucket",
675
+ children: [
676
+ /*#__PURE__*/ jsx(BucketOverview.Actions, {}),
677
+ /*#__PURE__*/ jsxs(BucketOverview.Sections, {
678
+ children: [
679
+ /*#__PURE__*/ jsx(BucketOverview.GeneralSection, {}),
680
+ extraSections.map((section)=>/*#__PURE__*/ jsx(BucketOverview.Section, {
681
+ title: section.title,
682
+ children: section.render()
683
+ }, section.id)),
684
+ /*#__PURE__*/ jsx(BucketOverview.DataProtectionSection, {}),
685
+ /*#__PURE__*/ jsx(BucketOverview.PermissionsSection, {})
686
+ ]
687
+ })
688
+ ]
689
+ })
690
+ })
691
+ }));
692
+ expect(screen.getByText('Bucket name from context: my-custom-bucket')).toBeInTheDocument();
681
693
  });
682
694
  });
683
- describe("Field Overrides", ()=>{
684
- it("renders slot-based field override", ()=>{
695
+ describe('Field Overrides', ()=>{
696
+ it('renders slot-based field override', ()=>{
685
697
  const Wrapper = createTestWrapper();
686
- render(/*#__PURE__*/ jsx(external_react_router_dom_.MemoryRouter, {
698
+ render(/*#__PURE__*/ jsx(MemoryRouter, {
687
699
  children: /*#__PURE__*/ jsx(Wrapper, {
688
700
  children: /*#__PURE__*/ jsxs(BucketOverview, {
689
701
  bucketName: "test-bucket",
@@ -704,12 +716,12 @@ describe("BucketOverview", ()=>{
704
716
  })
705
717
  })
706
718
  }));
707
- expect(screen.getByText("Custom Location Content")).toBeInTheDocument();
708
- expect(screen.getByText("test-bucket")).toBeInTheDocument();
719
+ expect(screen.getByText('Custom Location Content')).toBeInTheDocument();
720
+ expect(screen.getByText('test-bucket')).toBeInTheDocument();
709
721
  });
710
- it("renders render prop field override", ()=>{
722
+ it('renders render prop field override', ()=>{
711
723
  const Wrapper = createTestWrapper();
712
- render(/*#__PURE__*/ jsx(external_react_router_dom_.MemoryRouter, {
724
+ render(/*#__PURE__*/ jsx(MemoryRouter, {
713
725
  children: /*#__PURE__*/ jsx(Wrapper, {
714
726
  children: /*#__PURE__*/ jsxs(BucketOverview, {
715
727
  bucketName: "test-bucket",
@@ -733,14 +745,14 @@ describe("BucketOverview", ()=>{
733
745
  })
734
746
  })
735
747
  }));
736
- expect(screen.getByText("Custom Versioning for test-bucket")).toBeInTheDocument();
748
+ expect(screen.getByText('Custom Versioning for test-bucket')).toBeInTheDocument();
737
749
  });
738
- it("prioritizes slot prop over render prop over default", ()=>{
750
+ it('prioritizes slot prop over render prop over default', ()=>{
739
751
  const Wrapper = createTestWrapper();
740
752
  const renderName = jest.fn(()=>/*#__PURE__*/ jsx("span", {
741
753
  children: "Render Prop Name"
742
754
  }));
743
- render(/*#__PURE__*/ jsx(external_react_router_dom_.MemoryRouter, {
755
+ render(/*#__PURE__*/ jsx(MemoryRouter, {
744
756
  children: /*#__PURE__*/ jsx(Wrapper, {
745
757
  children: /*#__PURE__*/ jsxs(BucketOverview, {
746
758
  bucketName: "test-bucket",
@@ -762,7 +774,7 @@ describe("BucketOverview", ()=>{
762
774
  })
763
775
  })
764
776
  }));
765
- expect(screen.getByText("Slot Prop Name")).toBeInTheDocument();
777
+ expect(screen.getByText('Slot Prop Name')).toBeInTheDocument();
766
778
  expect(renderName).not.toHaveBeenCalled();
767
779
  });
768
780
  });