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

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 (256) hide show
  1. package/dist/components/Editor.d.ts +12 -0
  2. package/dist/components/Editor.js +28 -0
  3. package/dist/components/__tests__/BucketCreate.test.d.ts +1 -0
  4. package/dist/components/__tests__/BucketCreate.test.js +408 -0
  5. package/dist/components/__tests__/BucketLifecycleFormPage.test.d.ts +1 -0
  6. package/dist/components/__tests__/BucketLifecycleFormPage.test.js +618 -0
  7. package/dist/components/__tests__/BucketLifecycleList.test.d.ts +1 -0
  8. package/dist/components/__tests__/BucketLifecycleList.test.js +325 -0
  9. package/dist/components/__tests__/BucketList.test.d.ts +1 -0
  10. package/dist/components/__tests__/BucketList.test.js +415 -0
  11. package/dist/components/__tests__/BucketNotificationCreatePage.test.d.ts +1 -0
  12. package/dist/components/__tests__/BucketNotificationCreatePage.test.js +316 -0
  13. package/dist/components/__tests__/BucketOverview.test.d.ts +1 -0
  14. package/dist/components/__tests__/BucketOverview.test.js +769 -0
  15. package/dist/components/__tests__/BucketPolicyPage.test.d.ts +1 -0
  16. package/dist/components/__tests__/BucketPolicyPage.test.js +268 -0
  17. package/dist/components/__tests__/BucketReplicationFormPage.test.d.ts +1 -0
  18. package/dist/components/__tests__/BucketReplicationFormPage.test.js +1757 -0
  19. package/dist/components/__tests__/BucketReplicationList.test.d.ts +1 -0
  20. package/dist/components/__tests__/BucketReplicationList.test.js +344 -0
  21. package/dist/components/__tests__/CreateFolderButton.test.d.ts +1 -0
  22. package/dist/components/__tests__/CreateFolderButton.test.js +147 -0
  23. package/dist/components/__tests__/DeleteBucketButton.test.d.ts +1 -0
  24. package/dist/components/__tests__/DeleteBucketButton.test.js +272 -0
  25. package/dist/components/__tests__/DeleteBucketConfigRuleButton.test.d.ts +1 -0
  26. package/dist/components/__tests__/DeleteBucketConfigRuleButton.test.js +196 -0
  27. package/dist/components/__tests__/DeleteObjectButton.test.d.ts +1 -0
  28. package/dist/components/__tests__/DeleteObjectButton.test.js +302 -0
  29. package/dist/components/__tests__/EmptyBucketButton.test.d.ts +1 -0
  30. package/dist/components/__tests__/EmptyBucketButton.test.js +302 -0
  31. package/dist/components/__tests__/MetadataSearch.test.d.ts +1 -0
  32. package/dist/components/__tests__/MetadataSearch.test.js +201 -0
  33. package/dist/components/__tests__/ObjectList.test.d.ts +1 -0
  34. package/dist/components/__tests__/ObjectList.test.js +283 -0
  35. package/dist/components/__tests__/UploadButton.test.d.ts +1 -0
  36. package/dist/components/__tests__/UploadButton.test.js +144 -0
  37. package/dist/components/buckets/BucketCreate.d.ts +49 -0
  38. package/dist/components/buckets/BucketCreate.js +237 -0
  39. package/dist/components/buckets/BucketDetails.d.ts +1 -0
  40. package/dist/components/buckets/BucketDetails.js +106 -0
  41. package/dist/components/buckets/BucketLifecycleFormPage.d.ts +15 -0
  42. package/dist/components/buckets/BucketLifecycleFormPage.js +1085 -0
  43. package/dist/components/buckets/BucketLifecycleList.d.ts +10 -0
  44. package/dist/components/buckets/BucketLifecycleList.js +270 -0
  45. package/dist/components/buckets/BucketList.d.ts +15 -0
  46. package/dist/components/buckets/BucketList.js +146 -0
  47. package/dist/components/buckets/BucketLocation.d.ts +3 -0
  48. package/dist/components/buckets/BucketLocation.js +16 -0
  49. package/dist/components/buckets/BucketOverview.d.ts +88 -0
  50. package/dist/components/buckets/BucketOverview.js +291 -0
  51. package/dist/components/buckets/BucketPage.d.ts +2 -0
  52. package/dist/components/buckets/BucketPage.js +47 -0
  53. package/dist/components/buckets/BucketPolicyButton.d.ts +7 -0
  54. package/dist/components/buckets/BucketPolicyButton.js +18 -0
  55. package/dist/components/buckets/BucketPolicyPage.d.ts +1 -0
  56. package/dist/components/buckets/BucketPolicyPage.js +236 -0
  57. package/dist/components/buckets/BucketReplicationFormPage.d.ts +1 -0
  58. package/dist/components/buckets/BucketReplicationFormPage.js +834 -0
  59. package/dist/components/buckets/BucketReplicationList.d.ts +11 -0
  60. package/dist/components/buckets/BucketReplicationList.js +189 -0
  61. package/dist/components/buckets/BucketVersioning.d.ts +4 -0
  62. package/dist/components/buckets/BucketVersioning.js +73 -0
  63. package/dist/components/buckets/DeleteBucketButton.d.ts +8 -0
  64. package/dist/components/buckets/DeleteBucketButton.js +78 -0
  65. package/dist/components/buckets/DeleteBucketConfigRuleButton.d.ts +18 -0
  66. package/dist/components/buckets/DeleteBucketConfigRuleButton.js +53 -0
  67. package/dist/components/buckets/EmptyBucketButton.d.ts +5 -0
  68. package/dist/components/buckets/EmptyBucketButton.js +232 -0
  69. package/dist/components/buckets/EmptyBucketSummary.d.ts +9 -0
  70. package/dist/components/buckets/EmptyBucketSummary.js +60 -0
  71. package/dist/components/buckets/EmptyBucketSummaryList.d.ts +13 -0
  72. package/dist/components/buckets/EmptyBucketSummaryList.js +140 -0
  73. package/dist/components/buckets/__tests__/BucketVersioning.test.d.ts +1 -0
  74. package/dist/components/buckets/__tests__/BucketVersioning.test.js +163 -0
  75. package/dist/components/buckets/notifications/BucketNotificationCreatePage.d.ts +1 -0
  76. package/dist/components/buckets/notifications/BucketNotificationCreatePage.js +234 -0
  77. package/dist/components/buckets/notifications/EventsSection.d.ts +1 -0
  78. package/dist/components/buckets/notifications/EventsSection.js +123 -0
  79. package/dist/components/buckets/notifications/events.d.ts +12 -0
  80. package/dist/components/buckets/notifications/events.js +27 -0
  81. package/dist/components/index.d.ts +21 -0
  82. package/dist/components/index.js +22 -0
  83. package/dist/components/layouts/ArrowNavigation.d.ts +4 -0
  84. package/dist/components/layouts/ArrowNavigation.js +16 -0
  85. package/dist/components/layouts/BrowserPageLayout.d.ts +12 -0
  86. package/dist/components/layouts/BrowserPageLayout.js +51 -0
  87. package/dist/components/objects/CreateFolderButton.d.ts +29 -0
  88. package/dist/components/objects/CreateFolderButton.js +118 -0
  89. package/dist/components/objects/DeleteObjectButton.d.ts +8 -0
  90. package/dist/components/objects/DeleteObjectButton.js +191 -0
  91. package/dist/components/objects/ObjectDetails/ObjectMetadata.d.ts +2 -0
  92. package/dist/components/objects/ObjectDetails/ObjectMetadata.js +356 -0
  93. package/dist/components/objects/ObjectDetails/ObjectSummary.d.ts +3 -0
  94. package/dist/components/objects/ObjectDetails/ObjectSummary.js +241 -0
  95. package/dist/components/objects/ObjectDetails/ObjectTags.d.ts +3 -0
  96. package/dist/components/objects/ObjectDetails/ObjectTags.js +272 -0
  97. package/dist/components/objects/ObjectDetails/index.d.ts +9 -0
  98. package/dist/components/objects/ObjectDetails/index.js +75 -0
  99. package/dist/components/objects/ObjectList.d.ts +40 -0
  100. package/dist/components/objects/ObjectList.js +453 -0
  101. package/dist/components/objects/ObjectLock/EditRetentionButton.d.ts +4 -0
  102. package/dist/components/objects/ObjectLock/EditRetentionButton.js +32 -0
  103. package/dist/components/objects/ObjectLock/ObjectLockRetentionSettings.d.ts +3 -0
  104. package/dist/components/objects/ObjectLock/ObjectLockRetentionSettings.js +211 -0
  105. package/dist/components/objects/ObjectLock/ObjectLockSettings.d.ts +9 -0
  106. package/dist/components/objects/ObjectLock/ObjectLockSettings.js +158 -0
  107. package/dist/components/objects/ObjectLock/ObjectLockSettingsUtils.d.ts +8 -0
  108. package/dist/components/objects/ObjectLock/ObjectLockSettingsUtils.js +39 -0
  109. package/dist/components/objects/ObjectLock/__tests__/EditRetentionButton.test.d.ts +1 -0
  110. package/dist/components/objects/ObjectLock/__tests__/EditRetentionButton.test.js +204 -0
  111. package/dist/components/objects/ObjectLock/__tests__/ObjectLockSettings.test.d.ts +1 -0
  112. package/dist/components/objects/ObjectLock/__tests__/ObjectLockSettings.test.js +374 -0
  113. package/dist/components/objects/ObjectPage.d.ts +1 -0
  114. package/dist/components/objects/ObjectPage.js +45 -0
  115. package/dist/components/objects/UploadButton.d.ts +34 -0
  116. package/dist/components/objects/UploadButton.js +229 -0
  117. package/dist/components/providers/DataBrowserProvider.d.ts +20 -0
  118. package/dist/components/providers/DataBrowserProvider.js +42 -0
  119. package/dist/components/search/MetadataSearch.d.ts +5 -0
  120. package/dist/components/search/MetadataSearch.js +162 -0
  121. package/dist/components/search/SearchHints.d.ts +8 -0
  122. package/dist/components/search/SearchHints.js +21 -0
  123. package/dist/components/ui/ArrayFieldActions.d.ts +36 -0
  124. package/dist/components/ui/ArrayFieldActions.js +43 -0
  125. package/dist/components/ui/ConfirmDeleteRuleModal.d.ts +16 -0
  126. package/dist/components/ui/ConfirmDeleteRuleModal.js +43 -0
  127. package/dist/components/ui/DeleteObjectModalContent.d.ts +5 -0
  128. package/dist/components/ui/DeleteObjectModalContent.js +71 -0
  129. package/dist/components/ui/FilterFormSection.d.ts +44 -0
  130. package/dist/components/ui/FilterFormSection.js +159 -0
  131. package/dist/components/ui/Search.elements.d.ts +17 -0
  132. package/dist/components/ui/Search.elements.js +59 -0
  133. package/dist/components/ui/Table.elements.d.ts +36 -0
  134. package/dist/components/ui/Table.elements.js +87 -0
  135. package/dist/config/factory.d.ts +63 -0
  136. package/dist/config/factory.js +74 -0
  137. package/dist/config/types.d.ts +46 -0
  138. package/dist/config/types.js +0 -0
  139. package/dist/hooks/__tests__/useISVBucketDetection.test.d.ts +1 -0
  140. package/dist/hooks/__tests__/useISVBucketDetection.test.js +188 -0
  141. package/dist/hooks/__tests__/useIsBucketEmpty.test.d.ts +1 -0
  142. package/dist/hooks/__tests__/useIsBucketEmpty.test.js +122 -0
  143. package/dist/hooks/bucketConfiguration.d.ts +168 -0
  144. package/dist/hooks/bucketConfiguration.js +67 -0
  145. package/dist/hooks/bucketOperations.d.ts +36 -0
  146. package/dist/hooks/bucketOperations.js +12 -0
  147. package/dist/hooks/factories/__tests__/useCreateS3FunctionMutationHook.test.d.ts +1 -0
  148. package/dist/hooks/factories/__tests__/useCreateS3FunctionMutationHook.test.js +276 -0
  149. package/dist/hooks/factories/__tests__/useCreateS3InfiniteQueryHook.test.d.ts +1 -0
  150. package/dist/hooks/factories/__tests__/useCreateS3InfiniteQueryHook.test.js +259 -0
  151. package/dist/hooks/factories/__tests__/useCreateS3LoginHook.test.d.ts +1 -0
  152. package/dist/hooks/factories/__tests__/useCreateS3LoginHook.test.js +166 -0
  153. package/dist/hooks/factories/__tests__/useCreateS3MutationHook.test.d.ts +1 -0
  154. package/dist/hooks/factories/__tests__/useCreateS3MutationHook.test.js +200 -0
  155. package/dist/hooks/factories/__tests__/useCreateS3QueryHook.test.d.ts +1 -0
  156. package/dist/hooks/factories/__tests__/useCreateS3QueryHook.test.js +179 -0
  157. package/dist/hooks/factories/index.d.ts +18 -0
  158. package/dist/hooks/factories/index.js +5 -0
  159. package/dist/hooks/factories/useCreateS3InfiniteQueryHook.d.ts +13 -0
  160. package/dist/hooks/factories/useCreateS3InfiniteQueryHook.js +76 -0
  161. package/dist/hooks/factories/useCreateS3LoginHook.d.ts +8 -0
  162. package/dist/hooks/factories/useCreateS3LoginHook.js +22 -0
  163. package/dist/hooks/factories/useCreateS3MutationHook.d.ts +5 -0
  164. package/dist/hooks/factories/useCreateS3MutationHook.js +50 -0
  165. package/dist/hooks/factories/useCreateS3QueryHook.d.ts +3 -0
  166. package/dist/hooks/factories/useCreateS3QueryHook.js +51 -0
  167. package/dist/hooks/index.d.ts +13 -0
  168. package/dist/hooks/index.js +13 -0
  169. package/dist/hooks/loginOperations.d.ts +21 -0
  170. package/dist/hooks/loginOperations.js +9 -0
  171. package/dist/hooks/objectOperations.d.ts +190 -0
  172. package/dist/hooks/objectOperations.js +67 -0
  173. package/dist/hooks/presignedOperations.d.ts +73 -0
  174. package/dist/hooks/presignedOperations.js +72 -0
  175. package/dist/hooks/useBatchObjectLegalHold.d.ts +11 -0
  176. package/dist/hooks/useBatchObjectLegalHold.js +45 -0
  177. package/dist/hooks/useDeleteBucketConfigRule.d.ts +26 -0
  178. package/dist/hooks/useDeleteBucketConfigRule.js +46 -0
  179. package/dist/hooks/useEmptyBucket.d.ts +27 -0
  180. package/dist/hooks/useEmptyBucket.js +116 -0
  181. package/dist/hooks/useISVBucketDetection.d.ts +15 -0
  182. package/dist/hooks/useISVBucketDetection.js +27 -0
  183. package/dist/hooks/useIsBucketEmpty.d.ts +7 -0
  184. package/dist/hooks/useIsBucketEmpty.js +36 -0
  185. package/dist/hooks/useLoginMutation.d.ts +21 -0
  186. package/dist/hooks/useLoginMutation.js +9 -0
  187. package/dist/hooks/useS3Client.d.ts +1 -0
  188. package/dist/hooks/useS3Client.js +13 -0
  189. package/dist/hooks/useTableRowSelection.d.ts +9 -0
  190. package/dist/hooks/useTableRowSelection.js +45 -0
  191. package/dist/index.d.ts +6 -0
  192. package/dist/index.js +6 -0
  193. package/dist/schemas/bucketPolicySchema.json +321 -0
  194. package/dist/test/msw/handlers/deleteBucket.d.ts +1 -0
  195. package/dist/test/msw/handlers/deleteBucket.js +14 -0
  196. package/dist/test/msw/handlers/getBucketAcl.d.ts +1 -0
  197. package/dist/test/msw/handlers/getBucketAcl.js +96 -0
  198. package/dist/test/msw/handlers/getBucketLocation.d.ts +1 -0
  199. package/dist/test/msw/handlers/getBucketLocation.js +23 -0
  200. package/dist/test/msw/handlers/getBucketPolicy.d.ts +11 -0
  201. package/dist/test/msw/handlers/getBucketPolicy.js +72 -0
  202. package/dist/test/msw/handlers/headObject.d.ts +1 -0
  203. package/dist/test/msw/handlers/headObject.js +17 -0
  204. package/dist/test/msw/handlers/listBuckets.d.ts +1 -0
  205. package/dist/test/msw/handlers/listBuckets.js +24 -0
  206. package/dist/test/msw/handlers/listObjectVersions.d.ts +1 -0
  207. package/dist/test/msw/handlers/listObjectVersions.js +83 -0
  208. package/dist/test/msw/handlers/listObjects.d.ts +1 -0
  209. package/dist/test/msw/handlers/listObjects.js +66 -0
  210. package/dist/test/msw/handlers/objectLegalHold.d.ts +1 -0
  211. package/dist/test/msw/handlers/objectLegalHold.js +24 -0
  212. package/dist/test/msw/handlers/objectRetention.d.ts +1 -0
  213. package/dist/test/msw/handlers/objectRetention.js +27 -0
  214. package/dist/test/msw/handlers/putBucketAcl.d.ts +1 -0
  215. package/dist/test/msw/handlers/putBucketAcl.js +18 -0
  216. package/dist/test/msw/handlers/putObject.d.ts +1 -0
  217. package/dist/test/msw/handlers/putObject.js +16 -0
  218. package/dist/test/msw/handlers.d.ts +4 -0
  219. package/dist/test/msw/handlers.js +109 -0
  220. package/dist/test/msw/index.d.ts +2 -0
  221. package/dist/test/msw/index.js +3 -0
  222. package/dist/test/msw/server.d.ts +4 -0
  223. package/dist/test/msw/server.js +20 -0
  224. package/dist/test/msw/utils.d.ts +2 -0
  225. package/dist/test/msw/utils.js +13 -0
  226. package/dist/test/setup.d.ts +1 -0
  227. package/dist/test/setup.js +90 -0
  228. package/dist/test/testUtils.d.ts +181 -0
  229. package/dist/test/testUtils.js +310 -0
  230. package/dist/test/utils/errorHandling.test.d.ts +1 -0
  231. package/dist/test/utils/errorHandling.test.js +423 -0
  232. package/dist/types/index.d.ts +51 -0
  233. package/dist/types/index.js +0 -0
  234. package/dist/utils/constants.d.ts +12 -0
  235. package/dist/utils/constants.js +9 -0
  236. package/dist/utils/deletion/index.d.ts +2 -0
  237. package/dist/utils/deletion/index.js +2 -0
  238. package/dist/utils/deletion/messages.d.ts +5 -0
  239. package/dist/utils/deletion/messages.js +29 -0
  240. package/dist/utils/deletion/types.d.ts +11 -0
  241. package/dist/utils/deletion/types.js +0 -0
  242. package/dist/utils/errorHandling.d.ts +63 -0
  243. package/dist/utils/errorHandling.js +84 -0
  244. package/dist/utils/hooks.d.ts +2 -0
  245. package/dist/utils/hooks.js +26 -0
  246. package/dist/utils/index.d.ts +4 -0
  247. package/dist/utils/index.js +4 -0
  248. package/dist/utils/proxyMiddleware.d.ts +18 -0
  249. package/dist/utils/proxyMiddleware.js +56 -0
  250. package/dist/utils/s3Client.d.ts +5 -0
  251. package/dist/utils/s3Client.js +36 -0
  252. package/dist/utils/s3RuleUtils.d.ts +53 -0
  253. package/dist/utils/s3RuleUtils.js +101 -0
  254. package/dist/utils/useFeatures.d.ts +1 -0
  255. package/dist/utils/useFeatures.js +7 -0
  256. package/package.json +84 -0
