@scality/data-browser-library 1.0.0-preview.8 → 1.0.1

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 (303) hide show
  1. package/dist/components/DataBrowserUI.d.ts +12 -0
  2. package/dist/components/DataBrowserUI.js +99 -0
  3. package/dist/components/Editor.d.ts +1 -1
  4. package/dist/components/Editor.js +3 -3
  5. package/dist/components/__tests__/BucketAccessor.test.js +214 -0
  6. package/dist/components/__tests__/BucketCorsPage.test.d.ts +1 -0
  7. package/dist/components/__tests__/BucketCorsPage.test.js +263 -0
  8. package/dist/components/__tests__/BucketCreate.test.d.ts +1 -0
  9. package/dist/components/__tests__/BucketCreate.test.js +574 -0
  10. package/dist/components/__tests__/BucketDetails.test.d.ts +1 -0
  11. package/dist/components/__tests__/BucketDetails.test.js +421 -0
  12. package/dist/components/__tests__/BucketLifecycleFormPage.test.d.ts +14 -0
  13. package/dist/components/__tests__/BucketLifecycleFormPage.test.js +618 -0
  14. package/dist/components/__tests__/BucketLifecycleList.test.d.ts +1 -0
  15. package/dist/components/__tests__/BucketLifecycleList.test.js +325 -0
  16. package/dist/components/__tests__/BucketList.test.js +495 -81
  17. package/dist/components/__tests__/BucketNotificationFormPage.test.d.ts +1 -0
  18. package/dist/components/__tests__/BucketNotificationFormPage.test.js +348 -0
  19. package/dist/components/__tests__/BucketNotificationList.test.d.ts +1 -0
  20. package/dist/components/__tests__/BucketNotificationList.test.js +379 -0
  21. package/dist/components/__tests__/BucketOverview.test.js +484 -179
  22. package/dist/components/__tests__/BucketPolicyPage.test.js +151 -99
  23. package/dist/components/__tests__/BucketReplicationFormPage.test.d.ts +16 -0
  24. package/dist/components/__tests__/BucketReplicationFormPage.test.js +1757 -0
  25. package/dist/components/__tests__/BucketReplicationList.test.d.ts +1 -0
  26. package/dist/components/__tests__/BucketReplicationList.test.js +344 -0
  27. package/dist/components/__tests__/CreateFolderButton.test.js +56 -56
  28. package/dist/components/__tests__/DeleteBucketButton.test.js +64 -64
  29. package/dist/components/__tests__/DeleteBucketConfigRuleButton.test.d.ts +1 -0
  30. package/dist/components/__tests__/DeleteBucketConfigRuleButton.test.js +196 -0
  31. package/dist/components/__tests__/DeleteObjectButton.test.js +64 -64
  32. package/dist/components/__tests__/EmptyBucketButton.test.d.ts +1 -0
  33. package/dist/components/__tests__/EmptyBucketButton.test.js +302 -0
  34. package/dist/components/__tests__/MetadataSearch.test.js +65 -65
  35. package/dist/components/__tests__/ObjectList.test.js +741 -240
  36. package/dist/components/__tests__/UploadButton.test.js +45 -45
  37. package/dist/components/breadcrumb/Breadcrumb.d.ts +6 -0
  38. package/dist/components/breadcrumb/Breadcrumb.js +37 -0
  39. package/dist/components/breadcrumb/DataBrowserBreadcrumb.d.ts +1 -0
  40. package/dist/components/breadcrumb/DataBrowserBreadcrumb.js +10 -0
  41. package/dist/components/breadcrumb/__tests__/Breadcrumb.test.d.ts +1 -0
  42. package/dist/components/breadcrumb/__tests__/Breadcrumb.test.js +196 -0
  43. package/dist/components/breadcrumb/__tests__/DataBrowserBreadcrumb.test.d.ts +1 -0
  44. package/dist/components/breadcrumb/__tests__/DataBrowserBreadcrumb.test.js +153 -0
  45. package/dist/components/breadcrumb/__tests__/useBreadcrumbPaths.test.d.ts +1 -0
  46. package/dist/components/breadcrumb/__tests__/useBreadcrumbPaths.test.js +134 -0
  47. package/dist/components/breadcrumb/index.d.ts +8 -0
  48. package/dist/components/breadcrumb/index.js +4 -0
  49. package/dist/components/breadcrumb/useBreadcrumbPaths.d.ts +2 -0
  50. package/dist/components/breadcrumb/useBreadcrumbPaths.js +82 -0
  51. package/dist/components/buckets/BucketAccessor.d.ts +2 -0
  52. package/dist/components/buckets/BucketAccessor.js +125 -0
  53. package/dist/components/buckets/BucketConfigEditButton.d.ts +8 -0
  54. package/dist/components/buckets/{BucketPolicyButton.js → BucketConfigEditButton.js} +9 -5
  55. package/dist/components/buckets/BucketCorsPage.d.ts +1 -0
  56. package/dist/components/buckets/BucketCorsPage.js +234 -0
  57. package/dist/components/buckets/BucketCreate.d.ts +50 -0
  58. package/dist/components/buckets/BucketCreate.js +279 -0
  59. package/dist/components/buckets/BucketDetails.d.ts +42 -0
  60. package/dist/components/buckets/BucketDetails.js +256 -40
  61. package/dist/components/buckets/BucketLifecycleFormPage.d.ts +15 -0
  62. package/dist/components/buckets/BucketLifecycleFormPage.js +1086 -0
  63. package/dist/components/buckets/BucketLifecycleList.d.ts +10 -0
  64. package/dist/components/buckets/BucketLifecycleList.js +270 -0
  65. package/dist/components/buckets/BucketList.d.ts +6 -4
  66. package/dist/components/buckets/BucketList.js +161 -94
  67. package/dist/components/buckets/BucketLocation.js +4 -4
  68. package/dist/components/buckets/BucketOverview.d.ts +86 -5
  69. package/dist/components/buckets/BucketOverview.js +481 -192
  70. package/dist/components/buckets/BucketPage.js +44 -22
  71. package/dist/components/buckets/BucketPolicyPage.js +155 -127
  72. package/dist/components/buckets/BucketReplicationFormPage.d.ts +1 -0
  73. package/dist/components/buckets/BucketReplicationFormPage.js +835 -0
  74. package/dist/components/buckets/BucketReplicationList.d.ts +11 -0
  75. package/dist/components/buckets/BucketReplicationList.js +189 -0
  76. package/dist/components/buckets/BucketVersioning.d.ts +4 -0
  77. package/dist/components/buckets/BucketVersioning.js +76 -0
  78. package/dist/components/buckets/DeleteBucketButton.js +8 -8
  79. package/dist/components/buckets/DeleteBucketConfigRuleButton.d.ts +18 -0
  80. package/dist/components/buckets/DeleteBucketConfigRuleButton.js +53 -0
  81. package/dist/components/buckets/EmptyBucketButton.d.ts +5 -0
  82. package/dist/components/buckets/EmptyBucketButton.js +232 -0
  83. package/dist/components/buckets/EmptyBucketSummary.d.ts +9 -0
  84. package/dist/components/buckets/EmptyBucketSummary.js +60 -0
  85. package/dist/components/buckets/EmptyBucketSummaryList.d.ts +13 -0
  86. package/dist/components/buckets/EmptyBucketSummaryList.js +140 -0
  87. package/dist/components/buckets/__tests__/BucketVersioning.test.d.ts +1 -0
  88. package/dist/components/buckets/__tests__/BucketVersioning.test.js +163 -0
  89. package/dist/components/buckets/notifications/BucketNotificationFormPage.d.ts +1 -0
  90. package/dist/components/buckets/notifications/BucketNotificationFormPage.js +316 -0
  91. package/dist/components/buckets/notifications/BucketNotificationList.d.ts +10 -0
  92. package/dist/components/buckets/notifications/BucketNotificationList.js +267 -0
  93. package/dist/components/buckets/notifications/EventsSection.js +145 -29
  94. package/dist/components/buckets/notifications/__tests__/events.test.d.ts +1 -0
  95. package/dist/components/buckets/notifications/__tests__/events.test.js +56 -0
  96. package/dist/components/buckets/notifications/events.d.ts +71 -7
  97. package/dist/components/buckets/notifications/events.js +98 -16
  98. package/dist/components/index.d.ts +27 -13
  99. package/dist/components/index.js +20 -6
  100. package/dist/components/layouts/ArrowNavigation.d.ts +3 -0
  101. package/dist/components/layouts/ArrowNavigation.js +28 -0
  102. package/dist/components/layouts/BrowserPageLayout.d.ts +5 -1
  103. package/dist/components/layouts/BrowserPageLayout.js +10 -5
  104. package/dist/components/objects/CreateFolderButton.d.ts +2 -2
  105. package/dist/components/objects/CreateFolderButton.js +12 -12
  106. package/dist/components/objects/DeleteObjectButton.d.ts +1 -1
  107. package/dist/components/objects/DeleteObjectButton.js +19 -21
  108. package/dist/components/objects/GetPresignedUrlButton.d.ts +7 -0
  109. package/dist/components/objects/GetPresignedUrlButton.js +255 -0
  110. package/dist/components/objects/ObjectDetails/ObjectMetadata.d.ts +2 -2
  111. package/dist/components/objects/ObjectDetails/ObjectMetadata.js +263 -230
  112. package/dist/components/objects/ObjectDetails/ObjectSummary.d.ts +2 -2
  113. package/dist/components/objects/ObjectDetails/ObjectSummary.js +540 -138
  114. package/dist/components/objects/ObjectDetails/ObjectTags.d.ts +2 -2
  115. package/dist/components/objects/ObjectDetails/ObjectTags.js +95 -123
  116. package/dist/components/objects/ObjectDetails/__tests__/ObjectDetails.test.d.ts +1 -0
  117. package/dist/components/objects/ObjectDetails/__tests__/ObjectDetails.test.js +516 -0
  118. package/dist/components/objects/ObjectDetails/__tests__/ObjectSummary.test.d.ts +1 -0
  119. package/dist/components/objects/ObjectDetails/__tests__/ObjectSummary.test.js +1064 -0
  120. package/dist/components/objects/ObjectDetails/index.d.ts +18 -2
  121. package/dist/components/objects/ObjectDetails/index.js +152 -40
  122. package/dist/components/objects/ObjectList.d.ts +12 -10
  123. package/dist/components/objects/ObjectList.js +590 -263
  124. package/dist/components/objects/ObjectLock/EditRetentionButton.d.ts +4 -0
  125. package/dist/components/objects/ObjectLock/EditRetentionButton.js +32 -0
  126. package/dist/components/objects/ObjectLock/ObjectLockRetentionSettings.d.ts +3 -0
  127. package/dist/components/objects/ObjectLock/ObjectLockRetentionSettings.js +211 -0
  128. package/dist/components/objects/ObjectLock/ObjectLockSettings.d.ts +9 -0
  129. package/dist/components/objects/ObjectLock/ObjectLockSettings.js +159 -0
  130. package/dist/components/objects/ObjectLock/ObjectLockSettingsUtils.d.ts +8 -0
  131. package/dist/components/objects/ObjectLock/ObjectLockSettingsUtils.js +39 -0
  132. package/dist/components/objects/ObjectLock/__tests__/EditRetentionButton.test.d.ts +1 -0
  133. package/dist/components/objects/ObjectLock/__tests__/EditRetentionButton.test.js +204 -0
  134. package/dist/components/objects/ObjectLock/__tests__/ObjectLockSettings.test.d.ts +1 -0
  135. package/dist/components/objects/ObjectLock/__tests__/ObjectLockSettings.test.js +374 -0
  136. package/dist/components/objects/ObjectPage.js +12 -8
  137. package/dist/components/objects/UploadButton.d.ts +3 -3
  138. package/dist/components/objects/UploadButton.js +10 -10
  139. package/dist/components/objects/__tests__/GetPresignedUrlButton.test.d.ts +1 -0
  140. package/dist/components/objects/__tests__/GetPresignedUrlButton.test.js +531 -0
  141. package/dist/components/providers/DataBrowserProvider.d.ts +23 -12
  142. package/dist/components/providers/DataBrowserProvider.js +60 -38
  143. package/dist/components/providers/QueryProvider.d.ts +9 -0
  144. package/dist/components/providers/QueryProvider.js +21 -0
  145. package/dist/components/search/MetadataSearch.js +29 -28
  146. package/dist/components/search/SearchHints.js +1 -1
  147. package/dist/components/ui/ArrayFieldActions.d.ts +36 -0
  148. package/dist/components/ui/ArrayFieldActions.js +43 -0
  149. package/dist/components/ui/ConfirmDeleteRuleModal.d.ts +16 -0
  150. package/dist/components/ui/ConfirmDeleteRuleModal.js +48 -0
  151. package/dist/components/ui/DeleteObjectModalContent.d.ts +1 -1
  152. package/dist/components/ui/DeleteObjectModalContent.js +12 -12
  153. package/dist/components/ui/FilterFormSection.d.ts +44 -0
  154. package/dist/components/ui/FilterFormSection.js +159 -0
  155. package/dist/components/ui/Search.elements.d.ts +2 -2
  156. package/dist/components/ui/Search.elements.js +7 -7
  157. package/dist/components/ui/Table.elements.d.ts +2 -1
  158. package/dist/components/ui/Table.elements.js +18 -12
  159. package/dist/config/__tests__/factory.test.d.ts +1 -0
  160. package/dist/config/__tests__/factory.test.js +311 -0
  161. package/dist/config/factory.d.ts +14 -49
  162. package/dist/config/factory.js +23 -68
  163. package/dist/config/types.d.ts +212 -34
  164. package/dist/contexts/DataBrowserUICustomizationContext.d.ts +27 -0
  165. package/dist/contexts/DataBrowserUICustomizationContext.js +13 -0
  166. package/dist/hooks/__tests__/useAccessibleBuckets.test.d.ts +1 -0
  167. package/dist/hooks/__tests__/useAccessibleBuckets.test.js +145 -0
  168. package/dist/hooks/__tests__/useISVBucketDetection.test.d.ts +1 -0
  169. package/dist/hooks/__tests__/useISVBucketDetection.test.js +188 -0
  170. package/dist/hooks/__tests__/useIsBucketEmpty.test.js +27 -27
  171. package/dist/hooks/__tests__/useLoginMutation.test.d.ts +1 -0
  172. package/dist/hooks/__tests__/useLoginMutation.test.js +194 -0
  173. package/dist/hooks/bucketConfiguration.d.ts +8 -1
  174. package/dist/hooks/bucketConfiguration.js +52 -51
  175. package/dist/hooks/bucketOperations.d.ts +10 -1
  176. package/dist/hooks/bucketOperations.js +10 -9
  177. package/dist/hooks/factories/__tests__/useCreateS3FunctionMutationHook.test.js +80 -80
  178. package/dist/hooks/factories/__tests__/useCreateS3InfiniteQueryHook.test.js +80 -80
  179. package/dist/hooks/factories/__tests__/useCreateS3LoginHook.test.js +44 -44
  180. package/dist/hooks/factories/__tests__/useCreateS3MutationHook.test.js +63 -63
  181. package/dist/hooks/factories/__tests__/useCreateS3QueryHook.test.js +95 -52
  182. package/dist/hooks/factories/index.d.ts +4 -4
  183. package/dist/hooks/factories/index.js +2 -2
  184. package/dist/hooks/factories/useCreateS3InfiniteQueryHook.d.ts +2 -2
  185. package/dist/hooks/factories/useCreateS3InfiniteQueryHook.js +16 -13
  186. package/dist/hooks/factories/useCreateS3LoginHook.d.ts +2 -2
  187. package/dist/hooks/factories/useCreateS3LoginHook.js +1 -1
  188. package/dist/hooks/factories/useCreateS3MutationHook.d.ts +3 -3
  189. package/dist/hooks/factories/useCreateS3MutationHook.js +7 -2
  190. package/dist/hooks/factories/useCreateS3QueryHook.d.ts +2 -2
  191. package/dist/hooks/factories/useCreateS3QueryHook.js +29 -3
  192. package/dist/hooks/index.d.ts +19 -8
  193. package/dist/hooks/index.js +16 -5
  194. package/dist/hooks/loginOperations.d.ts +1 -1
  195. package/dist/hooks/loginOperations.js +1 -1
  196. package/dist/hooks/objectOperations.d.ts +2 -2
  197. package/dist/hooks/objectOperations.js +50 -49
  198. package/dist/hooks/presignedOperations.d.ts +4 -4
  199. package/dist/hooks/presignedOperations.js +5 -5
  200. package/dist/hooks/useAccessibleBuckets.d.ts +11 -0
  201. package/dist/hooks/useAccessibleBuckets.js +115 -0
  202. package/dist/hooks/useBatchObjectLegalHold.d.ts +11 -0
  203. package/dist/hooks/useBatchObjectLegalHold.js +48 -0
  204. package/dist/hooks/useBucketConfigEditor.d.ts +31 -0
  205. package/dist/hooks/useBucketConfigEditor.js +82 -0
  206. package/dist/hooks/useDataBrowserNavigate.d.ts +28 -0
  207. package/dist/hooks/useDataBrowserNavigate.js +24 -0
  208. package/dist/hooks/useDeleteBucketConfigRule.d.ts +26 -0
  209. package/dist/hooks/useDeleteBucketConfigRule.js +46 -0
  210. package/dist/hooks/useEmptyBucket.d.ts +27 -0
  211. package/dist/hooks/useEmptyBucket.js +116 -0
  212. package/dist/hooks/useFeatures.d.ts +7 -0
  213. package/dist/hooks/useFeatures.js +8 -0
  214. package/dist/hooks/useISVBucketDetection.d.ts +15 -0
  215. package/dist/hooks/useISVBucketDetection.js +27 -0
  216. package/dist/hooks/useIsBucketEmpty.js +4 -4
  217. package/dist/hooks/useLimitedAccessFlow.d.ts +48 -0
  218. package/dist/hooks/useLimitedAccessFlow.js +23 -0
  219. package/dist/hooks/useS3Client.d.ts +6 -0
  220. package/dist/hooks/useS3Client.js +3 -2
  221. package/dist/hooks/useS3ConfigSwitch.d.ts +11 -0
  222. package/dist/hooks/useS3ConfigSwitch.js +37 -0
  223. package/dist/hooks/useSupportedNotificationEvents.d.ts +6 -0
  224. package/dist/hooks/useSupportedNotificationEvents.js +8 -0
  225. package/dist/hooks/useTableRowSelection.d.ts +9 -0
  226. package/dist/hooks/useTableRowSelection.js +45 -0
  227. package/dist/index.d.ts +6 -6
  228. package/dist/index.js +2 -2
  229. package/dist/schemas/bucketPolicySchema.json +3 -13
  230. package/dist/test/msw/handlers/deleteBucket.d.ts +1 -1
  231. package/dist/test/msw/handlers/deleteBucket.js +20 -10
  232. package/dist/test/msw/handlers/getBucketAcl.d.ts +1 -1
  233. package/dist/test/msw/handlers/getBucketAcl.js +29 -17
  234. package/dist/test/msw/handlers/getBucketLocation.d.ts +1 -1
  235. package/dist/test/msw/handlers/getBucketLocation.js +29 -15
  236. package/dist/test/msw/handlers/getBucketPolicy.d.ts +1 -1
  237. package/dist/test/msw/handlers/getBucketPolicy.js +52 -32
  238. package/dist/test/msw/handlers/headObject.d.ts +1 -1
  239. package/dist/test/msw/handlers/headObject.js +31 -13
  240. package/dist/test/msw/handlers/listBuckets.d.ts +1 -1
  241. package/dist/test/msw/handlers/listBuckets.js +5 -3
  242. package/dist/test/msw/handlers/listObjectVersions.d.ts +1 -1
  243. package/dist/test/msw/handlers/listObjectVersions.js +38 -26
  244. package/dist/test/msw/handlers/listObjects.d.ts +1 -1
  245. package/dist/test/msw/handlers/listObjects.js +35 -23
  246. package/dist/test/msw/handlers/objectLegalHold.d.ts +1 -1
  247. package/dist/test/msw/handlers/objectLegalHold.js +32 -17
  248. package/dist/test/msw/handlers/objectRetention.d.ts +1 -1
  249. package/dist/test/msw/handlers/objectRetention.js +31 -17
  250. package/dist/test/msw/handlers/putBucketAcl.d.ts +1 -1
  251. package/dist/test/msw/handlers/putBucketAcl.js +29 -14
  252. package/dist/test/msw/handlers/putObject.d.ts +1 -1
  253. package/dist/test/msw/handlers/putObject.js +27 -12
  254. package/dist/test/msw/handlers.d.ts +3 -3
  255. package/dist/test/msw/handlers.js +77 -54
  256. package/dist/test/msw/index.d.ts +2 -2
  257. package/dist/test/msw/index.js +1 -1
  258. package/dist/test/msw/server.d.ts +1 -1
  259. package/dist/test/msw/server.js +1 -1
  260. package/dist/test/msw/utils.js +2 -2
  261. package/dist/test/setup.d.ts +1 -1
  262. package/dist/test/setup.js +13 -30
  263. package/dist/test/testUtils.d.ts +170 -36
  264. package/dist/test/testUtils.js +229 -116
  265. package/dist/test/utils/errorHandling.test.js +146 -108
  266. package/dist/types/index.d.ts +49 -36
  267. package/dist/types/monaco.d.ts +13 -0
  268. package/dist/types/monaco.js +0 -0
  269. package/dist/utils/__tests__/proxyMiddleware.test.d.ts +1 -0
  270. package/dist/utils/__tests__/proxyMiddleware.test.js +579 -0
  271. package/dist/utils/__tests__/s3Client.test.d.ts +1 -0
  272. package/dist/utils/__tests__/s3Client.test.js +340 -0
  273. package/dist/utils/__tests__/s3ConfigIdentifier.test.d.ts +1 -0
  274. package/dist/utils/__tests__/s3ConfigIdentifier.test.js +437 -0
  275. package/dist/utils/constants.d.ts +22 -0
  276. package/dist/utils/constants.js +19 -0
  277. package/dist/utils/deletion/index.d.ts +2 -2
  278. package/dist/utils/deletion/index.js +1 -1
  279. package/dist/utils/deletion/messages.d.ts +1 -1
  280. package/dist/utils/deletion/messages.js +4 -4
  281. package/dist/utils/errorHandling.d.ts +12 -3
  282. package/dist/utils/errorHandling.js +12 -7
  283. package/dist/utils/hooks.js +8 -8
  284. package/dist/utils/index.d.ts +5 -2
  285. package/dist/utils/index.js +5 -1
  286. package/dist/utils/proxyMiddleware.d.ts +32 -13
  287. package/dist/utils/proxyMiddleware.js +90 -36
  288. package/dist/utils/s3Client.d.ts +14 -4
  289. package/dist/utils/s3Client.js +5 -26
  290. package/dist/utils/s3ConfigIdentifier.d.ts +79 -0
  291. package/dist/utils/s3ConfigIdentifier.js +57 -0
  292. package/dist/utils/s3RuleUtils.d.ts +53 -0
  293. package/dist/utils/s3RuleUtils.js +101 -0
  294. package/package.json +10 -8
  295. package/dist/components/__tests__/BucketNotificationCreatePage.test.js +0 -316
  296. package/dist/components/buckets/BucketPolicyButton.d.ts +0 -7
  297. package/dist/components/buckets/notifications/BucketNotificationCreatePage.d.ts +0 -1
  298. package/dist/components/buckets/notifications/BucketNotificationCreatePage.js +0 -234
  299. package/dist/hooks/useLoginMutation.d.ts +0 -21
  300. package/dist/hooks/useLoginMutation.js +0 -9
  301. package/dist/utils/useFeatures.d.ts +0 -1
  302. package/dist/utils/useFeatures.js +0 -7
  303. /package/dist/components/__tests__/{BucketNotificationCreatePage.test.d.ts → BucketAccessor.test.d.ts} +0 -0
