@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
@@ -3,10 +3,10 @@ import { fireEvent, render, screen, waitFor } from "@testing-library/react";
3
3
  import user_event from "@testing-library/user-event";
4
4
  import { createTestWrapper } from "../../test/testUtils.js";
5
5
  import { UploadButton } from "../objects/UploadButton.js";
6
- describe("UploadButton - Core Functionality", ()=>{
6
+ describe('UploadButton - Core Functionality', ()=>{
7
7
  const defaultProps = {
8
- bucket: "test-bucket",
9
- prefix: "test-prefix"
8
+ bucket: 'test-bucket',
9
+ prefix: 'test-prefix'
10
10
  };
11
11
  const renderUploadButton = (props = {})=>{
12
12
  const Wrapper = createTestWrapper();
@@ -17,128 +17,128 @@ describe("UploadButton - Core Functionality", ()=>{
17
17
  })
18
18
  }));
19
19
  };
20
- it("renders upload button with default label", ()=>{
20
+ it('renders upload button with default label', ()=>{
21
21
  renderUploadButton();
22
- expect(screen.getByRole("button", {
22
+ expect(screen.getByRole('button', {
23
23
  name: /upload/i
24
24
  })).toBeInTheDocument();
25
25
  });
26
- it("renders upload button", ()=>{
26
+ it('renders upload button', ()=>{
27
27
  renderUploadButton();
28
- expect(screen.getByRole("button", {
28
+ expect(screen.getByRole('button', {
29
29
  name: /upload/i
30
30
  })).toBeInTheDocument();
31
31
  });
32
- it("opens modal when upload button is clicked", async ()=>{
32
+ it('opens modal when upload button is clicked', async ()=>{
33
33
  renderUploadButton();
34
- const uploadButton = screen.getByRole("button", {
34
+ const uploadButton = screen.getByRole('button', {
35
35
  name: /upload/i
36
36
  });
37
37
  fireEvent.click(uploadButton);
38
38
  await waitFor(()=>{
39
- expect(screen.getByText("Upload Files")).toBeInTheDocument();
39
+ expect(screen.getByText('Upload Files')).toBeInTheDocument();
40
40
  });
41
41
  });
42
- it("closes modal when cancel button is clicked", async ()=>{
42
+ it('closes modal when cancel button is clicked', async ()=>{
43
43
  renderUploadButton();
44
- const uploadButton = screen.getByRole("button", {
44
+ const uploadButton = screen.getByRole('button', {
45
45
  name: /upload/i
46
46
  });
47
47
  fireEvent.click(uploadButton);
48
48
  await waitFor(()=>{
49
- expect(screen.getByText("Upload Files")).toBeInTheDocument();
49
+ expect(screen.getByText('Upload Files')).toBeInTheDocument();
50
50
  });
51
- const cancelButton = screen.getByRole("button", {
51
+ const cancelButton = screen.getByRole('button', {
52
52
  name: /cancel/i
53
53
  });
54
54
  fireEvent.click(cancelButton);
55
55
  await waitFor(()=>{
56
- expect(screen.queryByText("Upload Files")).not.toBeInTheDocument();
56
+ expect(screen.queryByText('Upload Files')).not.toBeInTheDocument();
57
57
  });
58
58
  });
59
- it("displays empty state initially", async ()=>{
59
+ it('displays empty state initially', async ()=>{
60
60
  renderUploadButton();
61
- const uploadButton = screen.getByRole("button", {
61
+ const uploadButton = screen.getByRole('button', {
62
62
  name: /upload/i
63
63
  });
64
64
  fireEvent.click(uploadButton);
65
65
  await waitFor(()=>{
66
- expect(screen.getByText("Drag and drop files and folders here")).toBeInTheDocument();
67
- expect(screen.getByRole("button", {
66
+ expect(screen.getByText('Drag and drop files and folders here')).toBeInTheDocument();
67
+ expect(screen.getByRole('button', {
68
68
  name: /add files/i
69
69
  })).toBeInTheDocument();
70
70
  });
71
71
  });
72
- it("can add files and shows upload button enabled", async ()=>{
72
+ it('can add files and shows upload button enabled', async ()=>{
73
73
  const onUploadSuccess = jest.fn();
74
74
  renderUploadButton({
75
75
  onUploadSuccess
76
76
  });
77
- const uploadButton = screen.getByRole("button", {
77
+ const uploadButton = screen.getByRole('button', {
78
78
  name: /upload/i
79
79
  });
80
80
  fireEvent.click(uploadButton);
81
81
  await waitFor(()=>{
82
- expect(screen.getByText("Upload Files")).toBeInTheDocument();
82
+ expect(screen.getByText('Upload Files')).toBeInTheDocument();
83
83
  });
84
- const uploadButtons = screen.getAllByRole("button", {
85
- name: "Upload"
84
+ const uploadButtons = screen.getAllByRole('button', {
85
+ name: 'Upload'
86
86
  });
87
- const modalUploadButton = uploadButtons.find((button)=>!button.querySelector("svg"));
87
+ const modalUploadButton = uploadButtons.find((button)=>!button.querySelector('svg'));
88
88
  expect(modalUploadButton).toBeDisabled();
89
- const fileInput = screen.getByRole("presentation").querySelector('input[type="file"]');
89
+ const fileInput = screen.getByRole('presentation').querySelector('input[type="file"]');
90
90
  const testFile = new File([
91
- "test content"
92
- ], "test.txt", {
93
- type: "text/plain"
91
+ 'test content'
92
+ ], 'test.txt', {
93
+ type: 'text/plain'
94
94
  });
95
95
  await user_event.upload(fileInput, testFile);
96
96
  await waitFor(()=>{
97
- expect(screen.getByText("test.txt")).toBeInTheDocument();
98
- expect(screen.getByText("12 B")).toBeInTheDocument();
97
+ expect(screen.getByText('test.txt')).toBeInTheDocument();
98
+ expect(screen.getByText('12 B')).toBeInTheDocument();
99
99
  });
100
100
  expect(modalUploadButton).toBeEnabled();
101
101
  });
102
- it("displays correct bucket and prefix information", ()=>{
103
- const customBucket = "custom-bucket";
104
- const customPrefix = "custom/prefix";
102
+ it('displays correct bucket and prefix information', ()=>{
103
+ const customBucket = 'custom-bucket';
104
+ const customPrefix = 'custom/prefix';
105
105
  renderUploadButton({
106
106
  bucket: customBucket,
107
107
  prefix: customPrefix
108
108
  });
109
- expect(screen.getByRole("button", {
109
+ expect(screen.getByRole('button', {
110
110
  name: /upload/i
111
111
  })).toBeInTheDocument();
112
112
  });
113
- it("handles different button variants", ()=>{
113
+ it('handles different button variants', ()=>{
114
114
  renderUploadButton({
115
- variant: "primary"
115
+ variant: 'primary'
116
116
  });
117
- const button = screen.getByRole("button", {
117
+ const button = screen.getByRole('button', {
118
118
  name: /upload/i
119
119
  });
120
120
  expect(button).toBeInTheDocument();
121
121
  });
122
- it("resets state when modal is closed", async ()=>{
122
+ it('resets state when modal is closed', async ()=>{
123
123
  renderUploadButton();
124
- const uploadButton = screen.getByRole("button", {
124
+ const uploadButton = screen.getByRole('button', {
125
125
  name: /upload/i
126
126
  });
127
127
  fireEvent.click(uploadButton);
128
128
  await waitFor(()=>{
129
- expect(screen.getByText("Upload Files")).toBeInTheDocument();
129
+ expect(screen.getByText('Upload Files')).toBeInTheDocument();
130
130
  });
131
- const cancelButton = screen.getByRole("button", {
131
+ const cancelButton = screen.getByRole('button', {
132
132
  name: /cancel/i
133
133
  });
134
134
  fireEvent.click(cancelButton);
135
135
  await waitFor(()=>{
136
- expect(screen.queryByText("Upload Files")).not.toBeInTheDocument();
136
+ expect(screen.queryByText('Upload Files')).not.toBeInTheDocument();
137
137
  });
138
138
  fireEvent.click(uploadButton);
139
139
  await waitFor(()=>{
140
- expect(screen.getByText("Upload Files")).toBeInTheDocument();
141
- expect(screen.getByText("Drag and drop files and folders here")).toBeInTheDocument();
140
+ expect(screen.getByText('Upload Files')).toBeInTheDocument();
141
+ expect(screen.getByText('Drag and drop files and folders here')).toBeInTheDocument();
142
142
  });
143
143
  });
144
144
  });
@@ -0,0 +1,6 @@
1
+ import type { BreadcrumbItem } from './index';
2
+ interface BreadcrumbProps {
3
+ items: BreadcrumbItem[];
4
+ }
5
+ export declare const Breadcrumb: React.FC<BreadcrumbProps>;
6
+ export {};
@@ -0,0 +1,37 @@
1
+ import { jsx } from "react/jsx-runtime";
2
+ import { Breadcrumb, ConstrainedText, spacing } from "@scality/core-ui";
3
+ import { Box } from "@scality/core-ui/dist/next";
4
+ import { Link } from "react-router";
5
+ import { useDataBrowserNavigate } from "../../hooks/useDataBrowserNavigate.js";
6
+ const Breadcrumb_Breadcrumb = ({ items })=>{
7
+ const navigate = useDataBrowserNavigate();
8
+ if (0 === items.length) return null;
9
+ const paths = items.map((item, index)=>{
10
+ const isLast = index === items.length - 1;
11
+ const isOnlyItem = 1 === items.length;
12
+ const key = `${item.label}-${index}`;
13
+ if (!item.path || isLast && !isOnlyItem) return /*#__PURE__*/ jsx(ConstrainedText, {
14
+ text: item.label
15
+ }, key);
16
+ const itemPath = item.path;
17
+ const targetPath = item.search ? `${itemPath}${item.search}` : itemPath;
18
+ const handleClick = (e)=>{
19
+ e.preventDefault();
20
+ navigate(targetPath);
21
+ };
22
+ return /*#__PURE__*/ jsx(Link, {
23
+ to: targetPath,
24
+ onClick: handleClick,
25
+ children: /*#__PURE__*/ jsx(ConstrainedText, {
26
+ text: item.label
27
+ })
28
+ }, key);
29
+ });
30
+ return /*#__PURE__*/ jsx(Box, {
31
+ padding: `0 ${spacing.r16}`,
32
+ children: /*#__PURE__*/ jsx(Breadcrumb, {
33
+ paths: paths
34
+ })
35
+ });
36
+ };
37
+ export { Breadcrumb_Breadcrumb as Breadcrumb };
@@ -0,0 +1 @@
1
+ export declare const DataBrowserBreadcrumb: () => import("react/jsx-runtime").JSX.Element | null;
@@ -0,0 +1,10 @@
1
+ import { jsx } from "react/jsx-runtime";
2
+ import { Breadcrumb } from "./Breadcrumb.js";
3
+ import { useBreadcrumbPaths } from "./useBreadcrumbPaths.js";
4
+ const DataBrowserBreadcrumb = ()=>{
5
+ const items = useBreadcrumbPaths();
6
+ return items.length ? /*#__PURE__*/ jsx(Breadcrumb, {
7
+ items: items
8
+ }) : null;
9
+ };
10
+ export { DataBrowserBreadcrumb };
@@ -0,0 +1,196 @@
1
+ import { jsx } from "react/jsx-runtime";
2
+ import { render, screen } from "@testing-library/react";
3
+ import user_event from "@testing-library/user-event";
4
+ import { MemoryRouter } from "react-router";
5
+ import { createTestWrapper } from "../../../test/testUtils.js";
6
+ import { Breadcrumb } from "../Breadcrumb.js";
7
+ const mockNavigate = jest.fn();
8
+ jest.mock('../../../hooks/useDataBrowserNavigate', ()=>({
9
+ useDataBrowserNavigate: ()=>mockNavigate
10
+ }));
11
+ describe('Breadcrumb Component', ()=>{
12
+ const Wrapper = createTestWrapper();
13
+ beforeEach(()=>{
14
+ mockNavigate.mockClear();
15
+ });
16
+ const renderBreadcrumb = (items)=>render(/*#__PURE__*/ jsx(MemoryRouter, {
17
+ children: /*#__PURE__*/ jsx(Wrapper, {
18
+ children: /*#__PURE__*/ jsx(Breadcrumb, {
19
+ items: items
20
+ })
21
+ })
22
+ }));
23
+ it('renders nothing when items array is empty', ()=>{
24
+ const { container } = renderBreadcrumb([]);
25
+ expect(container.firstChild).toBeNull();
26
+ });
27
+ it('renders a single breadcrumb item without link', ()=>{
28
+ renderBreadcrumb([
29
+ {
30
+ label: 'Home'
31
+ }
32
+ ]);
33
+ expect(screen.getByText('Home')).toBeInTheDocument();
34
+ expect(screen.queryByRole('link')).not.toBeInTheDocument();
35
+ });
36
+ it('renders multiple items with correct link structure', ()=>{
37
+ renderBreadcrumb([
38
+ {
39
+ label: 'Home',
40
+ path: '/home'
41
+ },
42
+ {
43
+ label: 'Products',
44
+ path: '/products'
45
+ },
46
+ {
47
+ label: 'Item'
48
+ }
49
+ ]);
50
+ expect(screen.getByRole('link', {
51
+ name: /home/i
52
+ })).toHaveAttribute('href', '/home');
53
+ expect(screen.getByRole('link', {
54
+ name: /products/i
55
+ })).toHaveAttribute('href', '/products');
56
+ expect(screen.queryByRole('link', {
57
+ name: /^item$/i
58
+ })).not.toBeInTheDocument();
59
+ expect(screen.getByText('Item')).toBeInTheDocument();
60
+ });
61
+ it('last item is never a link even if it has a path', ()=>{
62
+ renderBreadcrumb([
63
+ {
64
+ label: 'Home',
65
+ path: '/home'
66
+ },
67
+ {
68
+ label: 'Current',
69
+ path: '/current'
70
+ }
71
+ ]);
72
+ expect(screen.getByRole('link', {
73
+ name: /home/i
74
+ })).toBeInTheDocument();
75
+ expect(screen.queryByRole('link', {
76
+ name: /current/i
77
+ })).not.toBeInTheDocument();
78
+ expect(screen.getByText('Current')).toBeInTheDocument();
79
+ });
80
+ it('handles items with search parameters', ()=>{
81
+ renderBreadcrumb([
82
+ {
83
+ label: 'Home',
84
+ path: '/home'
85
+ },
86
+ {
87
+ label: 'Folder',
88
+ path: '/folder',
89
+ search: '?prefix=test/'
90
+ },
91
+ {
92
+ label: 'Current'
93
+ }
94
+ ]);
95
+ expect(screen.getByRole('link', {
96
+ name: /folder/i
97
+ })).toHaveAttribute('href', '/folder?prefix=test/');
98
+ });
99
+ it('calls navigate with correct path on link click', async ()=>{
100
+ const user = user_event.setup();
101
+ renderBreadcrumb([
102
+ {
103
+ label: 'Home',
104
+ path: '/home'
105
+ },
106
+ {
107
+ label: 'Current'
108
+ }
109
+ ]);
110
+ await user.click(screen.getByRole('link', {
111
+ name: /home/i
112
+ }));
113
+ expect(mockNavigate).toHaveBeenCalledWith('/home');
114
+ });
115
+ it('calls navigate with path and search params on link click', async ()=>{
116
+ const user = user_event.setup();
117
+ renderBreadcrumb([
118
+ {
119
+ label: 'Home',
120
+ path: '/home'
121
+ },
122
+ {
123
+ label: 'Folder',
124
+ path: '/folder',
125
+ search: '?prefix=test/'
126
+ },
127
+ {
128
+ label: 'Current'
129
+ }
130
+ ]);
131
+ await user.click(screen.getByRole('link', {
132
+ name: /folder/i
133
+ }));
134
+ expect(mockNavigate).toHaveBeenCalledWith('/folder?prefix=test/');
135
+ });
136
+ it('prevents default navigation behavior on link click', async ()=>{
137
+ const user = user_event.setup();
138
+ renderBreadcrumb([
139
+ {
140
+ label: 'Home',
141
+ path: '/home'
142
+ },
143
+ {
144
+ label: 'Current'
145
+ }
146
+ ]);
147
+ const link = screen.getByRole('link', {
148
+ name: /home/i
149
+ });
150
+ await user.click(link);
151
+ expect(mockNavigate).toHaveBeenCalled();
152
+ });
153
+ it('renders long labels with ConstrainedText', ()=>{
154
+ const longLabel = 'This is a very long breadcrumb label that should be constrained';
155
+ renderBreadcrumb([
156
+ {
157
+ label: longLabel
158
+ }
159
+ ]);
160
+ expect(screen.getByText(longLabel)).toBeInTheDocument();
161
+ });
162
+ it('handles special characters in labels', ()=>{
163
+ renderBreadcrumb([
164
+ {
165
+ label: 'Bucket & Folder',
166
+ path: '/bucket'
167
+ },
168
+ {
169
+ label: 'File (1).txt'
170
+ }
171
+ ]);
172
+ expect(screen.getByText('Bucket & Folder')).toBeInTheDocument();
173
+ expect(screen.getByText('File (1).txt')).toBeInTheDocument();
174
+ });
175
+ it('renders correct number of breadcrumb items', ()=>{
176
+ renderBreadcrumb([
177
+ {
178
+ label: 'Level 1',
179
+ path: '/1'
180
+ },
181
+ {
182
+ label: 'Level 2',
183
+ path: '/2'
184
+ },
185
+ {
186
+ label: 'Level 3',
187
+ path: '/3'
188
+ },
189
+ {
190
+ label: 'Current'
191
+ }
192
+ ]);
193
+ expect(screen.getAllByRole('link')).toHaveLength(3);
194
+ expect(screen.getByText('Current')).toBeInTheDocument();
195
+ });
196
+ });
@@ -0,0 +1,153 @@
1
+ import { jsx } from "react/jsx-runtime";
2
+ import { render, screen } from "@testing-library/react";
3
+ import { MemoryRouter } from "react-router";
4
+ import { createTestWrapper } from "../../../test/testUtils.js";
5
+ import { DataBrowserBreadcrumb } from "../DataBrowserBreadcrumb.js";
6
+ describe('DataBrowserBreadcrumb - User Experience', ()=>{
7
+ const renderBreadcrumb = (path)=>{
8
+ const Wrapper = createTestWrapper();
9
+ return render(/*#__PURE__*/ jsx(MemoryRouter, {
10
+ initialEntries: [
11
+ path
12
+ ],
13
+ children: /*#__PURE__*/ jsx(Wrapper, {
14
+ children: /*#__PURE__*/ jsx(DataBrowserBreadcrumb, {})
15
+ })
16
+ }));
17
+ };
18
+ it('shows breadcrumb only on BucketPage and ObjectsPage', ()=>{
19
+ const bucketList = renderBreadcrumb('/buckets');
20
+ expect(bucketList.container.firstChild).not.toBeNull();
21
+ const bucketDetail = renderBreadcrumb('/buckets/my-bucket');
22
+ expect(bucketDetail.container.firstChild).not.toBeNull();
23
+ const objectsPage = renderBreadcrumb('/buckets/my-bucket/objects');
24
+ expect(objectsPage.container.firstChild).not.toBeNull();
25
+ const createPage = renderBreadcrumb('/buckets/-/create');
26
+ expect(createPage.container.firstChild).toBeNull();
27
+ const settingsPage = renderBreadcrumb('/buckets/my-bucket/policy');
28
+ expect(settingsPage.container.firstChild).toBeNull();
29
+ });
30
+ it.each([
31
+ '/buckets/-/create',
32
+ '/buckets/-/access',
33
+ '/buckets/my-bucket/policy',
34
+ '/buckets/my-bucket/cors',
35
+ '/buckets/my-bucket/lifecycle/create',
36
+ '/buckets/my-bucket/lifecycle/edit/rule-123',
37
+ '/buckets/my-bucket/replication/create',
38
+ '/buckets/my-bucket/replication/edit/rule-456',
39
+ '/buckets/my-bucket/notifications/create',
40
+ '/buckets/my-bucket/notifications/edit/notif-789',
41
+ '/buckets/my-bucket/objects/object-lock-settings',
42
+ '/buckets/my-bucket/unknown-setting'
43
+ ])('does not show breadcrumb on %s', (path)=>{
44
+ const { container } = renderBreadcrumb(path);
45
+ expect(container.firstChild).toBeNull();
46
+ });
47
+ it('shows endpoint URL as clickable link on bucket list page', ()=>{
48
+ renderBreadcrumb('/buckets');
49
+ const link = screen.getByRole('link', {
50
+ name: /s3\.amazonaws\.com/i
51
+ });
52
+ expect(link).toBeInTheDocument();
53
+ expect(link).toHaveAttribute('href', '/buckets');
54
+ });
55
+ it('shows endpoint URL as clickable link on bucket detail page', ()=>{
56
+ renderBreadcrumb('/buckets/my-bucket');
57
+ const link = screen.getByRole('link', {
58
+ name: /s3\.amazonaws\.com/i
59
+ });
60
+ expect(link).toBeInTheDocument();
61
+ expect(link).toHaveAttribute('href', '/buckets');
62
+ });
63
+ it('shows endpoint and bucket name when viewing root objects', ()=>{
64
+ renderBreadcrumb('/buckets/my-bucket/objects');
65
+ expect(screen.getByText(/s3\.amazonaws\.com/i)).toBeInTheDocument();
66
+ expect(screen.getByText('my-bucket')).toBeInTheDocument();
67
+ });
68
+ it('shows folder navigation path when in a folder', ()=>{
69
+ renderBreadcrumb('/buckets/my-bucket/objects?prefix=folder1/');
70
+ expect(screen.getByText(/s3\.amazonaws\.com/i)).toBeInTheDocument();
71
+ expect(screen.getByText('my-bucket')).toBeInTheDocument();
72
+ expect(screen.getByText('folder1')).toBeInTheDocument();
73
+ });
74
+ it('shows nested folder path', ()=>{
75
+ renderBreadcrumb('/buckets/my-bucket/objects?prefix=folder1/folder2/');
76
+ expect(screen.getByText(/s3\.amazonaws\.com/i)).toBeInTheDocument();
77
+ expect(screen.getByText('my-bucket')).toBeInTheDocument();
78
+ expect(screen.getByText('folder1')).toBeInTheDocument();
79
+ expect(screen.getByText('folder2')).toBeInTheDocument();
80
+ });
81
+ it('shows file name when viewing a file', ()=>{
82
+ renderBreadcrumb('/buckets/my-bucket/objects?prefix=folder/file.txt');
83
+ expect(screen.getByText(/s3\.amazonaws\.com/i)).toBeInTheDocument();
84
+ expect(screen.getByText('my-bucket')).toBeInTheDocument();
85
+ expect(screen.getByText('folder')).toBeInTheDocument();
86
+ expect(screen.getByText('file.txt')).toBeInTheDocument();
87
+ });
88
+ it('endpoint URL is always clickable when viewing objects', ()=>{
89
+ renderBreadcrumb('/buckets/my-bucket/objects');
90
+ const link = screen.getByRole('link', {
91
+ name: /s3\.amazonaws\.com/i
92
+ });
93
+ expect(link).toBeInTheDocument();
94
+ expect(link).toHaveAttribute('href', '/buckets');
95
+ });
96
+ it('bucket name becomes clickable when in a folder', ()=>{
97
+ renderBreadcrumb('/buckets/my-bucket/objects?prefix=folder1/');
98
+ const link = screen.getByRole('link', {
99
+ name: /my-bucket/i
100
+ });
101
+ expect(link).toBeInTheDocument();
102
+ expect(link).toHaveAttribute('href', '/buckets/my-bucket/objects');
103
+ });
104
+ it('bucket name is not clickable on root objects page', ()=>{
105
+ renderBreadcrumb('/buckets/my-bucket/objects');
106
+ expect(screen.queryByRole('link', {
107
+ name: /^my-bucket$/i
108
+ })).not.toBeInTheDocument();
109
+ expect(screen.getByText('my-bucket')).toBeInTheDocument();
110
+ });
111
+ it('last item in breadcrumb is never clickable', ()=>{
112
+ renderBreadcrumb('/buckets/my-bucket/objects?prefix=folder1/folder2/');
113
+ expect(screen.queryByRole('link', {
114
+ name: /^folder2$/i
115
+ })).not.toBeInTheDocument();
116
+ expect(screen.getByText('folder2')).toBeInTheDocument();
117
+ });
118
+ it('file name is not clickable when viewing a file', ()=>{
119
+ renderBreadcrumb('/buckets/my-bucket/objects?prefix=folder/file.txt');
120
+ expect(screen.queryByRole('link', {
121
+ name: /file\.txt/i
122
+ })).not.toBeInTheDocument();
123
+ expect(screen.getByText('file.txt')).toBeInTheDocument();
124
+ });
125
+ it('parent folder is clickable when viewing a file', ()=>{
126
+ renderBreadcrumb('/buckets/my-bucket/objects?prefix=folder/file.txt');
127
+ const link = screen.getByRole('link', {
128
+ name: /folder/i
129
+ });
130
+ expect(link).toBeInTheDocument();
131
+ expect(link).toHaveAttribute('href', '/buckets/my-bucket/objects?prefix=folder%2F');
132
+ });
133
+ it('handles bucket names with special characters', ()=>{
134
+ renderBreadcrumb('/buckets/my-bucket-123/objects');
135
+ expect(screen.getByText(/s3\.amazonaws\.com/i)).toBeInTheDocument();
136
+ expect(screen.getByText('my-bucket-123')).toBeInTheDocument();
137
+ });
138
+ it('handles folder names with special characters', ()=>{
139
+ renderBreadcrumb('/buckets/my-bucket/objects?prefix=folder%20with%20spaces/');
140
+ expect(screen.getByText(/s3\.amazonaws\.com/i)).toBeInTheDocument();
141
+ expect(screen.getByText('my-bucket')).toBeInTheDocument();
142
+ expect(screen.getByText('folder with spaces')).toBeInTheDocument();
143
+ });
144
+ it('handles deeply nested folder structure', ()=>{
145
+ renderBreadcrumb('/buckets/my-bucket/objects?prefix=level1/level2/level3/level4/');
146
+ expect(screen.getByText(/s3\.amazonaws\.com/i)).toBeInTheDocument();
147
+ expect(screen.getByText('my-bucket')).toBeInTheDocument();
148
+ expect(screen.getByText('level1')).toBeInTheDocument();
149
+ expect(screen.getByText('level2')).toBeInTheDocument();
150
+ expect(screen.getByText('level3')).toBeInTheDocument();
151
+ expect(screen.getByText('level4')).toBeInTheDocument();
152
+ });
153
+ });