@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.
- package/dist/components/DataBrowserUI.d.ts +12 -0
- package/dist/components/DataBrowserUI.js +99 -0
- package/dist/components/Editor.d.ts +1 -1
- package/dist/components/Editor.js +3 -3
- package/dist/components/__tests__/BucketAccessor.test.js +214 -0
- package/dist/components/__tests__/BucketCorsPage.test.d.ts +1 -0
- package/dist/components/__tests__/BucketCorsPage.test.js +263 -0
- package/dist/components/__tests__/BucketCreate.test.d.ts +1 -0
- package/dist/components/__tests__/BucketCreate.test.js +574 -0
- package/dist/components/__tests__/BucketDetails.test.d.ts +1 -0
- package/dist/components/__tests__/BucketDetails.test.js +421 -0
- package/dist/components/__tests__/BucketLifecycleFormPage.test.d.ts +14 -0
- package/dist/components/__tests__/BucketLifecycleFormPage.test.js +618 -0
- package/dist/components/__tests__/BucketLifecycleList.test.d.ts +1 -0
- package/dist/components/__tests__/BucketLifecycleList.test.js +325 -0
- package/dist/components/__tests__/BucketList.test.js +495 -81
- package/dist/components/__tests__/BucketNotificationFormPage.test.d.ts +1 -0
- package/dist/components/__tests__/BucketNotificationFormPage.test.js +348 -0
- package/dist/components/__tests__/BucketNotificationList.test.d.ts +1 -0
- package/dist/components/__tests__/BucketNotificationList.test.js +379 -0
- package/dist/components/__tests__/BucketOverview.test.js +484 -179
- package/dist/components/__tests__/BucketPolicyPage.test.js +151 -99
- package/dist/components/__tests__/BucketReplicationFormPage.test.d.ts +16 -0
- package/dist/components/__tests__/BucketReplicationFormPage.test.js +1757 -0
- package/dist/components/__tests__/BucketReplicationList.test.d.ts +1 -0
- package/dist/components/__tests__/BucketReplicationList.test.js +344 -0
- package/dist/components/__tests__/CreateFolderButton.test.js +56 -56
- package/dist/components/__tests__/DeleteBucketButton.test.js +64 -64
- package/dist/components/__tests__/DeleteBucketConfigRuleButton.test.d.ts +1 -0
- package/dist/components/__tests__/DeleteBucketConfigRuleButton.test.js +196 -0
- package/dist/components/__tests__/DeleteObjectButton.test.js +64 -64
- package/dist/components/__tests__/EmptyBucketButton.test.d.ts +1 -0
- package/dist/components/__tests__/EmptyBucketButton.test.js +302 -0
- package/dist/components/__tests__/MetadataSearch.test.js +65 -65
- package/dist/components/__tests__/ObjectList.test.js +741 -240
- package/dist/components/__tests__/UploadButton.test.js +45 -45
- package/dist/components/breadcrumb/Breadcrumb.d.ts +6 -0
- package/dist/components/breadcrumb/Breadcrumb.js +37 -0
- package/dist/components/breadcrumb/DataBrowserBreadcrumb.d.ts +1 -0
- package/dist/components/breadcrumb/DataBrowserBreadcrumb.js +10 -0
- package/dist/components/breadcrumb/__tests__/Breadcrumb.test.d.ts +1 -0
- package/dist/components/breadcrumb/__tests__/Breadcrumb.test.js +196 -0
- package/dist/components/breadcrumb/__tests__/DataBrowserBreadcrumb.test.d.ts +1 -0
- package/dist/components/breadcrumb/__tests__/DataBrowserBreadcrumb.test.js +153 -0
- package/dist/components/breadcrumb/__tests__/useBreadcrumbPaths.test.d.ts +1 -0
- package/dist/components/breadcrumb/__tests__/useBreadcrumbPaths.test.js +134 -0
- package/dist/components/breadcrumb/index.d.ts +8 -0
- package/dist/components/breadcrumb/index.js +4 -0
- package/dist/components/breadcrumb/useBreadcrumbPaths.d.ts +2 -0
- package/dist/components/breadcrumb/useBreadcrumbPaths.js +82 -0
- package/dist/components/buckets/BucketAccessor.d.ts +2 -0
- package/dist/components/buckets/BucketAccessor.js +125 -0
- package/dist/components/buckets/BucketConfigEditButton.d.ts +8 -0
- package/dist/components/buckets/{BucketPolicyButton.js → BucketConfigEditButton.js} +9 -5
- package/dist/components/buckets/BucketCorsPage.d.ts +1 -0
- package/dist/components/buckets/BucketCorsPage.js +234 -0
- package/dist/components/buckets/BucketCreate.d.ts +50 -0
- package/dist/components/buckets/BucketCreate.js +279 -0
- package/dist/components/buckets/BucketDetails.d.ts +42 -0
- package/dist/components/buckets/BucketDetails.js +256 -40
- package/dist/components/buckets/BucketLifecycleFormPage.d.ts +15 -0
- package/dist/components/buckets/BucketLifecycleFormPage.js +1086 -0
- package/dist/components/buckets/BucketLifecycleList.d.ts +10 -0
- package/dist/components/buckets/BucketLifecycleList.js +270 -0
- package/dist/components/buckets/BucketList.d.ts +6 -4
- package/dist/components/buckets/BucketList.js +161 -94
- package/dist/components/buckets/BucketLocation.js +4 -4
- package/dist/components/buckets/BucketOverview.d.ts +86 -5
- package/dist/components/buckets/BucketOverview.js +481 -192
- package/dist/components/buckets/BucketPage.js +44 -22
- package/dist/components/buckets/BucketPolicyPage.js +155 -127
- package/dist/components/buckets/BucketReplicationFormPage.d.ts +1 -0
- package/dist/components/buckets/BucketReplicationFormPage.js +835 -0
- package/dist/components/buckets/BucketReplicationList.d.ts +11 -0
- package/dist/components/buckets/BucketReplicationList.js +189 -0
- package/dist/components/buckets/BucketVersioning.d.ts +4 -0
- package/dist/components/buckets/BucketVersioning.js +76 -0
- package/dist/components/buckets/DeleteBucketButton.js +8 -8
- package/dist/components/buckets/DeleteBucketConfigRuleButton.d.ts +18 -0
- package/dist/components/buckets/DeleteBucketConfigRuleButton.js +53 -0
- package/dist/components/buckets/EmptyBucketButton.d.ts +5 -0
- package/dist/components/buckets/EmptyBucketButton.js +232 -0
- package/dist/components/buckets/EmptyBucketSummary.d.ts +9 -0
- package/dist/components/buckets/EmptyBucketSummary.js +60 -0
- package/dist/components/buckets/EmptyBucketSummaryList.d.ts +13 -0
- package/dist/components/buckets/EmptyBucketSummaryList.js +140 -0
- package/dist/components/buckets/__tests__/BucketVersioning.test.d.ts +1 -0
- package/dist/components/buckets/__tests__/BucketVersioning.test.js +163 -0
- package/dist/components/buckets/notifications/BucketNotificationFormPage.d.ts +1 -0
- package/dist/components/buckets/notifications/BucketNotificationFormPage.js +316 -0
- package/dist/components/buckets/notifications/BucketNotificationList.d.ts +10 -0
- package/dist/components/buckets/notifications/BucketNotificationList.js +267 -0
- package/dist/components/buckets/notifications/EventsSection.js +145 -29
- package/dist/components/buckets/notifications/__tests__/events.test.d.ts +1 -0
- package/dist/components/buckets/notifications/__tests__/events.test.js +56 -0
- package/dist/components/buckets/notifications/events.d.ts +71 -7
- package/dist/components/buckets/notifications/events.js +98 -16
- package/dist/components/index.d.ts +27 -13
- package/dist/components/index.js +20 -6
- package/dist/components/layouts/ArrowNavigation.d.ts +3 -0
- package/dist/components/layouts/ArrowNavigation.js +28 -0
- package/dist/components/layouts/BrowserPageLayout.d.ts +5 -1
- package/dist/components/layouts/BrowserPageLayout.js +10 -5
- package/dist/components/objects/CreateFolderButton.d.ts +2 -2
- package/dist/components/objects/CreateFolderButton.js +12 -12
- package/dist/components/objects/DeleteObjectButton.d.ts +1 -1
- package/dist/components/objects/DeleteObjectButton.js +19 -21
- package/dist/components/objects/GetPresignedUrlButton.d.ts +7 -0
- package/dist/components/objects/GetPresignedUrlButton.js +255 -0
- package/dist/components/objects/ObjectDetails/ObjectMetadata.d.ts +2 -2
- package/dist/components/objects/ObjectDetails/ObjectMetadata.js +263 -230
- package/dist/components/objects/ObjectDetails/ObjectSummary.d.ts +2 -2
- package/dist/components/objects/ObjectDetails/ObjectSummary.js +540 -138
- package/dist/components/objects/ObjectDetails/ObjectTags.d.ts +2 -2
- package/dist/components/objects/ObjectDetails/ObjectTags.js +95 -123
- package/dist/components/objects/ObjectDetails/__tests__/ObjectDetails.test.d.ts +1 -0
- package/dist/components/objects/ObjectDetails/__tests__/ObjectDetails.test.js +516 -0
- package/dist/components/objects/ObjectDetails/__tests__/ObjectSummary.test.d.ts +1 -0
- package/dist/components/objects/ObjectDetails/__tests__/ObjectSummary.test.js +1064 -0
- package/dist/components/objects/ObjectDetails/index.d.ts +18 -2
- package/dist/components/objects/ObjectDetails/index.js +152 -40
- package/dist/components/objects/ObjectList.d.ts +12 -10
- package/dist/components/objects/ObjectList.js +590 -263
- package/dist/components/objects/ObjectLock/EditRetentionButton.d.ts +4 -0
- package/dist/components/objects/ObjectLock/EditRetentionButton.js +32 -0
- package/dist/components/objects/ObjectLock/ObjectLockRetentionSettings.d.ts +3 -0
- package/dist/components/objects/ObjectLock/ObjectLockRetentionSettings.js +211 -0
- package/dist/components/objects/ObjectLock/ObjectLockSettings.d.ts +9 -0
- package/dist/components/objects/ObjectLock/ObjectLockSettings.js +159 -0
- package/dist/components/objects/ObjectLock/ObjectLockSettingsUtils.d.ts +8 -0
- package/dist/components/objects/ObjectLock/ObjectLockSettingsUtils.js +39 -0
- package/dist/components/objects/ObjectLock/__tests__/EditRetentionButton.test.d.ts +1 -0
- package/dist/components/objects/ObjectLock/__tests__/EditRetentionButton.test.js +204 -0
- package/dist/components/objects/ObjectLock/__tests__/ObjectLockSettings.test.d.ts +1 -0
- package/dist/components/objects/ObjectLock/__tests__/ObjectLockSettings.test.js +374 -0
- package/dist/components/objects/ObjectPage.js +12 -8
- package/dist/components/objects/UploadButton.d.ts +3 -3
- package/dist/components/objects/UploadButton.js +10 -10
- package/dist/components/objects/__tests__/GetPresignedUrlButton.test.d.ts +1 -0
- package/dist/components/objects/__tests__/GetPresignedUrlButton.test.js +531 -0
- package/dist/components/providers/DataBrowserProvider.d.ts +23 -12
- package/dist/components/providers/DataBrowserProvider.js +60 -38
- package/dist/components/providers/QueryProvider.d.ts +9 -0
- package/dist/components/providers/QueryProvider.js +21 -0
- package/dist/components/search/MetadataSearch.js +29 -28
- package/dist/components/search/SearchHints.js +1 -1
- package/dist/components/ui/ArrayFieldActions.d.ts +36 -0
- package/dist/components/ui/ArrayFieldActions.js +43 -0
- package/dist/components/ui/ConfirmDeleteRuleModal.d.ts +16 -0
- package/dist/components/ui/ConfirmDeleteRuleModal.js +48 -0
- package/dist/components/ui/DeleteObjectModalContent.d.ts +1 -1
- package/dist/components/ui/DeleteObjectModalContent.js +12 -12
- package/dist/components/ui/FilterFormSection.d.ts +44 -0
- package/dist/components/ui/FilterFormSection.js +159 -0
- package/dist/components/ui/Search.elements.d.ts +2 -2
- package/dist/components/ui/Search.elements.js +7 -7
- package/dist/components/ui/Table.elements.d.ts +2 -1
- package/dist/components/ui/Table.elements.js +18 -12
- package/dist/config/__tests__/factory.test.d.ts +1 -0
- package/dist/config/__tests__/factory.test.js +311 -0
- package/dist/config/factory.d.ts +14 -49
- package/dist/config/factory.js +23 -68
- package/dist/config/types.d.ts +212 -34
- package/dist/contexts/DataBrowserUICustomizationContext.d.ts +27 -0
- package/dist/contexts/DataBrowserUICustomizationContext.js +13 -0
- package/dist/hooks/__tests__/useAccessibleBuckets.test.d.ts +1 -0
- package/dist/hooks/__tests__/useAccessibleBuckets.test.js +145 -0
- package/dist/hooks/__tests__/useISVBucketDetection.test.d.ts +1 -0
- package/dist/hooks/__tests__/useISVBucketDetection.test.js +188 -0
- package/dist/hooks/__tests__/useIsBucketEmpty.test.js +27 -27
- package/dist/hooks/__tests__/useLoginMutation.test.d.ts +1 -0
- package/dist/hooks/__tests__/useLoginMutation.test.js +194 -0
- package/dist/hooks/bucketConfiguration.d.ts +8 -1
- package/dist/hooks/bucketConfiguration.js +52 -51
- package/dist/hooks/bucketOperations.d.ts +10 -1
- package/dist/hooks/bucketOperations.js +10 -9
- package/dist/hooks/factories/__tests__/useCreateS3FunctionMutationHook.test.js +80 -80
- package/dist/hooks/factories/__tests__/useCreateS3InfiniteQueryHook.test.js +80 -80
- package/dist/hooks/factories/__tests__/useCreateS3LoginHook.test.js +44 -44
- package/dist/hooks/factories/__tests__/useCreateS3MutationHook.test.js +63 -63
- package/dist/hooks/factories/__tests__/useCreateS3QueryHook.test.js +95 -52
- package/dist/hooks/factories/index.d.ts +4 -4
- package/dist/hooks/factories/index.js +2 -2
- package/dist/hooks/factories/useCreateS3InfiniteQueryHook.d.ts +2 -2
- package/dist/hooks/factories/useCreateS3InfiniteQueryHook.js +16 -13
- package/dist/hooks/factories/useCreateS3LoginHook.d.ts +2 -2
- package/dist/hooks/factories/useCreateS3LoginHook.js +1 -1
- package/dist/hooks/factories/useCreateS3MutationHook.d.ts +3 -3
- package/dist/hooks/factories/useCreateS3MutationHook.js +7 -2
- package/dist/hooks/factories/useCreateS3QueryHook.d.ts +2 -2
- package/dist/hooks/factories/useCreateS3QueryHook.js +29 -3
- package/dist/hooks/index.d.ts +19 -8
- package/dist/hooks/index.js +16 -5
- package/dist/hooks/loginOperations.d.ts +1 -1
- package/dist/hooks/loginOperations.js +1 -1
- package/dist/hooks/objectOperations.d.ts +2 -2
- package/dist/hooks/objectOperations.js +50 -49
- package/dist/hooks/presignedOperations.d.ts +4 -4
- package/dist/hooks/presignedOperations.js +5 -5
- package/dist/hooks/useAccessibleBuckets.d.ts +11 -0
- package/dist/hooks/useAccessibleBuckets.js +115 -0
- package/dist/hooks/useBatchObjectLegalHold.d.ts +11 -0
- package/dist/hooks/useBatchObjectLegalHold.js +48 -0
- package/dist/hooks/useBucketConfigEditor.d.ts +31 -0
- package/dist/hooks/useBucketConfigEditor.js +82 -0
- package/dist/hooks/useDataBrowserNavigate.d.ts +28 -0
- package/dist/hooks/useDataBrowserNavigate.js +24 -0
- package/dist/hooks/useDeleteBucketConfigRule.d.ts +26 -0
- package/dist/hooks/useDeleteBucketConfigRule.js +46 -0
- package/dist/hooks/useEmptyBucket.d.ts +27 -0
- package/dist/hooks/useEmptyBucket.js +116 -0
- package/dist/hooks/useFeatures.d.ts +7 -0
- package/dist/hooks/useFeatures.js +8 -0
- package/dist/hooks/useISVBucketDetection.d.ts +15 -0
- package/dist/hooks/useISVBucketDetection.js +27 -0
- package/dist/hooks/useIsBucketEmpty.js +4 -4
- package/dist/hooks/useLimitedAccessFlow.d.ts +48 -0
- package/dist/hooks/useLimitedAccessFlow.js +23 -0
- package/dist/hooks/useS3Client.d.ts +6 -0
- package/dist/hooks/useS3Client.js +3 -2
- package/dist/hooks/useS3ConfigSwitch.d.ts +11 -0
- package/dist/hooks/useS3ConfigSwitch.js +37 -0
- package/dist/hooks/useSupportedNotificationEvents.d.ts +6 -0
- package/dist/hooks/useSupportedNotificationEvents.js +8 -0
- package/dist/hooks/useTableRowSelection.d.ts +9 -0
- package/dist/hooks/useTableRowSelection.js +45 -0
- package/dist/index.d.ts +6 -6
- package/dist/index.js +2 -2
- package/dist/schemas/bucketPolicySchema.json +3 -13
- package/dist/test/msw/handlers/deleteBucket.d.ts +1 -1
- package/dist/test/msw/handlers/deleteBucket.js +20 -10
- package/dist/test/msw/handlers/getBucketAcl.d.ts +1 -1
- package/dist/test/msw/handlers/getBucketAcl.js +29 -17
- package/dist/test/msw/handlers/getBucketLocation.d.ts +1 -1
- package/dist/test/msw/handlers/getBucketLocation.js +29 -15
- package/dist/test/msw/handlers/getBucketPolicy.d.ts +1 -1
- package/dist/test/msw/handlers/getBucketPolicy.js +52 -32
- package/dist/test/msw/handlers/headObject.d.ts +1 -1
- package/dist/test/msw/handlers/headObject.js +31 -13
- package/dist/test/msw/handlers/listBuckets.d.ts +1 -1
- package/dist/test/msw/handlers/listBuckets.js +5 -3
- package/dist/test/msw/handlers/listObjectVersions.d.ts +1 -1
- package/dist/test/msw/handlers/listObjectVersions.js +38 -26
- package/dist/test/msw/handlers/listObjects.d.ts +1 -1
- package/dist/test/msw/handlers/listObjects.js +35 -23
- package/dist/test/msw/handlers/objectLegalHold.d.ts +1 -1
- package/dist/test/msw/handlers/objectLegalHold.js +32 -17
- package/dist/test/msw/handlers/objectRetention.d.ts +1 -1
- package/dist/test/msw/handlers/objectRetention.js +31 -17
- package/dist/test/msw/handlers/putBucketAcl.d.ts +1 -1
- package/dist/test/msw/handlers/putBucketAcl.js +29 -14
- package/dist/test/msw/handlers/putObject.d.ts +1 -1
- package/dist/test/msw/handlers/putObject.js +27 -12
- package/dist/test/msw/handlers.d.ts +3 -3
- package/dist/test/msw/handlers.js +77 -54
- package/dist/test/msw/index.d.ts +2 -2
- package/dist/test/msw/index.js +1 -1
- package/dist/test/msw/server.d.ts +1 -1
- package/dist/test/msw/server.js +1 -1
- package/dist/test/msw/utils.js +2 -2
- package/dist/test/setup.d.ts +1 -1
- package/dist/test/setup.js +13 -30
- package/dist/test/testUtils.d.ts +170 -36
- package/dist/test/testUtils.js +229 -116
- package/dist/test/utils/errorHandling.test.js +146 -108
- package/dist/types/index.d.ts +49 -36
- package/dist/types/monaco.d.ts +13 -0
- package/dist/types/monaco.js +0 -0
- package/dist/utils/__tests__/proxyMiddleware.test.d.ts +1 -0
- package/dist/utils/__tests__/proxyMiddleware.test.js +579 -0
- package/dist/utils/__tests__/s3Client.test.d.ts +1 -0
- package/dist/utils/__tests__/s3Client.test.js +340 -0
- package/dist/utils/__tests__/s3ConfigIdentifier.test.d.ts +1 -0
- package/dist/utils/__tests__/s3ConfigIdentifier.test.js +437 -0
- package/dist/utils/constants.d.ts +22 -0
- package/dist/utils/constants.js +19 -0
- package/dist/utils/deletion/index.d.ts +2 -2
- package/dist/utils/deletion/index.js +1 -1
- package/dist/utils/deletion/messages.d.ts +1 -1
- package/dist/utils/deletion/messages.js +4 -4
- package/dist/utils/errorHandling.d.ts +12 -3
- package/dist/utils/errorHandling.js +12 -7
- package/dist/utils/hooks.js +8 -8
- package/dist/utils/index.d.ts +5 -2
- package/dist/utils/index.js +5 -1
- package/dist/utils/proxyMiddleware.d.ts +32 -13
- package/dist/utils/proxyMiddleware.js +90 -36
- package/dist/utils/s3Client.d.ts +14 -4
- package/dist/utils/s3Client.js +5 -26
- package/dist/utils/s3ConfigIdentifier.d.ts +79 -0
- package/dist/utils/s3ConfigIdentifier.js +57 -0
- package/dist/utils/s3RuleUtils.d.ts +53 -0
- package/dist/utils/s3RuleUtils.js +101 -0
- package/package.json +10 -8
- package/dist/components/__tests__/BucketNotificationCreatePage.test.js +0 -316
- package/dist/components/buckets/BucketPolicyButton.d.ts +0 -7
- package/dist/components/buckets/notifications/BucketNotificationCreatePage.d.ts +0 -1
- package/dist/components/buckets/notifications/BucketNotificationCreatePage.js +0 -234
- package/dist/hooks/useLoginMutation.d.ts +0 -21
- package/dist/hooks/useLoginMutation.js +0 -9
- package/dist/utils/useFeatures.d.ts +0 -1
- package/dist/utils/useFeatures.js +0 -7
- /package/dist/components/__tests__/{BucketNotificationCreatePage.test.d.ts → BucketAccessor.test.d.ts} +0 -0
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { useCallback, useState } from "react";
|
|
3
|
-
import { useDropzone } from "react-dropzone";
|
|
4
2
|
import { Icon, Modal, PrettyBytes, Stack, Wrap, spacing } from "@scality/core-ui";
|
|
5
3
|
import { Button } from "@scality/core-ui/dist/components/buttonv2/Buttonv2.component";
|
|
4
|
+
import { useCallback, useState } from "react";
|
|
5
|
+
import { useDropzone } from "react-dropzone";
|
|
6
6
|
import styled_components from "styled-components";
|
|
7
7
|
import { useUploadObjects } from "../../hooks/index.js";
|
|
8
8
|
const DropZone = styled_components.div`
|
|
@@ -51,7 +51,7 @@ const RemoveButton = styled_components.button`
|
|
|
51
51
|
}
|
|
52
52
|
`;
|
|
53
53
|
const maybePluralize = (count, word)=>1 === count ? `1 ${word}` : `${count} ${word}s`;
|
|
54
|
-
const getTitle = (fileCount)=>0 === fileCount ?
|
|
54
|
+
const getTitle = (fileCount)=>0 === fileCount ? 'Upload Files' : `Upload ${maybePluralize(fileCount, 'file')}`;
|
|
55
55
|
const FileList = ({ acceptedFiles, open, removeFile })=>/*#__PURE__*/ jsxs("div", {
|
|
56
56
|
children: [
|
|
57
57
|
/*#__PURE__*/ jsx(Button, {
|
|
@@ -111,7 +111,7 @@ const NoFile = ({ open })=>/*#__PURE__*/ jsxs(EmptyFile, {
|
|
|
111
111
|
})
|
|
112
112
|
]
|
|
113
113
|
});
|
|
114
|
-
const
|
|
114
|
+
const UploadButton = ({ bucket, prefix = '', uploadOptions = {}, onUploadSuccess, onUploadError })=>{
|
|
115
115
|
const [isModalOpen, setIsModalOpen] = useState(false);
|
|
116
116
|
const [acceptedFiles, setAcceptedFiles] = useState([]);
|
|
117
117
|
const uploadMutation = useUploadObjects();
|
|
@@ -177,8 +177,8 @@ const UploadButton_UploadButton = ({ bucket, prefix = "", uploadOptions = {}, on
|
|
|
177
177
|
icon: /*#__PURE__*/ jsx(Icon, {
|
|
178
178
|
name: "Simple-upload"
|
|
179
179
|
}),
|
|
180
|
-
label:
|
|
181
|
-
variant:
|
|
180
|
+
label: 'Upload',
|
|
181
|
+
variant: 'secondary',
|
|
182
182
|
onClick: openModal
|
|
183
183
|
}),
|
|
184
184
|
isModalOpen && /*#__PURE__*/ jsx(Modal, {
|
|
@@ -196,9 +196,9 @@ const UploadButton_UploadButton = ({ bucket, prefix = "", uploadOptions = {}, on
|
|
|
196
196
|
}),
|
|
197
197
|
/*#__PURE__*/ jsx(Button, {
|
|
198
198
|
disabled: 0 === acceptedFiles.length || uploadMutation.isPending,
|
|
199
|
-
variant: "
|
|
199
|
+
variant: "primary",
|
|
200
200
|
onClick: handleUpload,
|
|
201
|
-
label: uploadMutation.isPending ?
|
|
201
|
+
label: uploadMutation.isPending ? 'Uploading...' : 'Upload'
|
|
202
202
|
})
|
|
203
203
|
]
|
|
204
204
|
})
|
|
@@ -225,5 +225,5 @@ const UploadButton_UploadButton = ({ bucket, prefix = "", uploadOptions = {}, on
|
|
|
225
225
|
]
|
|
226
226
|
});
|
|
227
227
|
};
|
|
228
|
-
const
|
|
229
|
-
export {
|
|
228
|
+
const objects_UploadButton = UploadButton;
|
|
229
|
+
export { UploadButton, objects_UploadButton as default };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,531 @@
|
|
|
1
|
+
import { jsx } from "react/jsx-runtime";
|
|
2
|
+
import { useToast } from "@scality/core-ui";
|
|
3
|
+
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
|
|
4
|
+
import { cleanup, render, screen, waitFor } from "@testing-library/react";
|
|
5
|
+
import user_event from "@testing-library/user-event";
|
|
6
|
+
import { useGetPresignedDownload } from "../../../hooks/index.js";
|
|
7
|
+
import { GetPresignedUrlButton } from "../GetPresignedUrlButton.js";
|
|
8
|
+
jest.mock('../../../hooks');
|
|
9
|
+
jest.mock('@scality/core-ui', ()=>{
|
|
10
|
+
const actual = jest.requireActual('@scality/core-ui');
|
|
11
|
+
return {
|
|
12
|
+
...actual,
|
|
13
|
+
useToast: jest.fn()
|
|
14
|
+
};
|
|
15
|
+
});
|
|
16
|
+
const mockUseGetPresignedDownload = jest.mocked(useGetPresignedDownload);
|
|
17
|
+
const mockUseToast = jest.mocked(useToast);
|
|
18
|
+
const defaultProps = {
|
|
19
|
+
bucketName: 'test-bucket',
|
|
20
|
+
objectKey: 'folder/test-object.txt',
|
|
21
|
+
versionId: 'test-version-id'
|
|
22
|
+
};
|
|
23
|
+
const mockPresignedResult = {
|
|
24
|
+
Url: 'https://s3.example.com/test-bucket/folder/test-object.txt?signature=abc123',
|
|
25
|
+
ExpiresAt: new Date('2024-01-08T00:00:00Z'),
|
|
26
|
+
Bucket: 'test-bucket',
|
|
27
|
+
Key: 'folder/test-object.txt'
|
|
28
|
+
};
|
|
29
|
+
const setupMockDefaults = ()=>{
|
|
30
|
+
mockUseGetPresignedDownload.mockReturnValue({
|
|
31
|
+
mutateAsync: jest.fn().mockResolvedValue(mockPresignedResult),
|
|
32
|
+
isPending: false
|
|
33
|
+
});
|
|
34
|
+
mockUseToast.mockReturnValue({
|
|
35
|
+
showToast: jest.fn()
|
|
36
|
+
});
|
|
37
|
+
};
|
|
38
|
+
const renderWithProviders = (ui)=>{
|
|
39
|
+
const queryClient = new QueryClient({
|
|
40
|
+
defaultOptions: {
|
|
41
|
+
queries: {
|
|
42
|
+
retry: false
|
|
43
|
+
},
|
|
44
|
+
mutations: {
|
|
45
|
+
retry: false
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
return render(/*#__PURE__*/ jsx(QueryClientProvider, {
|
|
50
|
+
client: queryClient,
|
|
51
|
+
children: ui
|
|
52
|
+
}));
|
|
53
|
+
};
|
|
54
|
+
describe('GetPresignedUrlButton', ()=>{
|
|
55
|
+
beforeEach(()=>{
|
|
56
|
+
jest.clearAllMocks();
|
|
57
|
+
setupMockDefaults();
|
|
58
|
+
});
|
|
59
|
+
afterEach(()=>{
|
|
60
|
+
cleanup();
|
|
61
|
+
});
|
|
62
|
+
describe('Modal Behavior', ()=>{
|
|
63
|
+
it('should render the button', ()=>{
|
|
64
|
+
renderWithProviders(/*#__PURE__*/ jsx(GetPresignedUrlButton, {
|
|
65
|
+
...defaultProps
|
|
66
|
+
}));
|
|
67
|
+
expect(screen.getByRole('button', {
|
|
68
|
+
name: /get pre-signed url/i
|
|
69
|
+
})).toBeInTheDocument();
|
|
70
|
+
});
|
|
71
|
+
it('should open modal when button is clicked', async ()=>{
|
|
72
|
+
const user = user_event.setup();
|
|
73
|
+
renderWithProviders(/*#__PURE__*/ jsx(GetPresignedUrlButton, {
|
|
74
|
+
...defaultProps
|
|
75
|
+
}));
|
|
76
|
+
await user.click(screen.getByRole('button', {
|
|
77
|
+
name: /get pre-signed url/i
|
|
78
|
+
}));
|
|
79
|
+
expect(screen.getByText('Get a pre-signed url')).toBeInTheDocument();
|
|
80
|
+
expect(screen.getByText('test-object.txt')).toBeInTheDocument();
|
|
81
|
+
});
|
|
82
|
+
it('should close modal when Close button is clicked', async ()=>{
|
|
83
|
+
const user = user_event.setup();
|
|
84
|
+
renderWithProviders(/*#__PURE__*/ jsx(GetPresignedUrlButton, {
|
|
85
|
+
...defaultProps
|
|
86
|
+
}));
|
|
87
|
+
await user.click(screen.getByRole('button', {
|
|
88
|
+
name: /get pre-signed url/i
|
|
89
|
+
}));
|
|
90
|
+
expect(screen.getByText('Get a pre-signed url')).toBeInTheDocument();
|
|
91
|
+
await user.click(screen.getByRole('button', {
|
|
92
|
+
name: /close/i
|
|
93
|
+
}));
|
|
94
|
+
await waitFor(()=>{
|
|
95
|
+
expect(screen.queryByText('Get a pre-signed url')).not.toBeInTheDocument();
|
|
96
|
+
});
|
|
97
|
+
});
|
|
98
|
+
it('should reset state when modal closes', async ()=>{
|
|
99
|
+
const user = user_event.setup();
|
|
100
|
+
renderWithProviders(/*#__PURE__*/ jsx(GetPresignedUrlButton, {
|
|
101
|
+
...defaultProps
|
|
102
|
+
}));
|
|
103
|
+
await user.click(screen.getByRole('button', {
|
|
104
|
+
name: /get pre-signed url/i
|
|
105
|
+
}));
|
|
106
|
+
const daysInput = screen.getByLabelText('Days');
|
|
107
|
+
await user.clear(daysInput);
|
|
108
|
+
await user.type(daysInput, '3');
|
|
109
|
+
await user.click(screen.getByRole('button', {
|
|
110
|
+
name: /generate a pre-signed url/i
|
|
111
|
+
}));
|
|
112
|
+
await waitFor(()=>{
|
|
113
|
+
expect(screen.getByLabelText('Generated pre-signed URL')).toBeInTheDocument();
|
|
114
|
+
});
|
|
115
|
+
await user.click(screen.getByRole('button', {
|
|
116
|
+
name: /close/i
|
|
117
|
+
}));
|
|
118
|
+
await user.click(screen.getByRole('button', {
|
|
119
|
+
name: /get pre-signed url/i
|
|
120
|
+
}));
|
|
121
|
+
expect(screen.getByLabelText('Days')).toHaveValue(7);
|
|
122
|
+
expect(screen.getByLabelText('Hours')).toHaveValue(0);
|
|
123
|
+
expect(screen.getByLabelText('Minutes')).toHaveValue(0);
|
|
124
|
+
expect(screen.queryByLabelText('Generated pre-signed URL')).not.toBeInTheDocument();
|
|
125
|
+
});
|
|
126
|
+
it('should display object name from key path', async ()=>{
|
|
127
|
+
const user = user_event.setup();
|
|
128
|
+
renderWithProviders(/*#__PURE__*/ jsx(GetPresignedUrlButton, {
|
|
129
|
+
...defaultProps,
|
|
130
|
+
objectKey: "deep/nested/folder/myfile.pdf"
|
|
131
|
+
}));
|
|
132
|
+
await user.click(screen.getByRole('button', {
|
|
133
|
+
name: /get pre-signed url/i
|
|
134
|
+
}));
|
|
135
|
+
expect(screen.getByText('myfile.pdf')).toBeInTheDocument();
|
|
136
|
+
});
|
|
137
|
+
it('should handle object key without slashes', async ()=>{
|
|
138
|
+
const user = user_event.setup();
|
|
139
|
+
renderWithProviders(/*#__PURE__*/ jsx(GetPresignedUrlButton, {
|
|
140
|
+
...defaultProps,
|
|
141
|
+
objectKey: "simple-file.txt"
|
|
142
|
+
}));
|
|
143
|
+
await user.click(screen.getByRole('button', {
|
|
144
|
+
name: /get pre-signed url/i
|
|
145
|
+
}));
|
|
146
|
+
expect(screen.getByText('simple-file.txt')).toBeInTheDocument();
|
|
147
|
+
});
|
|
148
|
+
});
|
|
149
|
+
describe('Expiration Time Input', ()=>{
|
|
150
|
+
it('should initialize with 7 days, 0 hours, 0 minutes', async ()=>{
|
|
151
|
+
const user = user_event.setup();
|
|
152
|
+
renderWithProviders(/*#__PURE__*/ jsx(GetPresignedUrlButton, {
|
|
153
|
+
...defaultProps
|
|
154
|
+
}));
|
|
155
|
+
await user.click(screen.getByRole('button', {
|
|
156
|
+
name: /get pre-signed url/i
|
|
157
|
+
}));
|
|
158
|
+
expect(screen.getByLabelText('Days')).toHaveValue(7);
|
|
159
|
+
expect(screen.getByLabelText('Hours')).toHaveValue(0);
|
|
160
|
+
expect(screen.getByLabelText('Minutes')).toHaveValue(0);
|
|
161
|
+
});
|
|
162
|
+
it('should clamp days input to max 7', async ()=>{
|
|
163
|
+
const user = user_event.setup();
|
|
164
|
+
renderWithProviders(/*#__PURE__*/ jsx(GetPresignedUrlButton, {
|
|
165
|
+
...defaultProps
|
|
166
|
+
}));
|
|
167
|
+
await user.click(screen.getByRole('button', {
|
|
168
|
+
name: /get pre-signed url/i
|
|
169
|
+
}));
|
|
170
|
+
const daysInput = screen.getByLabelText('Days');
|
|
171
|
+
await user.clear(daysInput);
|
|
172
|
+
await user.type(daysInput, '10');
|
|
173
|
+
expect(daysInput).toHaveValue(7);
|
|
174
|
+
});
|
|
175
|
+
it('should treat empty/invalid input as 0', async ()=>{
|
|
176
|
+
const user = user_event.setup();
|
|
177
|
+
renderWithProviders(/*#__PURE__*/ jsx(GetPresignedUrlButton, {
|
|
178
|
+
...defaultProps
|
|
179
|
+
}));
|
|
180
|
+
await user.click(screen.getByRole('button', {
|
|
181
|
+
name: /get pre-signed url/i
|
|
182
|
+
}));
|
|
183
|
+
const daysInput = screen.getByLabelText('Days');
|
|
184
|
+
await user.clear(daysInput);
|
|
185
|
+
expect(daysInput).toHaveValue(0);
|
|
186
|
+
});
|
|
187
|
+
it('should disable hours and minutes when days equals 7', async ()=>{
|
|
188
|
+
const user = user_event.setup();
|
|
189
|
+
renderWithProviders(/*#__PURE__*/ jsx(GetPresignedUrlButton, {
|
|
190
|
+
...defaultProps
|
|
191
|
+
}));
|
|
192
|
+
await user.click(screen.getByRole('button', {
|
|
193
|
+
name: /get pre-signed url/i
|
|
194
|
+
}));
|
|
195
|
+
expect(screen.getByLabelText('Hours')).toBeDisabled();
|
|
196
|
+
expect(screen.getByLabelText('Minutes')).toBeDisabled();
|
|
197
|
+
});
|
|
198
|
+
it('should enable hours and minutes when days is less than 7', async ()=>{
|
|
199
|
+
const user = user_event.setup();
|
|
200
|
+
renderWithProviders(/*#__PURE__*/ jsx(GetPresignedUrlButton, {
|
|
201
|
+
...defaultProps
|
|
202
|
+
}));
|
|
203
|
+
await user.click(screen.getByRole('button', {
|
|
204
|
+
name: /get pre-signed url/i
|
|
205
|
+
}));
|
|
206
|
+
const daysInput = screen.getByLabelText('Days');
|
|
207
|
+
await user.clear(daysInput);
|
|
208
|
+
await user.type(daysInput, '3');
|
|
209
|
+
expect(screen.getByLabelText('Hours')).not.toBeDisabled();
|
|
210
|
+
expect(screen.getByLabelText('Minutes')).not.toBeDisabled();
|
|
211
|
+
});
|
|
212
|
+
it('should reset hours and minutes to 0 when days becomes 7', async ()=>{
|
|
213
|
+
const user = user_event.setup();
|
|
214
|
+
renderWithProviders(/*#__PURE__*/ jsx(GetPresignedUrlButton, {
|
|
215
|
+
...defaultProps
|
|
216
|
+
}));
|
|
217
|
+
await user.click(screen.getByRole('button', {
|
|
218
|
+
name: /get pre-signed url/i
|
|
219
|
+
}));
|
|
220
|
+
const daysInput = screen.getByLabelText('Days');
|
|
221
|
+
await user.clear(daysInput);
|
|
222
|
+
await user.type(daysInput, '3');
|
|
223
|
+
const hoursInput = screen.getByLabelText('Hours');
|
|
224
|
+
const minutesInput = screen.getByLabelText('Minutes');
|
|
225
|
+
await user.clear(hoursInput);
|
|
226
|
+
await user.type(hoursInput, '5');
|
|
227
|
+
await user.clear(minutesInput);
|
|
228
|
+
await user.type(minutesInput, '30');
|
|
229
|
+
expect(hoursInput).toHaveValue(5);
|
|
230
|
+
expect(minutesInput).toHaveValue(30);
|
|
231
|
+
await user.clear(daysInput);
|
|
232
|
+
await user.type(daysInput, '7');
|
|
233
|
+
expect(hoursInput).toHaveValue(0);
|
|
234
|
+
expect(minutesInput).toHaveValue(0);
|
|
235
|
+
});
|
|
236
|
+
it('should clamp hours input to 0-23 range', async ()=>{
|
|
237
|
+
const user = user_event.setup();
|
|
238
|
+
renderWithProviders(/*#__PURE__*/ jsx(GetPresignedUrlButton, {
|
|
239
|
+
...defaultProps
|
|
240
|
+
}));
|
|
241
|
+
await user.click(screen.getByRole('button', {
|
|
242
|
+
name: /get pre-signed url/i
|
|
243
|
+
}));
|
|
244
|
+
const daysInput = screen.getByLabelText('Days');
|
|
245
|
+
await user.clear(daysInput);
|
|
246
|
+
await user.type(daysInput, '3');
|
|
247
|
+
const hoursInput = screen.getByLabelText('Hours');
|
|
248
|
+
await user.clear(hoursInput);
|
|
249
|
+
await user.type(hoursInput, '30');
|
|
250
|
+
expect(hoursInput).toHaveValue(23);
|
|
251
|
+
});
|
|
252
|
+
it('should clamp minutes input to 0-59 range', async ()=>{
|
|
253
|
+
const user = user_event.setup();
|
|
254
|
+
renderWithProviders(/*#__PURE__*/ jsx(GetPresignedUrlButton, {
|
|
255
|
+
...defaultProps
|
|
256
|
+
}));
|
|
257
|
+
await user.click(screen.getByRole('button', {
|
|
258
|
+
name: /get pre-signed url/i
|
|
259
|
+
}));
|
|
260
|
+
const daysInput = screen.getByLabelText('Days');
|
|
261
|
+
await user.clear(daysInput);
|
|
262
|
+
await user.type(daysInput, '3');
|
|
263
|
+
const minutesInput = screen.getByLabelText('Minutes');
|
|
264
|
+
await user.clear(minutesInput);
|
|
265
|
+
await user.type(minutesInput, '99');
|
|
266
|
+
expect(minutesInput).toHaveValue(59);
|
|
267
|
+
});
|
|
268
|
+
});
|
|
269
|
+
describe('Generate Button State', ()=>{
|
|
270
|
+
it('should be disabled when total expiration is 0', async ()=>{
|
|
271
|
+
const user = user_event.setup();
|
|
272
|
+
renderWithProviders(/*#__PURE__*/ jsx(GetPresignedUrlButton, {
|
|
273
|
+
...defaultProps
|
|
274
|
+
}));
|
|
275
|
+
await user.click(screen.getByRole('button', {
|
|
276
|
+
name: /get pre-signed url/i
|
|
277
|
+
}));
|
|
278
|
+
const daysInput = screen.getByLabelText('Days');
|
|
279
|
+
await user.clear(daysInput);
|
|
280
|
+
await user.type(daysInput, '0');
|
|
281
|
+
expect(screen.getByRole('button', {
|
|
282
|
+
name: /generate a pre-signed url/i
|
|
283
|
+
})).toBeDisabled();
|
|
284
|
+
});
|
|
285
|
+
it('should be enabled with valid expiration time', async ()=>{
|
|
286
|
+
const user = user_event.setup();
|
|
287
|
+
renderWithProviders(/*#__PURE__*/ jsx(GetPresignedUrlButton, {
|
|
288
|
+
...defaultProps
|
|
289
|
+
}));
|
|
290
|
+
await user.click(screen.getByRole('button', {
|
|
291
|
+
name: /get pre-signed url/i
|
|
292
|
+
}));
|
|
293
|
+
expect(screen.getByRole('button', {
|
|
294
|
+
name: /generate a pre-signed url/i
|
|
295
|
+
})).not.toBeDisabled();
|
|
296
|
+
});
|
|
297
|
+
it('should be disabled while generating', async ()=>{
|
|
298
|
+
mockUseGetPresignedDownload.mockReturnValue({
|
|
299
|
+
mutateAsync: jest.fn().mockImplementation(()=>new Promise(()=>{})),
|
|
300
|
+
isPending: true
|
|
301
|
+
});
|
|
302
|
+
const user = user_event.setup();
|
|
303
|
+
renderWithProviders(/*#__PURE__*/ jsx(GetPresignedUrlButton, {
|
|
304
|
+
...defaultProps
|
|
305
|
+
}));
|
|
306
|
+
await user.click(screen.getByRole('button', {
|
|
307
|
+
name: /get pre-signed url/i
|
|
308
|
+
}));
|
|
309
|
+
expect(screen.getByRole('button', {
|
|
310
|
+
name: /generate a pre-signed url/i
|
|
311
|
+
})).toBeDisabled();
|
|
312
|
+
});
|
|
313
|
+
});
|
|
314
|
+
describe('URL Generation', ()=>{
|
|
315
|
+
it('should call getPresignedDownload with correct params', async ()=>{
|
|
316
|
+
const mockMutateAsync = jest.fn().mockResolvedValue(mockPresignedResult);
|
|
317
|
+
mockUseGetPresignedDownload.mockReturnValue({
|
|
318
|
+
mutateAsync: mockMutateAsync,
|
|
319
|
+
isPending: false
|
|
320
|
+
});
|
|
321
|
+
const user = user_event.setup();
|
|
322
|
+
renderWithProviders(/*#__PURE__*/ jsx(GetPresignedUrlButton, {
|
|
323
|
+
...defaultProps
|
|
324
|
+
}));
|
|
325
|
+
await user.click(screen.getByRole('button', {
|
|
326
|
+
name: /get pre-signed url/i
|
|
327
|
+
}));
|
|
328
|
+
await user.click(screen.getByRole('button', {
|
|
329
|
+
name: /generate a pre-signed url/i
|
|
330
|
+
}));
|
|
331
|
+
expect(mockMutateAsync).toHaveBeenCalledWith({
|
|
332
|
+
Bucket: 'test-bucket',
|
|
333
|
+
Key: 'folder/test-object.txt',
|
|
334
|
+
VersionId: 'test-version-id',
|
|
335
|
+
expiresIn: 604800
|
|
336
|
+
});
|
|
337
|
+
});
|
|
338
|
+
it('should not include versionId when not provided', async ()=>{
|
|
339
|
+
const mockMutateAsync = jest.fn().mockResolvedValue(mockPresignedResult);
|
|
340
|
+
mockUseGetPresignedDownload.mockReturnValue({
|
|
341
|
+
mutateAsync: mockMutateAsync,
|
|
342
|
+
isPending: false
|
|
343
|
+
});
|
|
344
|
+
const user = user_event.setup();
|
|
345
|
+
renderWithProviders(/*#__PURE__*/ jsx(GetPresignedUrlButton, {
|
|
346
|
+
bucketName: "test-bucket",
|
|
347
|
+
objectKey: "test.txt"
|
|
348
|
+
}));
|
|
349
|
+
await user.click(screen.getByRole('button', {
|
|
350
|
+
name: /get pre-signed url/i
|
|
351
|
+
}));
|
|
352
|
+
await user.click(screen.getByRole('button', {
|
|
353
|
+
name: /generate a pre-signed url/i
|
|
354
|
+
}));
|
|
355
|
+
expect(mockMutateAsync).toHaveBeenCalledWith({
|
|
356
|
+
Bucket: 'test-bucket',
|
|
357
|
+
Key: 'test.txt',
|
|
358
|
+
expiresIn: 604800
|
|
359
|
+
});
|
|
360
|
+
});
|
|
361
|
+
it('should display generated URL on success', async ()=>{
|
|
362
|
+
const user = user_event.setup();
|
|
363
|
+
renderWithProviders(/*#__PURE__*/ jsx(GetPresignedUrlButton, {
|
|
364
|
+
...defaultProps
|
|
365
|
+
}));
|
|
366
|
+
await user.click(screen.getByRole('button', {
|
|
367
|
+
name: /get pre-signed url/i
|
|
368
|
+
}));
|
|
369
|
+
await user.click(screen.getByRole('button', {
|
|
370
|
+
name: /generate a pre-signed url/i
|
|
371
|
+
}));
|
|
372
|
+
await waitFor(()=>{
|
|
373
|
+
expect(screen.getByLabelText('Generated pre-signed URL')).toHaveValue(mockPresignedResult.Url);
|
|
374
|
+
});
|
|
375
|
+
});
|
|
376
|
+
it('should display expiration date preview', async ()=>{
|
|
377
|
+
const user = user_event.setup();
|
|
378
|
+
renderWithProviders(/*#__PURE__*/ jsx(GetPresignedUrlButton, {
|
|
379
|
+
...defaultProps
|
|
380
|
+
}));
|
|
381
|
+
await user.click(screen.getByRole('button', {
|
|
382
|
+
name: /get pre-signed url/i
|
|
383
|
+
}));
|
|
384
|
+
expect(screen.getByText(/Access ends on:/)).toBeInTheDocument();
|
|
385
|
+
});
|
|
386
|
+
it('should change button label after first generation', async ()=>{
|
|
387
|
+
const user = user_event.setup();
|
|
388
|
+
renderWithProviders(/*#__PURE__*/ jsx(GetPresignedUrlButton, {
|
|
389
|
+
...defaultProps
|
|
390
|
+
}));
|
|
391
|
+
await user.click(screen.getByRole('button', {
|
|
392
|
+
name: /get pre-signed url/i
|
|
393
|
+
}));
|
|
394
|
+
expect(screen.getByRole('button', {
|
|
395
|
+
name: /generate a pre-signed url/i
|
|
396
|
+
})).toBeInTheDocument();
|
|
397
|
+
await user.click(screen.getByRole('button', {
|
|
398
|
+
name: /generate a pre-signed url/i
|
|
399
|
+
}));
|
|
400
|
+
await waitFor(()=>{
|
|
401
|
+
expect(screen.getByRole('button', {
|
|
402
|
+
name: /generate another pre-signed url/i
|
|
403
|
+
})).toBeInTheDocument();
|
|
404
|
+
});
|
|
405
|
+
});
|
|
406
|
+
it('should calculate correct expiration seconds', async ()=>{
|
|
407
|
+
const mockMutateAsync = jest.fn().mockResolvedValue(mockPresignedResult);
|
|
408
|
+
mockUseGetPresignedDownload.mockReturnValue({
|
|
409
|
+
mutateAsync: mockMutateAsync,
|
|
410
|
+
isPending: false
|
|
411
|
+
});
|
|
412
|
+
const user = user_event.setup();
|
|
413
|
+
renderWithProviders(/*#__PURE__*/ jsx(GetPresignedUrlButton, {
|
|
414
|
+
...defaultProps
|
|
415
|
+
}));
|
|
416
|
+
await user.click(screen.getByRole('button', {
|
|
417
|
+
name: /get pre-signed url/i
|
|
418
|
+
}));
|
|
419
|
+
const daysInput = screen.getByLabelText('Days');
|
|
420
|
+
await user.clear(daysInput);
|
|
421
|
+
await user.type(daysInput, '2');
|
|
422
|
+
const hoursInput = screen.getByLabelText('Hours');
|
|
423
|
+
await user.clear(hoursInput);
|
|
424
|
+
await user.type(hoursInput, '3');
|
|
425
|
+
const minutesInput = screen.getByLabelText('Minutes');
|
|
426
|
+
await user.clear(minutesInput);
|
|
427
|
+
await user.type(minutesInput, '30');
|
|
428
|
+
await user.click(screen.getByRole('button', {
|
|
429
|
+
name: /generate a pre-signed url/i
|
|
430
|
+
}));
|
|
431
|
+
expect(mockMutateAsync).toHaveBeenCalledWith(expect.objectContaining({
|
|
432
|
+
expiresIn: 185400
|
|
433
|
+
}));
|
|
434
|
+
});
|
|
435
|
+
});
|
|
436
|
+
describe('Error Handling', ()=>{
|
|
437
|
+
it('should show toast with error.message for Error instances', async ()=>{
|
|
438
|
+
const mockShowToast = jest.fn();
|
|
439
|
+
mockUseToast.mockReturnValue({
|
|
440
|
+
showToast: mockShowToast
|
|
441
|
+
});
|
|
442
|
+
const errorMessage = 'Access denied to bucket';
|
|
443
|
+
mockUseGetPresignedDownload.mockReturnValue({
|
|
444
|
+
mutateAsync: jest.fn().mockRejectedValue(new Error(errorMessage)),
|
|
445
|
+
isPending: false
|
|
446
|
+
});
|
|
447
|
+
const user = user_event.setup();
|
|
448
|
+
renderWithProviders(/*#__PURE__*/ jsx(GetPresignedUrlButton, {
|
|
449
|
+
...defaultProps
|
|
450
|
+
}));
|
|
451
|
+
await user.click(screen.getByRole('button', {
|
|
452
|
+
name: /get pre-signed url/i
|
|
453
|
+
}));
|
|
454
|
+
await user.click(screen.getByRole('button', {
|
|
455
|
+
name: /generate a pre-signed url/i
|
|
456
|
+
}));
|
|
457
|
+
await waitFor(()=>{
|
|
458
|
+
expect(mockShowToast).toHaveBeenCalledWith({
|
|
459
|
+
open: true,
|
|
460
|
+
message: errorMessage,
|
|
461
|
+
status: 'error'
|
|
462
|
+
});
|
|
463
|
+
});
|
|
464
|
+
});
|
|
465
|
+
it('should show generic toast for non-Error failures', async ()=>{
|
|
466
|
+
const mockShowToast = jest.fn();
|
|
467
|
+
mockUseToast.mockReturnValue({
|
|
468
|
+
showToast: mockShowToast
|
|
469
|
+
});
|
|
470
|
+
mockUseGetPresignedDownload.mockReturnValue({
|
|
471
|
+
mutateAsync: jest.fn().mockRejectedValue('string error'),
|
|
472
|
+
isPending: false
|
|
473
|
+
});
|
|
474
|
+
const user = user_event.setup();
|
|
475
|
+
renderWithProviders(/*#__PURE__*/ jsx(GetPresignedUrlButton, {
|
|
476
|
+
...defaultProps
|
|
477
|
+
}));
|
|
478
|
+
await user.click(screen.getByRole('button', {
|
|
479
|
+
name: /get pre-signed url/i
|
|
480
|
+
}));
|
|
481
|
+
await user.click(screen.getByRole('button', {
|
|
482
|
+
name: /generate a pre-signed url/i
|
|
483
|
+
}));
|
|
484
|
+
await waitFor(()=>{
|
|
485
|
+
expect(mockShowToast).toHaveBeenCalledWith({
|
|
486
|
+
open: true,
|
|
487
|
+
message: 'Failed to generate presigned URL',
|
|
488
|
+
status: 'error'
|
|
489
|
+
});
|
|
490
|
+
});
|
|
491
|
+
});
|
|
492
|
+
it('should not display URL when generation fails', async ()=>{
|
|
493
|
+
mockUseGetPresignedDownload.mockReturnValue({
|
|
494
|
+
mutateAsync: jest.fn().mockRejectedValue(new Error('Failed')),
|
|
495
|
+
isPending: false
|
|
496
|
+
});
|
|
497
|
+
const user = user_event.setup();
|
|
498
|
+
renderWithProviders(/*#__PURE__*/ jsx(GetPresignedUrlButton, {
|
|
499
|
+
...defaultProps
|
|
500
|
+
}));
|
|
501
|
+
await user.click(screen.getByRole('button', {
|
|
502
|
+
name: /get pre-signed url/i
|
|
503
|
+
}));
|
|
504
|
+
await user.click(screen.getByRole('button', {
|
|
505
|
+
name: /generate a pre-signed url/i
|
|
506
|
+
}));
|
|
507
|
+
await waitFor(()=>{
|
|
508
|
+
expect(screen.queryByLabelText('Generated pre-signed URL')).not.toBeInTheDocument();
|
|
509
|
+
});
|
|
510
|
+
});
|
|
511
|
+
});
|
|
512
|
+
describe('Copy Button', ()=>{
|
|
513
|
+
it('should render copy button with generated URL', async ()=>{
|
|
514
|
+
const user = user_event.setup();
|
|
515
|
+
renderWithProviders(/*#__PURE__*/ jsx(GetPresignedUrlButton, {
|
|
516
|
+
...defaultProps
|
|
517
|
+
}));
|
|
518
|
+
await user.click(screen.getByRole('button', {
|
|
519
|
+
name: /get pre-signed url/i
|
|
520
|
+
}));
|
|
521
|
+
await user.click(screen.getByRole('button', {
|
|
522
|
+
name: /generate a pre-signed url/i
|
|
523
|
+
}));
|
|
524
|
+
await waitFor(()=>{
|
|
525
|
+
expect(screen.getByRole('button', {
|
|
526
|
+
name: /copy/i
|
|
527
|
+
})).toBeInTheDocument();
|
|
528
|
+
});
|
|
529
|
+
});
|
|
530
|
+
});
|
|
531
|
+
});
|
|
@@ -1,20 +1,31 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { QueryClient } from
|
|
3
|
-
import
|
|
4
|
-
import {
|
|
1
|
+
import { type CoreUITheme } from '@scality/core-ui/dist/next';
|
|
2
|
+
import { type InvalidateQueryFilters, type QueryClient, type QueryKey } from '@tanstack/react-query';
|
|
3
|
+
import type React from 'react';
|
|
4
|
+
import type { GetConfigFunction } from '../../types';
|
|
5
5
|
export interface DataBrowserContextValue {
|
|
6
|
-
getS3Config: GetConfigFunction;
|
|
7
|
-
|
|
6
|
+
getS3Config: GetConfigFunction | null;
|
|
7
|
+
s3ConfigIdentifier: string;
|
|
8
8
|
}
|
|
9
|
-
export declare const DataBrowserContext: React.Context<DataBrowserContextValue
|
|
9
|
+
export declare const DataBrowserContext: React.Context<DataBrowserContextValue>;
|
|
10
10
|
export declare const useDataBrowserContext: () => DataBrowserContextValue;
|
|
11
|
-
export
|
|
12
|
-
interface DataBrowserProviderProps {
|
|
11
|
+
export interface DataBrowserProviderProps {
|
|
13
12
|
children: React.ReactNode;
|
|
14
|
-
queryClient?: QueryClient;
|
|
15
|
-
enableDevtools?: boolean;
|
|
16
13
|
getS3Config?: GetConfigFunction;
|
|
14
|
+
queryClient?: QueryClient;
|
|
17
15
|
theme?: CoreUITheme;
|
|
16
|
+
enableDevtools?: boolean;
|
|
18
17
|
}
|
|
19
18
|
export declare const DataBrowserProvider: React.FC<DataBrowserProviderProps>;
|
|
20
|
-
export {
|
|
19
|
+
export declare const useDataBrowserConfig: () => import("../../types").S3BrowserConfig & {
|
|
20
|
+
credentials: import("../../types").S3Credentials;
|
|
21
|
+
};
|
|
22
|
+
/**
|
|
23
|
+
* Hook to invalidate queries with automatic S3 config identifier prefixing.
|
|
24
|
+
*
|
|
25
|
+
* @example
|
|
26
|
+
* const invalidateQueries = useInvalidateQueries();
|
|
27
|
+
* await invalidateQueries({ queryKey: ['ListObjects', { Bucket: 'my-bucket' }] });
|
|
28
|
+
*/
|
|
29
|
+
export declare const useInvalidateQueries: () => (filters: Omit<InvalidateQueryFilters, "queryKey"> & {
|
|
30
|
+
queryKey: QueryKey;
|
|
31
|
+
}) => Promise<void>;
|