@@ -0,0 +1,618 @@
1
+ import { jsx, jsxs } from "react/jsx-runtime";
2
+ import { fireEvent, render, screen, waitFor } from "@testing-library/react";
3
+ import user_event from "@testing-library/user-event";
4
+ import { MemoryRouter, Route, Routes } from "react-router";
5
+ import { useGetBucketLifecycle, useSetBucketLifecycle } from "../../hooks/bucketConfiguration.js";
6
+ import { createTestWrapper, findToggleByLabel, mockErrorSubmit, mockOffsetSize, mockSuccessSubmit, submitForm } from "../../test/testUtils.js";
7
+ import { BucketLifecycleFormPage } from "../buckets/BucketLifecycleFormPage.js";
8
+ jest.mock('../../hooks/bucketConfiguration', ()=>({
9
+ useGetBucketLifecycle: jest.fn(),
10
+ useSetBucketLifecycle: jest.fn()
11
+ }));
12
+ const mockUseGetBucketLifecycle = jest.mocked(useGetBucketLifecycle);
13
+ const mockUseSetBucketLifecycle = jest.mocked(useSetBucketLifecycle);
14
+ const mockNavigate = jest.fn();
15
+ const mockShowToast = jest.fn();
16
+ jest.mock('react-router', ()=>({
17
+ ...jest.requireActual('react-router'),
18
+ useNavigate: ()=>mockNavigate
19
+ }));
20
+ jest.mock('@scality/core-ui', ()=>({
21
+ ...jest.requireActual('@scality/core-ui'),
22
+ useToast: ()=>({
23
+ showToast: mockShowToast
24
+ })
25
+ }));
26
+ const renderBucketLifecycleFormPage = (bucketName = 'test-bucket', ruleId)=>{
27
+ const Wrapper = createTestWrapper();
28
+ const path = ruleId ? `/buckets/${bucketName}/lifecycle/${ruleId}/edit` : `/buckets/${bucketName}/lifecycle/create`;
29
+ return render(/*#__PURE__*/ jsx(MemoryRouter, {
30
+ initialEntries: [
31
+ path
32
+ ],
33
+ children: /*#__PURE__*/ jsx(Wrapper, {
34
+ children: /*#__PURE__*/ jsxs(Routes, {
35
+ children: [
36
+ /*#__PURE__*/ jsx(Route, {
37
+ path: "/buckets/:bucketName/lifecycle/create",
38
+ element: /*#__PURE__*/ jsx(BucketLifecycleFormPage, {})
39
+ }),
40
+ /*#__PURE__*/ jsx(Route, {
41
+ path: "/buckets/:bucketName/lifecycle/:ruleId/edit",
42
+ element: /*#__PURE__*/ jsx(BucketLifecycleFormPage, {})
43
+ })
44
+ ]
45
+ })
46
+ })
47
+ }));
48
+ };
49
+ describe('BucketLifecycleFormPage', ()=>{
50
+ const mockMutate = jest.fn();
51
+ const enableExpirationAction = async ()=>{
52
+ const expirationToggle = findToggleByLabel('Expiration current version');
53
+ await user_event.click(expirationToggle);
54
+ };
55
+ const fillRequiredFields = async (ruleId)=>{
56
+ await user_event.type(screen.getByLabelText(/rule id/i), ruleId);
57
+ await enableExpirationAction();
58
+ };
59
+ beforeEach(()=>{
60
+ jest.clearAllMocks();
61
+ mockNavigate.mockClear();
62
+ mockShowToast.mockClear();
63
+ mockOffsetSize(800, 600);
64
+ mockUseGetBucketLifecycle.mockReturnValue({
65
+ data: void 0,
66
+ status: 'success'
67
+ });
68
+ mockUseSetBucketLifecycle.mockReturnValue({
69
+ mutate: mockMutate,
70
+ isPending: false
71
+ });
72
+ });
73
+ describe('Page Rendering', ()=>{
74
+ it('renders create mode with correct title', ()=>{
75
+ renderBucketLifecycleFormPage();
76
+ expect(screen.getByText('Create Lifecycle Rule')).toBeInTheDocument();
77
+ });
78
+ it('renders edit mode with correct title when rule exists', async ()=>{
79
+ const existingRule = {
80
+ ID: 'test-rule',
81
+ Status: 'Enabled',
82
+ Filter: {},
83
+ Expiration: {
84
+ Days: 30
85
+ }
86
+ };
87
+ mockUseGetBucketLifecycle.mockReturnValue({
88
+ data: {
89
+ Rules: [
90
+ existingRule
91
+ ]
92
+ },
93
+ status: 'success'
94
+ });
95
+ renderBucketLifecycleFormPage('test-bucket', 'test-rule');
96
+ await waitFor(()=>{
97
+ expect(screen.getByText('Edit Lifecycle Rule')).toBeInTheDocument();
98
+ });
99
+ });
100
+ it('shows loading state when fetching lifecycle data', ()=>{
101
+ mockUseGetBucketLifecycle.mockReturnValue({
102
+ data: void 0,
103
+ status: 'pending'
104
+ });
105
+ renderBucketLifecycleFormPage();
106
+ expect(screen.getByText('Loading...')).toBeInTheDocument();
107
+ });
108
+ it('shows error when rule not found in edit mode', ()=>{
109
+ mockUseGetBucketLifecycle.mockReturnValue({
110
+ data: {
111
+ Rules: []
112
+ },
113
+ status: 'success'
114
+ });
115
+ renderBucketLifecycleFormPage('test-bucket', 'non-existent');
116
+ expect(screen.getByText('Rule not found')).toBeInTheDocument();
117
+ });
118
+ });
119
+ describe('Form Fields - Initial State', ()=>{
120
+ it('renders required form fields in create mode', ()=>{
121
+ renderBucketLifecycleFormPage();
122
+ expect(screen.getByLabelText(/rule id/i)).toBeInTheDocument();
123
+ expect(screen.getByLabelText(/status/i)).toBeInTheDocument();
124
+ expect(screen.getByLabelText(/filter/i)).toBeInTheDocument();
125
+ });
126
+ it('renders all lifecycle action toggles', ()=>{
127
+ renderBucketLifecycleFormPage();
128
+ expect(screen.getByText('Transition current version')).toBeInTheDocument();
129
+ expect(screen.getByText('Expiration current version')).toBeInTheDocument();
130
+ expect(screen.getByText('Transition noncurrent version')).toBeInTheDocument();
131
+ expect(screen.getByText('Expiration noncurrent version')).toBeInTheDocument();
132
+ expect(screen.getByText('Expire incomplete multipart upload')).toBeInTheDocument();
133
+ });
134
+ it('shows all filter type options when filter select is opened', async ()=>{
135
+ renderBucketLifecycleFormPage();
136
+ const filterSelect = screen.getByLabelText(/filter/i);
137
+ await user_event.click(filterSelect);
138
+ expect(screen.getByRole('option', {
139
+ name: 'All objects'
140
+ })).toBeInTheDocument();
141
+ expect(screen.getByRole('option', {
142
+ name: 'Prefix filter'
143
+ })).toBeInTheDocument();
144
+ expect(screen.getByRole('option', {
145
+ name: 'Tags filter'
146
+ })).toBeInTheDocument();
147
+ expect(screen.getByRole('option', {
148
+ name: 'Prefix and tags filter'
149
+ })).toBeInTheDocument();
150
+ });
151
+ it('disables rule ID input in edit mode', async ()=>{
152
+ const existingRule = {
153
+ ID: 'test-rule',
154
+ Status: 'Enabled',
155
+ Filter: {},
156
+ Expiration: {
157
+ Days: 30
158
+ }
159
+ };
160
+ mockUseGetBucketLifecycle.mockReturnValue({
161
+ data: {
162
+ Rules: [
163
+ existingRule
164
+ ]
165
+ },
166
+ status: 'success'
167
+ });
168
+ renderBucketLifecycleFormPage('test-bucket', 'test-rule');
169
+ await waitFor(()=>{
170
+ expect(screen.getByText('test-rule')).toBeInTheDocument();
171
+ });
172
+ expect(screen.queryByRole('textbox', {
173
+ name: /rule id/i
174
+ })).not.toBeInTheDocument();
175
+ });
176
+ });
177
+ describe('Form Validation', ()=>{
178
+ it('validates rule ID is required', async ()=>{
179
+ renderBucketLifecycleFormPage();
180
+ const ruleIdInput = screen.getByLabelText(/rule id/i);
181
+ await user_event.type(ruleIdInput, 'test');
182
+ await user_event.clear(ruleIdInput);
183
+ await user_event.tab();
184
+ await waitFor(()=>{
185
+ expect(screen.getByText(/rule id is required/i)).toBeInTheDocument();
186
+ });
187
+ });
188
+ it('validates rule ID uniqueness against existing rules', async ()=>{
189
+ mockUseGetBucketLifecycle.mockReturnValue({
190
+ data: {
191
+ Rules: [
192
+ {
193
+ ID: 'existing-rule',
194
+ Status: 'Enabled',
195
+ Expiration: {
196
+ Days: 30
197
+ }
198
+ }
199
+ ]
200
+ },
201
+ status: 'success'
202
+ });
203
+ renderBucketLifecycleFormPage();
204
+ const ruleIdInput = screen.getByLabelText(/rule id/i);
205
+ await user_event.type(ruleIdInput, 'existing-rule');
206
+ await user_event.tab();
207
+ await waitFor(()=>{
208
+ expect(screen.getByText(/a rule with this id already exists/i)).toBeInTheDocument();
209
+ });
210
+ });
211
+ it('disables create button when form is pristine', ()=>{
212
+ renderBucketLifecycleFormPage();
213
+ const createButton = screen.getByRole('button', {
214
+ name: /create/i
215
+ });
216
+ expect(createButton).toBeDisabled();
217
+ });
218
+ it('disables create button when no lifecycle action is enabled', async ()=>{
219
+ renderBucketLifecycleFormPage();
220
+ await user_event.type(screen.getByLabelText(/rule id/i), 'test-rule');
221
+ const createButton = screen.getByRole('button', {
222
+ name: /create/i
223
+ });
224
+ expect(createButton).toBeDisabled();
225
+ });
226
+ it('enables create button when form is valid and has at least one action', async ()=>{
227
+ renderBucketLifecycleFormPage();
228
+ await fillRequiredFields('valid-rule');
229
+ await waitFor(()=>{
230
+ const createButton = screen.getByRole('button', {
231
+ name: /create/i
232
+ });
233
+ expect(createButton).toBeEnabled();
234
+ });
235
+ });
236
+ });
237
+ describe('Form Submission - Create Mode', ()=>{
238
+ it('submits minimal lifecycle rule with expiration action', async ()=>{
239
+ renderBucketLifecycleFormPage();
240
+ await fillRequiredFields('minimal-rule');
241
+ mockSuccessSubmit(mockMutate);
242
+ await submitForm('create');
243
+ await waitFor(()=>{
244
+ expect(mockMutate).toHaveBeenCalledWith(expect.objectContaining({
245
+ Bucket: 'test-bucket',
246
+ LifecycleConfiguration: {
247
+ Rules: expect.arrayContaining([
248
+ expect.objectContaining({
249
+ ID: 'minimal-rule',
250
+ Status: 'Enabled',
251
+ Filter: {},
252
+ Expiration: {
253
+ Days: 30
254
+ }
255
+ })
256
+ ])
257
+ }
258
+ }), expect.any(Object));
259
+ });
260
+ });
261
+ it('navigates to bucket lifecycle tab on successful creation', async ()=>{
262
+ renderBucketLifecycleFormPage();
263
+ await fillRequiredFields('success-rule');
264
+ mockSuccessSubmit(mockMutate);
265
+ await submitForm('create');
266
+ await waitFor(()=>{
267
+ expect(mockNavigate).toHaveBeenCalledWith('/buckets/test-bucket?tab=lifecycle');
268
+ });
269
+ });
270
+ it('displays success toast after rule creation', async ()=>{
271
+ renderBucketLifecycleFormPage();
272
+ await fillRequiredFields('toast-rule');
273
+ mockSuccessSubmit(mockMutate);
274
+ await submitForm('create');
275
+ await waitFor(()=>{
276
+ expect(mockShowToast).toHaveBeenCalledWith({
277
+ open: true,
278
+ message: 'Lifecycle rule created successfully',
279
+ status: 'success'
280
+ });
281
+ });
282
+ });
283
+ it('displays error toast when creation fails', async ()=>{
284
+ renderBucketLifecycleFormPage();
285
+ await fillRequiredFields('error-rule');
286
+ mockErrorSubmit(mockMutate, 'Access Denied');
287
+ await submitForm('create');
288
+ await waitFor(()=>{
289
+ expect(mockShowToast).toHaveBeenCalledWith({
290
+ open: true,
291
+ message: 'Access Denied',
292
+ status: 'error'
293
+ });
294
+ expect(mockNavigate).not.toHaveBeenCalled();
295
+ });
296
+ });
297
+ it('appends new rule to existing rules on creation', async ()=>{
298
+ mockUseGetBucketLifecycle.mockReturnValue({
299
+ data: {
300
+ Rules: [
301
+ {
302
+ ID: 'existing-rule',
303
+ Status: 'Enabled',
304
+ Filter: {},
305
+ Expiration: {
306
+ Days: 90
307
+ }
308
+ }
309
+ ]
310
+ },
311
+ status: 'success'
312
+ });
313
+ renderBucketLifecycleFormPage();
314
+ await fillRequiredFields('new-rule');
315
+ mockSuccessSubmit(mockMutate);
316
+ await submitForm('create');
317
+ await waitFor(()=>{
318
+ const call = mockMutate.mock.calls[0][0];
319
+ expect(call.LifecycleConfiguration.Rules).toHaveLength(2);
320
+ expect(call.LifecycleConfiguration.Rules[0].ID).toBe('existing-rule');
321
+ expect(call.LifecycleConfiguration.Rules[1].ID).toBe('new-rule');
322
+ });
323
+ });
324
+ });
325
+ describe('Form Submission - Edit Mode', ()=>{
326
+ it('updates existing rule in edit mode', async ()=>{
327
+ const existingRule = {
328
+ ID: 'update-rule',
329
+ Status: 'Enabled',
330
+ Filter: {},
331
+ Expiration: {
332
+ Days: 30
333
+ }
334
+ };
335
+ mockUseGetBucketLifecycle.mockReturnValue({
336
+ data: {
337
+ Rules: [
338
+ existingRule
339
+ ]
340
+ },
341
+ status: 'success'
342
+ });
343
+ renderBucketLifecycleFormPage('test-bucket', 'update-rule');
344
+ await waitFor(()=>{
345
+ expect(screen.getByText('Edit Lifecycle Rule')).toBeInTheDocument();
346
+ });
347
+ const statusSelect = screen.getByLabelText(/status/i);
348
+ await user_event.click(statusSelect);
349
+ await user_event.click(screen.getByRole('option', {
350
+ name: 'Disabled'
351
+ }));
352
+ mockSuccessSubmit(mockMutate);
353
+ await submitForm('save');
354
+ await waitFor(()=>{
355
+ const call = mockMutate.mock.calls[0][0];
356
+ expect(call.LifecycleConfiguration.Rules).toHaveLength(1);
357
+ expect(call.LifecycleConfiguration.Rules[0].ID).toBe('update-rule');
358
+ expect(call.LifecycleConfiguration.Rules[0].Status).toBe('Disabled');
359
+ });
360
+ });
361
+ it('displays update success toast in edit mode', async ()=>{
362
+ const existingRule = {
363
+ ID: 'edit-rule',
364
+ Status: 'Enabled',
365
+ Filter: {},
366
+ Expiration: {
367
+ Days: 30
368
+ }
369
+ };
370
+ mockUseGetBucketLifecycle.mockReturnValue({
371
+ data: {
372
+ Rules: [
373
+ existingRule
374
+ ]
375
+ },
376
+ status: 'success'
377
+ });
378
+ renderBucketLifecycleFormPage('test-bucket', 'edit-rule');
379
+ await waitFor(()=>{
380
+ expect(screen.getByText('Edit Lifecycle Rule')).toBeInTheDocument();
381
+ });
382
+ const statusSelect = screen.getByLabelText(/status/i);
383
+ await user_event.click(statusSelect);
384
+ await user_event.click(screen.getByRole('option', {
385
+ name: 'Disabled'
386
+ }));
387
+ mockSuccessSubmit(mockMutate);
388
+ await submitForm('save');
389
+ await waitFor(()=>{
390
+ expect(mockShowToast).toHaveBeenCalledWith({
391
+ open: true,
392
+ message: 'Lifecycle rule updated successfully',
393
+ status: 'success'
394
+ });
395
+ });
396
+ });
397
+ it('disables save button when form is not dirty', async ()=>{
398
+ const existingRule = {
399
+ ID: 'unchanged-rule',
400
+ Status: 'Enabled',
401
+ Filter: {},
402
+ Expiration: {
403
+ Days: 30
404
+ }
405
+ };
406
+ mockUseGetBucketLifecycle.mockReturnValue({
407
+ data: {
408
+ Rules: [
409
+ existingRule
410
+ ]
411
+ },
412
+ status: 'success'
413
+ });
414
+ renderBucketLifecycleFormPage('test-bucket', 'unchanged-rule');
415
+ await waitFor(()=>{
416
+ expect(screen.getByText('Edit Lifecycle Rule')).toBeInTheDocument();
417
+ });
418
+ const saveButton = screen.getByRole('button', {
419
+ name: /save/i
420
+ });
421
+ expect(saveButton).toBeDisabled();
422
+ });
423
+ });
424
+ describe('Rule Data Loading', ()=>{
425
+ it('loads rule with prefix filter correctly', async ()=>{
426
+ const rule = {
427
+ ID: 'prefix-rule',
428
+ Status: 'Enabled',
429
+ Filter: {
430
+ Prefix: 'documents/'
431
+ },
432
+ Expiration: {
433
+ Days: 90
434
+ }
435
+ };
436
+ mockUseGetBucketLifecycle.mockReturnValue({
437
+ data: {
438
+ Rules: [
439
+ rule
440
+ ]
441
+ },
442
+ status: 'success'
443
+ });
444
+ renderBucketLifecycleFormPage('test-bucket', 'prefix-rule');
445
+ await waitFor(()=>{
446
+ const prefixInput = screen.getByLabelText(/prefix/i);
447
+ expect(prefixInput).toHaveValue('documents/');
448
+ });
449
+ });
450
+ it('loads rule with single tag filter correctly', async ()=>{
451
+ const rule = {
452
+ ID: 'tag-rule',
453
+ Status: 'Enabled',
454
+ Filter: {
455
+ Tag: {
456
+ Key: 'env',
457
+ Value: 'prod'
458
+ }
459
+ },
460
+ Expiration: {
461
+ Days: 180
462
+ }
463
+ };
464
+ mockUseGetBucketLifecycle.mockReturnValue({
465
+ data: {
466
+ Rules: [
467
+ rule
468
+ ]
469
+ },
470
+ status: 'success'
471
+ });
472
+ renderBucketLifecycleFormPage('test-bucket', 'tag-rule');
473
+ await waitFor(()=>{
474
+ expect(screen.getByDisplayValue('env')).toBeInTheDocument();
475
+ expect(screen.getByDisplayValue('prod')).toBeInTheDocument();
476
+ });
477
+ });
478
+ it('loads rule with expiration days correctly', async ()=>{
479
+ const rule = {
480
+ ID: 'expiration-rule',
481
+ Status: 'Enabled',
482
+ Filter: {},
483
+ Expiration: {
484
+ Days: 365
485
+ }
486
+ };
487
+ mockUseGetBucketLifecycle.mockReturnValue({
488
+ data: {
489
+ Rules: [
490
+ rule
491
+ ]
492
+ },
493
+ status: 'success'
494
+ });
495
+ renderBucketLifecycleFormPage('test-bucket', 'expiration-rule');
496
+ await waitFor(()=>{
497
+ const expirationToggle = findToggleByLabel('Expiration current version');
498
+ expect(expirationToggle).toBeChecked();
499
+ const daysInput = screen.getByLabelText(/^days$/i);
500
+ expect(daysInput).toHaveValue(365);
501
+ });
502
+ });
503
+ it('loads rule with noncurrent version expiration correctly', async ()=>{
504
+ const rule = {
505
+ ID: 'noncurrent-rule',
506
+ Status: 'Enabled',
507
+ Filter: {},
508
+ NoncurrentVersionExpiration: {
509
+ NoncurrentDays: 90,
510
+ NewerNoncurrentVersions: 3
511
+ }
512
+ };
513
+ mockUseGetBucketLifecycle.mockReturnValue({
514
+ data: {
515
+ Rules: [
516
+ rule
517
+ ]
518
+ },
519
+ status: 'success'
520
+ });
521
+ renderBucketLifecycleFormPage('test-bucket', 'noncurrent-rule');
522
+ await waitFor(()=>{
523
+ const noncurrentExpirationToggle = findToggleByLabel('Expiration noncurrent version');
524
+ expect(noncurrentExpirationToggle).toBeChecked();
525
+ const noncurrentDaysInput = screen.getByLabelText(/noncurrent days/i);
526
+ expect(noncurrentDaysInput).toHaveValue(90);
527
+ const keepVersionsInput = screen.getByLabelText(/keep newer versions/i);
528
+ expect(keepVersionsInput).toHaveValue(3);
529
+ });
530
+ });
531
+ it('loads rule with abort incomplete multipart upload correctly', async ()=>{
532
+ const rule = {
533
+ ID: 'mpu-rule',
534
+ Status: 'Enabled',
535
+ Filter: {},
536
+ AbortIncompleteMultipartUpload: {
537
+ DaysAfterInitiation: 7
538
+ }
539
+ };
540
+ mockUseGetBucketLifecycle.mockReturnValue({
541
+ data: {
542
+ Rules: [
543
+ rule
544
+ ]
545
+ },
546
+ status: 'success'
547
+ });
548
+ renderBucketLifecycleFormPage('test-bucket', 'mpu-rule');
549
+ await waitFor(()=>{
550
+ const mpuToggle = findToggleByLabel('Expire incomplete multipart upload');
551
+ expect(mpuToggle).toBeChecked();
552
+ const mpuDaysInput = screen.getByLabelText(/days after initiation/i);
553
+ expect(mpuDaysInput).toHaveValue(7);
554
+ });
555
+ });
556
+ it('loads rule with transition correctly', async ()=>{
557
+ const rule = {
558
+ ID: 'transition-rule',
559
+ Status: 'Enabled',
560
+ Filter: {},
561
+ Transitions: [
562
+ {
563
+ Days: 30,
564
+ StorageClass: 'GLACIER'
565
+ }
566
+ ]
567
+ };
568
+ mockUseGetBucketLifecycle.mockReturnValue({
569
+ data: {
570
+ Rules: [
571
+ rule
572
+ ]
573
+ },
574
+ status: 'success'
575
+ });
576
+ renderBucketLifecycleFormPage('test-bucket', 'transition-rule');
577
+ await waitFor(()=>{
578
+ const transitionToggle = findToggleByLabel('Transition current version');
579
+ expect(transitionToggle).toBeChecked();
580
+ });
581
+ });
582
+ });
583
+ describe('Navigation', ()=>{
584
+ it('navigates back to bucket lifecycle tab when cancel is clicked', ()=>{
585
+ renderBucketLifecycleFormPage();
586
+ const cancelButton = screen.getByRole('button', {
587
+ name: /cancel/i
588
+ });
589
+ fireEvent.click(cancelButton);
590
+ expect(mockNavigate).toHaveBeenCalledWith('/buckets/test-bucket?tab=lifecycle');
591
+ });
592
+ it('disables cancel button when mutation is pending', ()=>{
593
+ mockUseSetBucketLifecycle.mockReturnValue({
594
+ mutate: mockMutate,
595
+ isPending: true
596
+ });
597
+ renderBucketLifecycleFormPage();
598
+ const cancelButton = screen.getByRole('button', {
599
+ name: /cancel/i
600
+ });
601
+ expect(cancelButton).toBeDisabled();
602
+ });
603
+ it('disables submit button when mutation is pending', async ()=>{
604
+ mockUseSetBucketLifecycle.mockReturnValue({
605
+ mutate: mockMutate,
606
+ isPending: true
607
+ });
608
+ renderBucketLifecycleFormPage();
609
+ await fillRequiredFields('test-rule');
610
+ await waitFor(()=>{
611
+ const createButton = screen.getByRole('button', {
612
+ name: /create/i
613
+ });
614
+ expect(createButton).toBeDisabled();
615
+ });
616
+ });
617
+ });
618
+ });