@@ -0,0 +1,344 @@
1
+ import { jsx } from "react/jsx-runtime";
2
+ import { fireEvent, render, screen } from "@testing-library/react";
3
+ import { MemoryRouter } from "react-router";
4
+ import { createTestWrapper, mockOffsetSize } from "../../test/testUtils.js";
5
+ import { BucketReplicationList } from "../buckets/BucketReplicationList.js";
6
+ const renderBucketReplicationList = (props = {})=>{
7
+ const Wrapper = createTestWrapper();
8
+ return render(/*#__PURE__*/ jsx(MemoryRouter, {
9
+ children: /*#__PURE__*/ jsx(Wrapper, {
10
+ children: /*#__PURE__*/ jsx(BucketReplicationList, {
11
+ bucketName: "test-bucket",
12
+ replicationRules: [],
13
+ replicationRole: "arn:aws:iam::123456789012:role/replication-role",
14
+ ...props
15
+ })
16
+ })
17
+ }));
18
+ };
19
+ const mockReplicationRules = [
20
+ {
21
+ ID: "rule-1",
22
+ Status: "Enabled",
23
+ Priority: 1,
24
+ Destination: {
25
+ Bucket: "arn:aws:s3:::destination-bucket-1",
26
+ StorageClass: "STANDARD"
27
+ }
28
+ },
29
+ {
30
+ ID: "rule-2",
31
+ Status: "Disabled",
32
+ Priority: 2,
33
+ Destination: {
34
+ Bucket: "arn:aws:s3:::123456789012:backup-bucket",
35
+ StorageClass: "GLACIER",
36
+ Account: "123456789012"
37
+ }
38
+ },
39
+ {
40
+ ID: "rule-3",
41
+ Status: "Enabled",
42
+ Priority: 100,
43
+ Destination: {
44
+ Bucket: "arn:aws:s3:::logs-backup",
45
+ StorageClass: "ONEZONE_IA"
46
+ }
47
+ }
48
+ ];
49
+ const mockRuleWithoutPriority = {
50
+ ID: "no-priority-rule",
51
+ Status: "Enabled",
52
+ Destination: {
53
+ Bucket: "arn:aws:s3:::simple-backup"
54
+ }
55
+ };
56
+ const mockRuleWithoutStorageClass = {
57
+ ID: "no-storage-class-rule",
58
+ Status: "Enabled",
59
+ Priority: 5,
60
+ Destination: {
61
+ Bucket: "arn:aws:s3:::mirror-bucket"
62
+ }
63
+ };
64
+ describe("BucketReplicationList", ()=>{
65
+ beforeEach(()=>{
66
+ jest.clearAllMocks();
67
+ mockOffsetSize(800, 600);
68
+ });
69
+ it("shows a table with proper headers", ()=>{
70
+ renderBucketReplicationList({
71
+ replicationRules: mockReplicationRules
72
+ });
73
+ expect(screen.getByRole("grid")).toBeInTheDocument();
74
+ expect(screen.getByText("Rule ID")).toBeInTheDocument();
75
+ expect(screen.getByText("Status")).toBeInTheDocument();
76
+ expect(screen.getByText("Destination")).toBeInTheDocument();
77
+ expect(screen.getByText("Priority")).toBeInTheDocument();
78
+ });
79
+ it("displays replication rules with their IDs", ()=>{
80
+ renderBucketReplicationList({
81
+ replicationRules: mockReplicationRules
82
+ });
83
+ expect(screen.getByText("rule-1")).toBeInTheDocument();
84
+ expect(screen.getByText("rule-2")).toBeInTheDocument();
85
+ expect(screen.getByText("rule-3")).toBeInTheDocument();
86
+ });
87
+ it("displays status as Active for Enabled rules", ()=>{
88
+ renderBucketReplicationList({
89
+ replicationRules: mockReplicationRules
90
+ });
91
+ const activeStatuses = screen.getAllByText("Active");
92
+ expect(activeStatuses.length).toBe(2);
93
+ });
94
+ it("displays status as Inactive for Disabled rules", ()=>{
95
+ renderBucketReplicationList({
96
+ replicationRules: mockReplicationRules
97
+ });
98
+ expect(screen.getByText("Inactive")).toBeInTheDocument();
99
+ });
100
+ it("displays replication action with bucket name", ()=>{
101
+ renderBucketReplicationList({
102
+ replicationRules: mockReplicationRules
103
+ });
104
+ expect(screen.getByText(/Replicate to destination-bucket-1/)).toBeInTheDocument();
105
+ expect(screen.getByText(/Replicate to backup-bucket/)).toBeInTheDocument();
106
+ expect(screen.getByText(/Replicate to logs-backup/)).toBeInTheDocument();
107
+ });
108
+ it("displays storage class in actions column", ()=>{
109
+ renderBucketReplicationList({
110
+ replicationRules: mockReplicationRules
111
+ });
112
+ const actionTexts = screen.getAllByText(/Replicate to/);
113
+ expect(actionTexts.length).toBeGreaterThanOrEqual(3);
114
+ expect(screen.getByText(/STANDARD/, {
115
+ exact: false
116
+ })).toBeInTheDocument();
117
+ expect(screen.getByText(/GLACIER/, {
118
+ exact: false
119
+ })).toBeInTheDocument();
120
+ expect(screen.getByText(/ONEZONE_IA/, {
121
+ exact: false
122
+ })).toBeInTheDocument();
123
+ });
124
+ it("displays shortened account ID for cross-account replication", ()=>{
125
+ renderBucketReplicationList({
126
+ replicationRules: mockReplicationRules
127
+ });
128
+ expect(screen.getByText(/account: 123\.\.\.012/)).toBeInTheDocument();
129
+ });
130
+ it("displays priority values correctly", ()=>{
131
+ renderBucketReplicationList({
132
+ replicationRules: mockReplicationRules
133
+ });
134
+ expect(screen.getByText("1")).toBeInTheDocument();
135
+ expect(screen.getByText("2")).toBeInTheDocument();
136
+ expect(screen.getByText("100")).toBeInTheDocument();
137
+ });
138
+ it("displays 'None' for rules without priority", ()=>{
139
+ renderBucketReplicationList({
140
+ replicationRules: [
141
+ mockRuleWithoutPriority
142
+ ]
143
+ });
144
+ expect(screen.getByText("None")).toBeInTheDocument();
145
+ });
146
+ it("displays action without storage class when not provided", ()=>{
147
+ renderBucketReplicationList({
148
+ replicationRules: [
149
+ mockRuleWithoutStorageClass
150
+ ]
151
+ });
152
+ const actionText = screen.getByText(/Replicate to mirror-bucket/);
153
+ expect(actionText).toBeInTheDocument();
154
+ expect(actionText.textContent).toBe("Replicate to mirror-bucket");
155
+ });
156
+ it("renders create rule button as enabled", ()=>{
157
+ renderBucketReplicationList({
158
+ replicationRules: mockReplicationRules
159
+ });
160
+ const createButton = screen.getByRole("button", {
161
+ name: /create rule/i
162
+ });
163
+ expect(createButton).toBeInTheDocument();
164
+ expect(createButton).toBeEnabled();
165
+ });
166
+ it("calls create rule callback when button is clicked", ()=>{
167
+ const onCreateRule = jest.fn();
168
+ renderBucketReplicationList({
169
+ replicationRules: mockReplicationRules,
170
+ onCreateRule
171
+ });
172
+ const createButton = screen.getByRole("button", {
173
+ name: /create rule/i
174
+ });
175
+ expect(createButton).toBeEnabled();
176
+ fireEvent.click(createButton);
177
+ expect(onCreateRule).toHaveBeenCalled();
178
+ });
179
+ it("handles edit button click", ()=>{
180
+ const onEditRule = jest.fn();
181
+ renderBucketReplicationList({
182
+ replicationRules: mockReplicationRules,
183
+ onEditRule
184
+ });
185
+ const editButtons = screen.getAllByRole("button", {
186
+ name: /edit rule/i
187
+ });
188
+ expect(editButtons.length).toBeGreaterThanOrEqual(3);
189
+ fireEvent.click(editButtons[0]);
190
+ expect(onEditRule).toHaveBeenCalledWith(expect.any(String));
191
+ });
192
+ it("renders delete buttons for each rule", ()=>{
193
+ renderBucketReplicationList({
194
+ replicationRules: mockReplicationRules
195
+ });
196
+ const deleteButtons = screen.getAllByRole("button", {
197
+ name: /delete rule/i
198
+ });
199
+ expect(deleteButtons.length).toBeGreaterThanOrEqual(3);
200
+ });
201
+ it("handles empty replication rules list", ()=>{
202
+ renderBucketReplicationList({
203
+ replicationRules: []
204
+ });
205
+ expect(screen.getByRole("grid")).toBeInTheDocument();
206
+ expect(screen.getByText(/no replication rules found/i)).toBeInTheDocument();
207
+ });
208
+ it("handles replication rules without IDs", ()=>{
209
+ const ruleWithoutId = {
210
+ Status: "Enabled",
211
+ Priority: 1,
212
+ Destination: {
213
+ Bucket: "arn:aws:s3:::test-bucket"
214
+ }
215
+ };
216
+ renderBucketReplicationList({
217
+ replicationRules: [
218
+ ruleWithoutId
219
+ ]
220
+ });
221
+ expect(screen.getByText("-")).toBeInTheDocument();
222
+ });
223
+ it("shows loading state when replicationStatus is loading", ()=>{
224
+ renderBucketReplicationList({
225
+ replicationRules: [],
226
+ replicationStatus: "loading"
227
+ });
228
+ expect(screen.getByRole("grid")).toBeInTheDocument();
229
+ expect(screen.queryByText("rule-1")).not.toBeInTheDocument();
230
+ });
231
+ it("shows error state when replicationStatus is error", ()=>{
232
+ renderBucketReplicationList({
233
+ replicationRules: [],
234
+ replicationStatus: "error"
235
+ });
236
+ expect(screen.getByRole("grid")).toBeInTheDocument();
237
+ expect(screen.queryByText("rule-1")).not.toBeInTheDocument();
238
+ });
239
+ it("shows data when replicationStatus is success", ()=>{
240
+ renderBucketReplicationList({
241
+ replicationRules: mockReplicationRules,
242
+ replicationStatus: "success"
243
+ });
244
+ expect(screen.getByRole("grid")).toBeInTheDocument();
245
+ expect(screen.getByText("rule-1")).toBeInTheDocument();
246
+ expect(screen.getByText("rule-2")).toBeInTheDocument();
247
+ });
248
+ it("works when no callbacks are provided", ()=>{
249
+ expect(()=>{
250
+ renderBucketReplicationList({
251
+ replicationRules: mockReplicationRules
252
+ });
253
+ }).not.toThrow();
254
+ });
255
+ it("renders rows that can be selected", ()=>{
256
+ renderBucketReplicationList({
257
+ replicationRules: mockReplicationRules
258
+ });
259
+ const rows = screen.getAllByRole("row");
260
+ expect(rows.length).toBeGreaterThan(3);
261
+ const dataRows = rows.slice(1);
262
+ dataRows.forEach((row)=>{
263
+ expect(row).toHaveAttribute("aria-selected");
264
+ });
265
+ });
266
+ it("displays complex cross-account replication with all details", ()=>{
267
+ const complexRule = {
268
+ ID: "complex-rule",
269
+ Status: "Enabled",
270
+ Priority: 25,
271
+ Destination: {
272
+ Bucket: "arn:aws:s3:::999888777666555:shared-bucket",
273
+ Account: "999888777666555",
274
+ StorageClass: "GLACIER_IR"
275
+ }
276
+ };
277
+ renderBucketReplicationList({
278
+ replicationRules: [
279
+ complexRule
280
+ ]
281
+ });
282
+ expect(screen.getByText(/account: 999\.\.\.555/)).toBeInTheDocument();
283
+ expect(screen.getByText(/GLACIER_IR/)).toBeInTheDocument();
284
+ expect(screen.getByText(/Replicate to shared-bucket \(account: 999\.\.\.555, GLACIER_IR\)/)).toBeInTheDocument();
285
+ });
286
+ it("displays action text without account ID for same-account replication", ()=>{
287
+ renderBucketReplicationList({
288
+ replicationRules: [
289
+ mockReplicationRules[0]
290
+ ]
291
+ });
292
+ const actionText = screen.getByText(/Replicate to destination-bucket-1/);
293
+ expect(actionText.textContent).not.toContain("account:");
294
+ });
295
+ it("renders with custom bucket name and replication role", ()=>{
296
+ renderBucketReplicationList({
297
+ replicationRules: mockReplicationRules,
298
+ bucketName: "custom-bucket",
299
+ replicationRole: "arn:aws:iam::999888777666:role/custom-role"
300
+ });
301
+ expect(screen.getByText("rule-1")).toBeInTheDocument();
302
+ expect(screen.getByText("rule-2")).toBeInTheDocument();
303
+ expect(screen.getByText("rule-3")).toBeInTheDocument();
304
+ });
305
+ it("sorts rules by priority from low to high by default", ()=>{
306
+ const unsortedRules = [
307
+ {
308
+ ID: "high-priority-rule",
309
+ Status: "Enabled",
310
+ Priority: 100,
311
+ Destination: {
312
+ Bucket: "arn:aws:s3:::bucket-high"
313
+ }
314
+ },
315
+ {
316
+ ID: "low-priority-rule",
317
+ Status: "Enabled",
318
+ Priority: 1,
319
+ Destination: {
320
+ Bucket: "arn:aws:s3:::bucket-low"
321
+ }
322
+ },
323
+ {
324
+ ID: "mid-priority-rule",
325
+ Status: "Enabled",
326
+ Priority: 50,
327
+ Destination: {
328
+ Bucket: "arn:aws:s3:::bucket-mid"
329
+ }
330
+ }
331
+ ];
332
+ renderBucketReplicationList({
333
+ replicationRules: unsortedRules
334
+ });
335
+ const rows = screen.getAllByRole("row");
336
+ const dataRows = rows.slice(1);
337
+ expect(dataRows[0]).toHaveTextContent("low-priority-rule");
338
+ expect(dataRows[0]).toHaveTextContent("1");
339
+ expect(dataRows[1]).toHaveTextContent("mid-priority-rule");
340
+ expect(dataRows[1]).toHaveTextContent("50");
341
+ expect(dataRows[2]).toHaveTextContent("high-priority-rule");
342
+ expect(dataRows[2]).toHaveTextContent("100");
343
+ });
344
+ });
@@ -0,0 +1,147 @@
1
+ import { jsx } 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 { createTestWrapper } from "../../test/testUtils.js";
5
+ import { CreateFolderButton } from "../objects/CreateFolderButton.js";
6
+ describe("CreateFolderButton", ()=>{
7
+ const defaultProps = {
8
+ bucket: "test-bucket",
9
+ prefix: "test-prefix"
10
+ };
11
+ const renderCreateFolderButton = (props = {})=>{
12
+ const Wrapper = createTestWrapper();
13
+ return render(/*#__PURE__*/ jsx(Wrapper, {
14
+ children: /*#__PURE__*/ jsx(CreateFolderButton, {
15
+ ...defaultProps,
16
+ ...props
17
+ })
18
+ }));
19
+ };
20
+ it("renders button with default label", ()=>{
21
+ renderCreateFolderButton();
22
+ expect(screen.getByRole("button", {
23
+ name: /folder/i
24
+ })).toBeInTheDocument();
25
+ });
26
+ it("renders button with custom label", ()=>{
27
+ renderCreateFolderButton({
28
+ label: "Add New Folder"
29
+ });
30
+ expect(screen.getByRole("button", {
31
+ name: /add new folder/i
32
+ })).toBeInTheDocument();
33
+ });
34
+ it("opens modal when button is clicked", async ()=>{
35
+ renderCreateFolderButton();
36
+ fireEvent.click(screen.getByRole("button", {
37
+ name: /folder/i
38
+ }));
39
+ await waitFor(()=>{
40
+ expect(screen.getByText("Create a folder")).toBeInTheDocument();
41
+ });
42
+ });
43
+ it("closes modal when cancel button is clicked", async ()=>{
44
+ renderCreateFolderButton();
45
+ fireEvent.click(screen.getByRole("button", {
46
+ name: /folder/i
47
+ }));
48
+ await waitFor(()=>screen.getByText("Create a folder"));
49
+ fireEvent.click(screen.getByRole("button", {
50
+ name: /cancel/i
51
+ }));
52
+ await waitFor(()=>{
53
+ expect(screen.queryByText("Create a folder")).not.toBeInTheDocument();
54
+ });
55
+ });
56
+ it("disables save button when folder name is empty", async ()=>{
57
+ renderCreateFolderButton();
58
+ fireEvent.click(screen.getByRole("button", {
59
+ name: /folder/i
60
+ }));
61
+ await waitFor(()=>screen.getByText("Create a folder"));
62
+ expect(screen.getByRole("button", {
63
+ name: /save/i
64
+ })).toBeDisabled();
65
+ });
66
+ it("enables save button when valid folder name is entered", async ()=>{
67
+ renderCreateFolderButton();
68
+ fireEvent.click(screen.getByRole("button", {
69
+ name: /folder/i
70
+ }));
71
+ await waitFor(()=>screen.getByText("Create a folder"));
72
+ await user_event.type(screen.getByRole("textbox"), "valid-folder");
73
+ expect(screen.getByRole("button", {
74
+ name: /save/i
75
+ })).toBeEnabled();
76
+ });
77
+ it("disables save button and shows error when folder name starts with slash", async ()=>{
78
+ renderCreateFolderButton();
79
+ fireEvent.click(screen.getByRole("button", {
80
+ name: /folder/i
81
+ }));
82
+ await waitFor(()=>screen.getByText("Create a folder"));
83
+ await user_event.type(screen.getByRole("textbox"), "/invalid-folder");
84
+ expect(screen.getByRole("button", {
85
+ name: /save/i
86
+ })).toBeDisabled();
87
+ });
88
+ it("triggers mutation when save is clicked with valid folder name", async ()=>{
89
+ renderCreateFolderButton();
90
+ fireEvent.click(screen.getByRole("button", {
91
+ name: /folder/i
92
+ }));
93
+ await waitFor(()=>screen.getByText("Create a folder"));
94
+ await user_event.type(screen.getByRole("textbox"), "test-folder");
95
+ const saveButton = screen.getByRole("button", {
96
+ name: /save/i
97
+ });
98
+ expect(saveButton).toBeEnabled();
99
+ fireEvent.click(saveButton);
100
+ expect(screen.getByText("Create a folder")).toBeInTheDocument();
101
+ });
102
+ it("clears folder name when modal is closed", async ()=>{
103
+ renderCreateFolderButton();
104
+ fireEvent.click(screen.getByRole("button", {
105
+ name: /folder/i
106
+ }));
107
+ await waitFor(()=>screen.getByText("Create a folder"));
108
+ await user_event.type(screen.getByRole("textbox"), "test-folder");
109
+ fireEvent.click(screen.getByRole("button", {
110
+ name: /cancel/i
111
+ }));
112
+ await waitFor(()=>{
113
+ expect(screen.queryByText("Create a folder")).not.toBeInTheDocument();
114
+ });
115
+ fireEvent.click(screen.getByRole("button", {
116
+ name: /folder/i
117
+ }));
118
+ await waitFor(()=>screen.getByText("Create a folder"));
119
+ expect(screen.getByRole("textbox")).toHaveValue("");
120
+ });
121
+ it("shows info message about folder creation", async ()=>{
122
+ renderCreateFolderButton();
123
+ fireEvent.click(screen.getByRole("button", {
124
+ name: /folder/i
125
+ }));
126
+ await waitFor(()=>screen.getByText("Create a folder"));
127
+ expect(screen.getByText("Creating a folder")).toBeInTheDocument();
128
+ expect(screen.getByText(/ensure the folder name does not begin with a slash/i)).toBeInTheDocument();
129
+ });
130
+ it("handles folder name validation correctly", async ()=>{
131
+ renderCreateFolderButton();
132
+ fireEvent.click(screen.getByRole("button", {
133
+ name: /folder/i
134
+ }));
135
+ await waitFor(()=>screen.getByText("Create a folder"));
136
+ const input = screen.getByRole("textbox");
137
+ const saveButton = screen.getByRole("button", {
138
+ name: /save/i
139
+ });
140
+ expect(saveButton).toBeDisabled();
141
+ await user_event.type(input, "valid-folder");
142
+ expect(saveButton).toBeEnabled();
143
+ await user_event.clear(input);
144
+ await user_event.type(input, "/invalid");
145
+ expect(saveButton).toBeDisabled();
146
+ });
147
+ });