@scality/data-browser-library 1.0.0-preview.2
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/Editor.d.ts +12 -0
- package/dist/components/Editor.js +28 -0
- package/dist/components/__tests__/BucketList.test.d.ts +1 -0
- package/dist/components/__tests__/BucketList.test.js +225 -0
- package/dist/components/__tests__/BucketOverview.test.d.ts +1 -0
- package/dist/components/__tests__/BucketOverview.test.js +479 -0
- package/dist/components/__tests__/BucketPolicyPage.test.d.ts +1 -0
- package/dist/components/__tests__/BucketPolicyPage.test.js +213 -0
- package/dist/components/__tests__/CreateFolderButton.test.d.ts +1 -0
- package/dist/components/__tests__/CreateFolderButton.test.js +147 -0
- package/dist/components/__tests__/DeleteBucketButton.test.d.ts +1 -0
- package/dist/components/__tests__/DeleteBucketButton.test.js +272 -0
- package/dist/components/__tests__/DeleteObjectButton.test.d.ts +1 -0
- package/dist/components/__tests__/DeleteObjectButton.test.js +302 -0
- package/dist/components/__tests__/MetadataSearch.test.d.ts +1 -0
- package/dist/components/__tests__/MetadataSearch.test.js +201 -0
- package/dist/components/__tests__/ObjectList.test.d.ts +1 -0
- package/dist/components/__tests__/ObjectList.test.js +283 -0
- package/dist/components/__tests__/UploadButton.test.d.ts +1 -0
- package/dist/components/__tests__/UploadButton.test.js +144 -0
- package/dist/components/buckets/BucketDetails.d.ts +1 -0
- package/dist/components/buckets/BucketDetails.js +51 -0
- package/dist/components/buckets/BucketList.d.ts +12 -0
- package/dist/components/buckets/BucketList.js +136 -0
- package/dist/components/buckets/BucketLocation.d.ts +3 -0
- package/dist/components/buckets/BucketLocation.js +16 -0
- package/dist/components/buckets/BucketOverview.d.ts +14 -0
- package/dist/components/buckets/BucketOverview.js +209 -0
- package/dist/components/buckets/BucketPage.d.ts +2 -0
- package/dist/components/buckets/BucketPage.js +47 -0
- package/dist/components/buckets/BucketPolicyButton.d.ts +7 -0
- package/dist/components/buckets/BucketPolicyButton.js +18 -0
- package/dist/components/buckets/BucketPolicyPage.d.ts +1 -0
- package/dist/components/buckets/BucketPolicyPage.js +205 -0
- package/dist/components/buckets/DeleteBucketButton.d.ts +8 -0
- package/dist/components/buckets/DeleteBucketButton.js +78 -0
- package/dist/components/index.d.ts +12 -0
- package/dist/components/index.js +13 -0
- package/dist/components/layouts/BrowserPageLayout.d.ts +9 -0
- package/dist/components/layouts/BrowserPageLayout.js +46 -0
- package/dist/components/objects/CreateFolderButton.d.ts +29 -0
- package/dist/components/objects/CreateFolderButton.js +118 -0
- package/dist/components/objects/DeleteObjectButton.d.ts +8 -0
- package/dist/components/objects/DeleteObjectButton.js +191 -0
- package/dist/components/objects/ObjectDetails/ObjectMetadata.d.ts +2 -0
- package/dist/components/objects/ObjectDetails/ObjectMetadata.js +323 -0
- package/dist/components/objects/ObjectDetails/ObjectSummary.d.ts +3 -0
- package/dist/components/objects/ObjectDetails/ObjectSummary.js +193 -0
- package/dist/components/objects/ObjectDetails/ObjectTags.d.ts +3 -0
- package/dist/components/objects/ObjectDetails/ObjectTags.js +300 -0
- package/dist/components/objects/ObjectDetails/index.d.ts +9 -0
- package/dist/components/objects/ObjectDetails/index.js +49 -0
- package/dist/components/objects/ObjectList.d.ts +40 -0
- package/dist/components/objects/ObjectList.js +407 -0
- package/dist/components/objects/ObjectPage.d.ts +1 -0
- package/dist/components/objects/ObjectPage.js +43 -0
- package/dist/components/objects/UploadButton.d.ts +34 -0
- package/dist/components/objects/UploadButton.js +229 -0
- package/dist/components/providers/DataBrowserProvider.d.ts +20 -0
- package/dist/components/providers/DataBrowserProvider.js +42 -0
- package/dist/components/search/MetadataSearch.d.ts +5 -0
- package/dist/components/search/MetadataSearch.js +162 -0
- package/dist/components/search/SearchHints.d.ts +8 -0
- package/dist/components/search/SearchHints.js +21 -0
- package/dist/components/ui/DeleteObjectModalContent.d.ts +5 -0
- package/dist/components/ui/DeleteObjectModalContent.js +71 -0
- package/dist/components/ui/Search.elements.d.ts +17 -0
- package/dist/components/ui/Search.elements.js +59 -0
- package/dist/components/ui/Table.elements.d.ts +36 -0
- package/dist/components/ui/Table.elements.js +87 -0
- package/dist/config/factory.d.ts +52 -0
- package/dist/config/factory.js +70 -0
- package/dist/config/types.d.ts +46 -0
- package/dist/config/types.js +0 -0
- package/dist/hooks/__tests__/useIsBucketEmpty.test.d.ts +1 -0
- package/dist/hooks/__tests__/useIsBucketEmpty.test.js +122 -0
- package/dist/hooks/bucketConfiguration.d.ts +147 -0
- package/dist/hooks/bucketConfiguration.js +59 -0
- package/dist/hooks/bucketOperations.d.ts +36 -0
- package/dist/hooks/bucketOperations.js +12 -0
- package/dist/hooks/factories/__tests__/useCreateS3FunctionMutationHook.test.d.ts +1 -0
- package/dist/hooks/factories/__tests__/useCreateS3FunctionMutationHook.test.js +276 -0
- package/dist/hooks/factories/__tests__/useCreateS3InfiniteQueryHook.test.d.ts +1 -0
- package/dist/hooks/factories/__tests__/useCreateS3InfiniteQueryHook.test.js +259 -0
- package/dist/hooks/factories/__tests__/useCreateS3LoginHook.test.d.ts +1 -0
- package/dist/hooks/factories/__tests__/useCreateS3LoginHook.test.js +166 -0
- package/dist/hooks/factories/__tests__/useCreateS3MutationHook.test.d.ts +1 -0
- package/dist/hooks/factories/__tests__/useCreateS3MutationHook.test.js +200 -0
- package/dist/hooks/factories/__tests__/useCreateS3QueryHook.test.d.ts +1 -0
- package/dist/hooks/factories/__tests__/useCreateS3QueryHook.test.js +136 -0
- package/dist/hooks/factories/index.d.ts +18 -0
- package/dist/hooks/factories/index.js +5 -0
- package/dist/hooks/factories/useCreateS3InfiniteQueryHook.d.ts +13 -0
- package/dist/hooks/factories/useCreateS3InfiniteQueryHook.js +76 -0
- package/dist/hooks/factories/useCreateS3LoginHook.d.ts +8 -0
- package/dist/hooks/factories/useCreateS3LoginHook.js +22 -0
- package/dist/hooks/factories/useCreateS3MutationHook.d.ts +5 -0
- package/dist/hooks/factories/useCreateS3MutationHook.js +50 -0
- package/dist/hooks/factories/useCreateS3QueryHook.d.ts +3 -0
- package/dist/hooks/factories/useCreateS3QueryHook.js +30 -0
- package/dist/hooks/index.d.ts +8 -0
- package/dist/hooks/index.js +8 -0
- package/dist/hooks/loginOperations.d.ts +21 -0
- package/dist/hooks/loginOperations.js +9 -0
- package/dist/hooks/objectOperations.d.ts +190 -0
- package/dist/hooks/objectOperations.js +66 -0
- package/dist/hooks/presignedOperations.d.ts +73 -0
- package/dist/hooks/presignedOperations.js +72 -0
- package/dist/hooks/useIsBucketEmpty.d.ts +7 -0
- package/dist/hooks/useIsBucketEmpty.js +36 -0
- package/dist/hooks/useLoginMutation.d.ts +21 -0
- package/dist/hooks/useLoginMutation.js +9 -0
- package/dist/hooks/useS3Client.d.ts +1 -0
- package/dist/hooks/useS3Client.js +13 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +6 -0
- package/dist/schemas/bucketPolicySchema.json +321 -0
- package/dist/test/msw/handlers/deleteBucket.d.ts +1 -0
- package/dist/test/msw/handlers/deleteBucket.js +14 -0
- package/dist/test/msw/handlers/getBucketAcl.d.ts +1 -0
- package/dist/test/msw/handlers/getBucketAcl.js +96 -0
- package/dist/test/msw/handlers/getBucketLocation.d.ts +1 -0
- package/dist/test/msw/handlers/getBucketLocation.js +23 -0
- package/dist/test/msw/handlers/getBucketPolicy.d.ts +11 -0
- package/dist/test/msw/handlers/getBucketPolicy.js +72 -0
- package/dist/test/msw/handlers/headObject.d.ts +1 -0
- package/dist/test/msw/handlers/headObject.js +17 -0
- package/dist/test/msw/handlers/listBuckets.d.ts +1 -0
- package/dist/test/msw/handlers/listBuckets.js +24 -0
- package/dist/test/msw/handlers/listObjectVersions.d.ts +1 -0
- package/dist/test/msw/handlers/listObjectVersions.js +83 -0
- package/dist/test/msw/handlers/listObjects.d.ts +1 -0
- package/dist/test/msw/handlers/listObjects.js +66 -0
- package/dist/test/msw/handlers/objectLegalHold.d.ts +1 -0
- package/dist/test/msw/handlers/objectLegalHold.js +24 -0
- package/dist/test/msw/handlers/objectRetention.d.ts +1 -0
- package/dist/test/msw/handlers/objectRetention.js +27 -0
- package/dist/test/msw/handlers/putBucketAcl.d.ts +1 -0
- package/dist/test/msw/handlers/putBucketAcl.js +18 -0
- package/dist/test/msw/handlers/putObject.d.ts +1 -0
- package/dist/test/msw/handlers/putObject.js +16 -0
- package/dist/test/msw/handlers.d.ts +4 -0
- package/dist/test/msw/handlers.js +109 -0
- package/dist/test/msw/index.d.ts +2 -0
- package/dist/test/msw/index.js +3 -0
- package/dist/test/msw/server.d.ts +4 -0
- package/dist/test/msw/server.js +20 -0
- package/dist/test/msw/utils.d.ts +2 -0
- package/dist/test/msw/utils.js +13 -0
- package/dist/test/setup.d.ts +1 -0
- package/dist/test/setup.js +82 -0
- package/dist/test/testUtils.d.ts +82 -0
- package/dist/test/testUtils.js +236 -0
- package/dist/test/utils/errorHandling.test.d.ts +1 -0
- package/dist/test/utils/errorHandling.test.js +385 -0
- package/dist/types/index.d.ts +48 -0
- package/dist/types/index.js +0 -0
- package/dist/utils/deletion/index.d.ts +2 -0
- package/dist/utils/deletion/index.js +2 -0
- package/dist/utils/deletion/messages.d.ts +5 -0
- package/dist/utils/deletion/messages.js +29 -0
- package/dist/utils/deletion/types.d.ts +11 -0
- package/dist/utils/deletion/types.js +0 -0
- package/dist/utils/errorHandling.d.ts +54 -0
- package/dist/utils/errorHandling.js +79 -0
- package/dist/utils/hooks.d.ts +2 -0
- package/dist/utils/hooks.js +26 -0
- package/dist/utils/index.d.ts +2 -0
- package/dist/utils/index.js +2 -0
- package/dist/utils/proxyMiddleware.d.ts +18 -0
- package/dist/utils/proxyMiddleware.js +56 -0
- package/dist/utils/s3Client.d.ts +5 -0
- package/dist/utils/s3Client.js +35 -0
- package/dist/utils/useFeatures.d.ts +1 -0
- package/dist/utils/useFeatures.js +7 -0
- package/package.json +79 -0
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { rest } from "msw";
|
|
2
|
+
import { createS3ErrorXml, getS3BaseUrl } from "../utils.js";
|
|
3
|
+
const listObjectVersionsHandler = rest.get(`${getS3BaseUrl()}/:bucketName`, (req, res, ctx)=>{
|
|
4
|
+
const { bucketName } = req.params;
|
|
5
|
+
const url = new URL(req.url);
|
|
6
|
+
if (!url.searchParams.has("versions")) return;
|
|
7
|
+
const prefix = url.searchParams.get("prefix") || "";
|
|
8
|
+
const delimiter = url.searchParams.get("delimiter") || "";
|
|
9
|
+
const maxKeys = parseInt(url.searchParams.get("max-keys") || "1000", 10);
|
|
10
|
+
const keyMarker = url.searchParams.get("key-marker");
|
|
11
|
+
if ("string" == typeof bucketName) {
|
|
12
|
+
if (bucketName.includes("non-existent-bucket")) return res(ctx.status(404), ctx.xml(createS3ErrorXml("NoSuchBucket", "The specified bucket does not exist", bucketName)));
|
|
13
|
+
if (bucketName.includes("access-denied-bucket")) return res(ctx.status(403), ctx.xml(createS3ErrorXml("AccessDenied", "Access Denied")));
|
|
14
|
+
if (bucketName.includes("network-error-bucket")) return res.networkError("Failed to connect");
|
|
15
|
+
if (bucketName.includes("empty-bucket")) return res(ctx.status(200), ctx.xml(`<?xml version="1.0" encoding="UTF-8"?>
|
|
16
|
+
<ListVersionsResult xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
|
|
17
|
+
<Name>${bucketName}</Name>
|
|
18
|
+
<Prefix>${prefix}</Prefix>
|
|
19
|
+
<Delimiter>${delimiter}</Delimiter>
|
|
20
|
+
<MaxKeys>${maxKeys}</MaxKeys>
|
|
21
|
+
<IsTruncated>false</IsTruncated>
|
|
22
|
+
</ListVersionsResult>`));
|
|
23
|
+
if (keyMarker) {
|
|
24
|
+
const pageKey = prefix && "file.txt" !== prefix ? `${prefix.replace(/\/$/, "")}-v3.txt` : "file-v3.txt";
|
|
25
|
+
return res(ctx.status(200), ctx.xml(`<?xml version="1.0" encoding="UTF-8"?>
|
|
26
|
+
<ListVersionsResult xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
|
|
27
|
+
<Name>${bucketName}</Name>
|
|
28
|
+
<Prefix>${prefix}</Prefix>
|
|
29
|
+
<Delimiter>${delimiter}</Delimiter>
|
|
30
|
+
<MaxKeys>${maxKeys}</MaxKeys>
|
|
31
|
+
<IsTruncated>false</IsTruncated>
|
|
32
|
+
<Version>
|
|
33
|
+
<Key>${pageKey}</Key>
|
|
34
|
+
<VersionId>version-id-3</VersionId>
|
|
35
|
+
<IsLatest>true</IsLatest>
|
|
36
|
+
<LastModified>2023-10-12T17:50:00.000Z</LastModified>
|
|
37
|
+
<ETag>"version-etag-3"</ETag>
|
|
38
|
+
<Size>1024</Size>
|
|
39
|
+
<StorageClass>STANDARD</StorageClass>
|
|
40
|
+
</Version>
|
|
41
|
+
</ListVersionsResult>`));
|
|
42
|
+
}
|
|
43
|
+
const hasMorePages = bucketName.includes("paginated-bucket");
|
|
44
|
+
const baseKey = prefix && "file.txt" !== prefix ? prefix : "file.txt";
|
|
45
|
+
const deletedKey = prefix && "file.txt" !== prefix ? `${prefix.replace(/\/$/, "")}-deleted.txt` : "deleted-file.txt";
|
|
46
|
+
const nextKey = prefix && "file.txt" !== prefix ? `${prefix.replace(/\/$/, "")}-v2.txt` : "file-v2.txt";
|
|
47
|
+
return res(ctx.status(200), ctx.xml(`<?xml version="1.0" encoding="UTF-8"?>
|
|
48
|
+
<ListVersionsResult xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
|
|
49
|
+
<Name>${bucketName}</Name>
|
|
50
|
+
<Prefix>${prefix}</Prefix>
|
|
51
|
+
<Delimiter>${delimiter}</Delimiter>
|
|
52
|
+
<MaxKeys>${maxKeys}</MaxKeys>
|
|
53
|
+
<IsTruncated>${hasMorePages}</IsTruncated>
|
|
54
|
+
${hasMorePages ? `<NextKeyMarker>${nextKey}</NextKeyMarker><NextVersionIdMarker>version-id-2</NextVersionIdMarker>` : ""}
|
|
55
|
+
<Version>
|
|
56
|
+
<Key>${baseKey}</Key>
|
|
57
|
+
<VersionId>version-id-1</VersionId>
|
|
58
|
+
<IsLatest>true</IsLatest>
|
|
59
|
+
<LastModified>2023-10-12T17:50:00.000Z</LastModified>
|
|
60
|
+
<ETag>"version-etag-1"</ETag>
|
|
61
|
+
<Size>1024</Size>
|
|
62
|
+
<StorageClass>STANDARD</StorageClass>
|
|
63
|
+
</Version>
|
|
64
|
+
<Version>
|
|
65
|
+
<Key>${baseKey}</Key>
|
|
66
|
+
<VersionId>version-id-2</VersionId>
|
|
67
|
+
<IsLatest>false</IsLatest>
|
|
68
|
+
<LastModified>2023-10-11T17:50:00.000Z</LastModified>
|
|
69
|
+
<ETag>"version-etag-2"</ETag>
|
|
70
|
+
<Size>512</Size>
|
|
71
|
+
<StorageClass>STANDARD</StorageClass>
|
|
72
|
+
</Version>
|
|
73
|
+
<DeleteMarker>
|
|
74
|
+
<Key>${deletedKey}</Key>
|
|
75
|
+
<VersionId>delete-marker-1</VersionId>
|
|
76
|
+
<IsLatest>true</IsLatest>
|
|
77
|
+
<LastModified>2023-10-10T17:50:00.000Z</LastModified>
|
|
78
|
+
</DeleteMarker>
|
|
79
|
+
</ListVersionsResult>`));
|
|
80
|
+
}
|
|
81
|
+
return res(ctx.status(200));
|
|
82
|
+
});
|
|
83
|
+
export { listObjectVersionsHandler };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const listObjectsHandler: import("msw").RestHandler<import("msw").MockedRequest<import("msw").DefaultRequestBody>>;
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { rest } from "msw";
|
|
2
|
+
import { createS3ErrorXml, getS3BaseUrl } from "../utils.js";
|
|
3
|
+
const listObjectsHandler = rest.get(`${getS3BaseUrl()}/:bucketName`, (req, res, ctx)=>{
|
|
4
|
+
const { bucketName } = req.params;
|
|
5
|
+
const url = new URL(req.url);
|
|
6
|
+
if ("2" !== url.searchParams.get("list-type")) return;
|
|
7
|
+
const prefix = url.searchParams.get("prefix") || "";
|
|
8
|
+
const delimiter = url.searchParams.get("delimiter") || "";
|
|
9
|
+
const maxKeys = parseInt(url.searchParams.get("max-keys") || "1000", 10);
|
|
10
|
+
const continuationToken = url.searchParams.get("continuation-token");
|
|
11
|
+
if ("string" == typeof bucketName) {
|
|
12
|
+
if (bucketName.includes("non-existent-bucket")) return res(ctx.status(404), ctx.xml(createS3ErrorXml("NoSuchBucket", "The specified bucket does not exist", bucketName)));
|
|
13
|
+
if (bucketName.includes("access-denied-bucket")) return res(ctx.status(403), ctx.xml(createS3ErrorXml("AccessDenied", "Access Denied")));
|
|
14
|
+
if (bucketName.includes("network-error-bucket")) return res.networkError("Failed to connect");
|
|
15
|
+
if (bucketName.includes("empty-bucket")) return res(ctx.status(200), ctx.xml(`<?xml version="1.0" encoding="UTF-8"?>
|
|
16
|
+
<ListBucketResult xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
|
|
17
|
+
<Name>${bucketName}</Name>
|
|
18
|
+
<Prefix>${prefix}</Prefix>
|
|
19
|
+
<Delimiter>${delimiter}</Delimiter>
|
|
20
|
+
<MaxKeys>${maxKeys}</MaxKeys>
|
|
21
|
+
<IsTruncated>false</IsTruncated>
|
|
22
|
+
</ListBucketResult>`));
|
|
23
|
+
if (continuationToken) return res(ctx.status(200), ctx.xml(`<?xml version="1.0" encoding="UTF-8"?>
|
|
24
|
+
<ListBucketResult xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
|
|
25
|
+
<Name>${bucketName}</Name>
|
|
26
|
+
<Prefix>${prefix}</Prefix>
|
|
27
|
+
<Delimiter>${delimiter}</Delimiter>
|
|
28
|
+
<MaxKeys>${maxKeys}</MaxKeys>
|
|
29
|
+
<IsTruncated>false</IsTruncated>
|
|
30
|
+
<Contents>
|
|
31
|
+
<Key>${prefix}file3.txt</Key>
|
|
32
|
+
<LastModified>2023-10-12T17:50:00.000Z</LastModified>
|
|
33
|
+
<ETag>"d41d8cd98f00b204e9800998ecf8427e"</ETag>
|
|
34
|
+
<Size>2048</Size>
|
|
35
|
+
<StorageClass>STANDARD</StorageClass>
|
|
36
|
+
</Contents>
|
|
37
|
+
</ListBucketResult>`));
|
|
38
|
+
const hasMorePages = bucketName.includes("paginated-bucket");
|
|
39
|
+
return res(ctx.status(200), ctx.xml(`<?xml version="1.0" encoding="UTF-8"?>
|
|
40
|
+
<ListBucketResult xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
|
|
41
|
+
<Name>${bucketName}</Name>
|
|
42
|
+
<Prefix>${prefix}</Prefix>
|
|
43
|
+
<Delimiter>${delimiter}</Delimiter>
|
|
44
|
+
<MaxKeys>${maxKeys}</MaxKeys>
|
|
45
|
+
<IsTruncated>${hasMorePages}</IsTruncated>
|
|
46
|
+
${hasMorePages ? "<NextContinuationToken>token-123</NextContinuationToken>" : ""}
|
|
47
|
+
<Contents>
|
|
48
|
+
<Key>${prefix}file1.txt</Key>
|
|
49
|
+
<LastModified>2023-10-12T17:50:00.000Z</LastModified>
|
|
50
|
+
<ETag>"d41d8cd98f00b204e9800998ecf8427e"</ETag>
|
|
51
|
+
<Size>1024</Size>
|
|
52
|
+
<StorageClass>STANDARD</StorageClass>
|
|
53
|
+
</Contents>
|
|
54
|
+
<Contents>
|
|
55
|
+
<Key>${prefix}file2.txt</Key>
|
|
56
|
+
<LastModified>2023-10-12T17:50:00.000Z</LastModified>
|
|
57
|
+
<ETag>"e58ed763928cf52221fa5c4e2d6422a"</ETag>
|
|
58
|
+
<Size>512</Size>
|
|
59
|
+
<StorageClass>STANDARD</StorageClass>
|
|
60
|
+
</Contents>
|
|
61
|
+
${delimiter ? `<CommonPrefixes><Prefix>${prefix}folder1/</Prefix></CommonPrefixes>` : ""}
|
|
62
|
+
</ListBucketResult>`));
|
|
63
|
+
}
|
|
64
|
+
return res(ctx.status(200));
|
|
65
|
+
});
|
|
66
|
+
export { listObjectsHandler };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const getObjectLegalHoldHandler: import("msw").RestHandler<import("msw").MockedRequest<import("msw").DefaultRequestBody>>;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { rest } from "msw";
|
|
2
|
+
import { createS3ErrorXml, getS3BaseUrl } from "../utils.js";
|
|
3
|
+
import { ObjectLockLegalHoldStatus } from "@aws-sdk/client-s3";
|
|
4
|
+
const getObjectLegalHoldHandler = rest.get(`${getS3BaseUrl()}/:bucketName/*`, (req, res, ctx)=>{
|
|
5
|
+
const { bucketName } = req.params;
|
|
6
|
+
const url = new URL(req.url);
|
|
7
|
+
const objectKey = url.pathname.substring(url.pathname.indexOf("/", 1) + 1);
|
|
8
|
+
if (!url.searchParams.has("legal-hold")) return;
|
|
9
|
+
if ("string" == typeof bucketName) {
|
|
10
|
+
if ("no-such-bucket" === bucketName || "non-existent-bucket" === bucketName) return res(ctx.status(404), ctx.xml(createS3ErrorXml("NoSuchBucket", "The specified bucket does not exist", bucketName)));
|
|
11
|
+
if ("access-denied-bucket" === bucketName || "restricted-bucket" === bucketName) return res(ctx.status(403), ctx.xml(createS3ErrorXml("AccessDenied", "Access Denied", bucketName, objectKey)));
|
|
12
|
+
if ("network-error-bucket" === bucketName) return res.networkError("Failed to connect");
|
|
13
|
+
if ("non-existent-object.txt" === objectKey) return res(ctx.status(404), ctx.xml(createS3ErrorXml("NoSuchKey", "The specified key does not exist.", bucketName, objectKey)));
|
|
14
|
+
if ("no-legal-hold-object.txt" === objectKey) return res(ctx.status(404), ctx.xml(createS3ErrorXml("NoSuchObjectLockConfiguration", "The specified object does not have a ObjectLock configuration", bucketName, objectKey)));
|
|
15
|
+
let status = ObjectLockLegalHoldStatus.ON;
|
|
16
|
+
if ("legal-hold-off-object.txt" === objectKey) status = ObjectLockLegalHoldStatus.OFF;
|
|
17
|
+
return res(ctx.status(200), ctx.set("Content-Type", "application/xml"), ctx.body(`<?xml version="1.0" encoding="UTF-8"?>
|
|
18
|
+
<LegalHold xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
|
|
19
|
+
<Status>${status}</Status>
|
|
20
|
+
</LegalHold>`));
|
|
21
|
+
}
|
|
22
|
+
return res(ctx.status(400), ctx.xml(createS3ErrorXml("InvalidArgument", "Invalid request parameters")));
|
|
23
|
+
});
|
|
24
|
+
export { getObjectLegalHoldHandler };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const getObjectRetentionHandler: import("msw").RestHandler<import("msw").MockedRequest<import("msw").DefaultRequestBody>>;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { rest } from "msw";
|
|
2
|
+
import { createS3ErrorXml, getS3BaseUrl } from "../utils.js";
|
|
3
|
+
const getObjectRetentionHandler = rest.get(`${getS3BaseUrl()}/:bucketName/*`, (req, res, ctx)=>{
|
|
4
|
+
const { bucketName } = req.params;
|
|
5
|
+
const url = new URL(req.url);
|
|
6
|
+
const objectKey = url.pathname.substring(url.pathname.indexOf("/", 1) + 1);
|
|
7
|
+
if (!url.searchParams.has("retention")) return;
|
|
8
|
+
if ("string" == typeof bucketName) {
|
|
9
|
+
if (bucketName.includes("non-existent-bucket")) return res(ctx.status(404), ctx.xml(createS3ErrorXml("NoSuchBucket", "The specified bucket does not exist", bucketName)));
|
|
10
|
+
if (objectKey.includes("non-existent-object")) return res(ctx.status(404), ctx.xml(createS3ErrorXml("NoSuchKey", "The specified key does not exist.", bucketName, objectKey)));
|
|
11
|
+
if (bucketName.includes("restricted-bucket")) return res(ctx.status(403), ctx.xml(createS3ErrorXml("AccessDenied", "Access Denied")));
|
|
12
|
+
if (objectKey.includes("no-retention-object")) return res(ctx.status(404), ctx.xml(createS3ErrorXml("NoSuchObjectLockConfiguration", "The specified object does not have a ObjectLock configuration", bucketName, objectKey)));
|
|
13
|
+
if (bucketName.includes("network-error-bucket")) return res.networkError("Failed to connect");
|
|
14
|
+
if (objectKey.includes("compliance-retention")) return res(ctx.status(200), ctx.xml(`<?xml version="1.0" encoding="UTF-8"?>
|
|
15
|
+
<Retention xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
|
|
16
|
+
<Mode>COMPLIANCE</Mode>
|
|
17
|
+
<RetainUntilDate>2024-12-31T23:59:59.000Z</RetainUntilDate>
|
|
18
|
+
</Retention>`));
|
|
19
|
+
return res(ctx.status(200), ctx.xml(`<?xml version="1.0" encoding="UTF-8"?>
|
|
20
|
+
<Retention xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
|
|
21
|
+
<Mode>GOVERNANCE</Mode>
|
|
22
|
+
<RetainUntilDate>2024-06-30T23:59:59.000Z</RetainUntilDate>
|
|
23
|
+
</Retention>`));
|
|
24
|
+
}
|
|
25
|
+
return res(ctx.status(400), ctx.xml(createS3ErrorXml("InvalidArgument", "Invalid request parameters")));
|
|
26
|
+
});
|
|
27
|
+
export { getObjectRetentionHandler };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const putBucketAclHandler: import("msw").RestHandler<import("msw").MockedRequest<import("msw").DefaultRequestBody>>;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { rest } from "msw";
|
|
2
|
+
import { createS3ErrorXml, getS3BaseUrl } from "../utils.js";
|
|
3
|
+
const putBucketAclHandler = rest.put(`${getS3BaseUrl()}/:bucketName`, (req, res, ctx)=>{
|
|
4
|
+
const { bucketName } = req.params;
|
|
5
|
+
const url = new URL(req.url);
|
|
6
|
+
if (!url.searchParams.has("acl")) return;
|
|
7
|
+
if ("string" == typeof bucketName) {
|
|
8
|
+
if (bucketName.includes("non-existent-bucket")) return res(ctx.status(404), ctx.xml(createS3ErrorXml("NoSuchBucket", "The specified bucket does not exist", bucketName)));
|
|
9
|
+
if (bucketName.includes("access-denied-bucket")) return res(ctx.status(403), ctx.xml(createS3ErrorXml("AccessDenied", "Access Denied")));
|
|
10
|
+
if (bucketName.includes("invalid-acl-bucket")) return res(ctx.status(400), ctx.xml(createS3ErrorXml("InvalidRequest", "The ACL configuration is invalid")));
|
|
11
|
+
if (bucketName.includes("malformed-acl-bucket")) return res(ctx.status(400), ctx.xml(createS3ErrorXml("MalformedACLError", "The XML provided does not match the expected format")));
|
|
12
|
+
if (bucketName.includes("network-error-bucket")) return res.networkError("Failed to connect");
|
|
13
|
+
const aclParam = url.searchParams.get("acl");
|
|
14
|
+
if ("invalid-acl-type" === aclParam) return res(ctx.status(400), ctx.xml(createS3ErrorXml("InvalidArgument", "Invalid canned ACL value")));
|
|
15
|
+
}
|
|
16
|
+
return res(ctx.status(200), ctx.set("Content-Type", "application/xml"), ctx.body(""));
|
|
17
|
+
});
|
|
18
|
+
export { putBucketAclHandler };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const putObjectHandler: import("msw").RestHandler<import("msw").MockedRequest<import("msw").DefaultRequestBody>>;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { rest } from "msw";
|
|
2
|
+
import { createS3ErrorXml, getS3BaseUrl } from "../utils.js";
|
|
3
|
+
const putObjectHandler = rest.put(`${getS3BaseUrl()}/:bucketName/*`, (req, res, ctx)=>{
|
|
4
|
+
const { bucketName } = req.params;
|
|
5
|
+
const url = new URL(req.url);
|
|
6
|
+
const objectKey = url.pathname.substring(url.pathname.indexOf("/", 1) + 1);
|
|
7
|
+
if ("string" == typeof bucketName) {
|
|
8
|
+
if (bucketName.includes("non-existent-bucket")) return res(ctx.status(404), ctx.xml(createS3ErrorXml("NoSuchBucket", "The specified bucket does not exist", bucketName)));
|
|
9
|
+
if (bucketName.includes("access-denied-bucket")) return res(ctx.status(403), ctx.xml(createS3ErrorXml("AccessDenied", "Access Denied")));
|
|
10
|
+
if (bucketName.includes("network-error-bucket")) return res.networkError("Failed to connect");
|
|
11
|
+
if (objectKey.includes("invalid-key")) return res(ctx.status(400), ctx.xml(createS3ErrorXml("InvalidRequest", "The specified key is not valid")));
|
|
12
|
+
return res(ctx.status(200), ctx.set("ETag", '"mock-etag-123"'), ctx.set("x-amz-version-id", "mock-version-id"), ctx.set("x-amz-server-side-encryption", "AES256"), ctx.body(""));
|
|
13
|
+
}
|
|
14
|
+
return res(ctx.status(400), ctx.xml(createS3ErrorXml("InvalidArgument", "Invalid request parameters")));
|
|
15
|
+
});
|
|
16
|
+
export { putObjectHandler };
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export declare const createBucketHandler: import("msw").RestHandler<import("msw").MockedRequest<import("msw").DefaultRequestBody>>;
|
|
2
|
+
export declare const getBucketVersioningHandler: import("msw").RestHandler<import("msw").MockedRequest<import("msw").DefaultRequestBody>>;
|
|
3
|
+
export declare const s3Handlers: import("msw").RestHandler<import("msw").MockedRequest<import("msw").DefaultRequestBody>>[];
|
|
4
|
+
export default s3Handlers;
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import { rest } from "msw";
|
|
2
|
+
import { listBucketsHandler } from "./handlers/listBuckets.js";
|
|
3
|
+
import { deleteBucketHandler } from "./handlers/deleteBucket.js";
|
|
4
|
+
import { getBucketLocationHandler } from "./handlers/getBucketLocation.js";
|
|
5
|
+
import { getBucketAclHandler } from "./handlers/getBucketAcl.js";
|
|
6
|
+
import { getBucketPolicyHandler } from "./handlers/getBucketPolicy.js";
|
|
7
|
+
import { listObjectsHandler } from "./handlers/listObjects.js";
|
|
8
|
+
import { listObjectVersionsHandler } from "./handlers/listObjectVersions.js";
|
|
9
|
+
import { headObjectHandler } from "./handlers/headObject.js";
|
|
10
|
+
import { getObjectRetentionHandler } from "./handlers/objectRetention.js";
|
|
11
|
+
import { getObjectLegalHoldHandler } from "./handlers/objectLegalHold.js";
|
|
12
|
+
import { putObjectHandler } from "./handlers/putObject.js";
|
|
13
|
+
import { putBucketAclHandler } from "./handlers/putBucketAcl.js";
|
|
14
|
+
import { createS3ErrorXml, getS3BaseUrl } from "./utils.js";
|
|
15
|
+
const isBucketConfigurationRequest = (url)=>{
|
|
16
|
+
const configParams = [
|
|
17
|
+
"acl",
|
|
18
|
+
"policy",
|
|
19
|
+
"versioning",
|
|
20
|
+
"lifecycle",
|
|
21
|
+
"cors",
|
|
22
|
+
"website",
|
|
23
|
+
"tagging",
|
|
24
|
+
"encryption",
|
|
25
|
+
"notification",
|
|
26
|
+
"replication",
|
|
27
|
+
"requestPayment",
|
|
28
|
+
"accelerate",
|
|
29
|
+
"metrics",
|
|
30
|
+
"inventory",
|
|
31
|
+
"analytics",
|
|
32
|
+
"intelligentTiering",
|
|
33
|
+
"ownershipControls",
|
|
34
|
+
"publicAccessBlock",
|
|
35
|
+
"logging",
|
|
36
|
+
"location"
|
|
37
|
+
];
|
|
38
|
+
return configParams.some((param)=>url.searchParams.has(param));
|
|
39
|
+
};
|
|
40
|
+
const createBucketHandler = rest.put(`${getS3BaseUrl()}/:bucketName`, (req, res, ctx)=>{
|
|
41
|
+
const { bucketName } = req.params;
|
|
42
|
+
const url = new URL(req.url);
|
|
43
|
+
if (isBucketConfigurationRequest(url)) return;
|
|
44
|
+
if ("string" == typeof bucketName) {
|
|
45
|
+
if (bucketName.includes("existing-bucket")) return res(ctx.status(409), ctx.xml(createS3ErrorXml("BucketAlreadyExists", "The requested bucket name is not available", bucketName)));
|
|
46
|
+
if (bucketName.includes("restricted-bucket")) return res(ctx.status(403), ctx.xml(createS3ErrorXml("AccessDenied", "Access Denied")));
|
|
47
|
+
if (bucketName.includes("invalid-bucket-name")) return res(ctx.status(400), ctx.xml(createS3ErrorXml("InvalidBucketName", "Invalid bucket name")));
|
|
48
|
+
if (bucketName.includes("network-test-bucket")) return res.networkError("Network connection failed");
|
|
49
|
+
}
|
|
50
|
+
return res(ctx.status(200), ctx.set("Location", `/${bucketName}`), ctx.xml(`<?xml version="1.0" encoding="UTF-8"?>
|
|
51
|
+
<CreateBucketResult xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
|
|
52
|
+
<Location>/${bucketName}</Location>
|
|
53
|
+
</CreateBucketResult>`));
|
|
54
|
+
});
|
|
55
|
+
const getBucketVersioningHandler = rest.get(`${getS3BaseUrl()}/:bucketName`, (req, res, ctx)=>{
|
|
56
|
+
const { bucketName } = req.params;
|
|
57
|
+
const url = new URL(req.url);
|
|
58
|
+
if (!url.searchParams.has("versioning")) return;
|
|
59
|
+
if ("string" == typeof bucketName) {
|
|
60
|
+
if (bucketName.includes("nonexistent-bucket")) return res(ctx.status(404), ctx.xml(`<?xml version="1.0" encoding="UTF-8"?>
|
|
61
|
+
<Error>
|
|
62
|
+
<Code>NoSuchBucket</Code>
|
|
63
|
+
<Message>The specified bucket does not exist</Message>
|
|
64
|
+
<BucketName>${bucketName}</BucketName>
|
|
65
|
+
</Error>`));
|
|
66
|
+
if (bucketName.includes("access-denied-bucket")) return res(ctx.status(403), ctx.xml(`<?xml version="1.0" encoding="UTF-8"?>
|
|
67
|
+
<Error>
|
|
68
|
+
<Code>AccessDenied</Code>
|
|
69
|
+
<Message>Access Denied</Message>
|
|
70
|
+
</Error>`));
|
|
71
|
+
if (bucketName.includes("network-error-bucket")) return res.networkError("Network connection failed");
|
|
72
|
+
if (bucketName.includes("enabled-versioning-bucket")) return res(ctx.status(200), ctx.xml(`<?xml version="1.0" encoding="UTF-8"?>
|
|
73
|
+
<VersioningConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
|
|
74
|
+
<Status>Enabled</Status>
|
|
75
|
+
<MfaDelete>Disabled</MfaDelete>
|
|
76
|
+
</VersioningConfiguration>`));
|
|
77
|
+
if (bucketName.includes("suspended-versioning-bucket")) return res(ctx.status(200), ctx.xml(`<?xml version="1.0" encoding="UTF-8"?>
|
|
78
|
+
<VersioningConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
|
|
79
|
+
<Status>Suspended</Status>
|
|
80
|
+
<MfaDelete>Disabled</MfaDelete>
|
|
81
|
+
</VersioningConfiguration>`));
|
|
82
|
+
if (bucketName.includes("mfa-enabled-bucket")) return res(ctx.status(200), ctx.xml(`<?xml version="1.0" encoding="UTF-8"?>
|
|
83
|
+
<VersioningConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
|
|
84
|
+
<Status>Enabled</Status>
|
|
85
|
+
<MfaDelete>Enabled</MfaDelete>
|
|
86
|
+
</VersioningConfiguration>`));
|
|
87
|
+
}
|
|
88
|
+
return res(ctx.status(200), ctx.xml(`<?xml version="1.0" encoding="UTF-8"?>
|
|
89
|
+
<VersioningConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
|
|
90
|
+
</VersioningConfiguration>`));
|
|
91
|
+
});
|
|
92
|
+
const s3Handlers = [
|
|
93
|
+
listBucketsHandler,
|
|
94
|
+
createBucketHandler,
|
|
95
|
+
deleteBucketHandler,
|
|
96
|
+
getBucketVersioningHandler,
|
|
97
|
+
getBucketLocationHandler,
|
|
98
|
+
getBucketAclHandler,
|
|
99
|
+
getBucketPolicyHandler,
|
|
100
|
+
listObjectsHandler,
|
|
101
|
+
listObjectVersionsHandler,
|
|
102
|
+
getObjectRetentionHandler,
|
|
103
|
+
getObjectLegalHoldHandler,
|
|
104
|
+
putObjectHandler,
|
|
105
|
+
headObjectHandler,
|
|
106
|
+
putBucketAclHandler
|
|
107
|
+
];
|
|
108
|
+
const handlers = s3Handlers;
|
|
109
|
+
export { createBucketHandler, handlers as default, getBucketVersioningHandler, s3Handlers };
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import { overrideHandlers, server, setupMswServer } from "./server.js";
|
|
2
|
+
import { createBucketHandler, getBucketVersioningHandler, s3Handlers } from "./handlers.js";
|
|
3
|
+
export { createBucketHandler, getBucketVersioningHandler, overrideHandlers, s3Handlers, server, setupMswServer };
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { setupServer } from "msw/node";
|
|
2
|
+
import { s3Handlers } from "./handlers.js";
|
|
3
|
+
const server = setupServer(...s3Handlers);
|
|
4
|
+
const setupMswServer = ()=>{
|
|
5
|
+
beforeAll(()=>{
|
|
6
|
+
server.listen({
|
|
7
|
+
onUnhandledRequest: "warn"
|
|
8
|
+
});
|
|
9
|
+
});
|
|
10
|
+
afterEach(()=>{
|
|
11
|
+
server.resetHandlers();
|
|
12
|
+
});
|
|
13
|
+
afterAll(()=>{
|
|
14
|
+
server.close();
|
|
15
|
+
});
|
|
16
|
+
};
|
|
17
|
+
const overrideHandlers = (...handlers)=>{
|
|
18
|
+
server.use(...handlers);
|
|
19
|
+
};
|
|
20
|
+
export { overrideHandlers, s3Handlers, server, setupMswServer };
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
const getS3BaseUrl = ()=>"https://s3.amazonaws.com";
|
|
2
|
+
const createS3ErrorXml = (code, message, bucketName, key)=>{
|
|
3
|
+
let resourceDetails = "";
|
|
4
|
+
if (bucketName) resourceDetails += `<BucketName>${bucketName}</BucketName>`;
|
|
5
|
+
if (key) resourceDetails += `<Key>${key}</Key>`;
|
|
6
|
+
return `<?xml version="1.0" encoding="UTF-8"?>
|
|
7
|
+
<Error>
|
|
8
|
+
<Code>${code}</Code>
|
|
9
|
+
<Message>${message}</Message>
|
|
10
|
+
${resourceDetails}
|
|
11
|
+
</Error>`;
|
|
12
|
+
};
|
|
13
|
+
export { createS3ErrorXml, getS3BaseUrl };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import "@testing-library/jest-dom";
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import "@testing-library/jest-dom";
|
|
2
|
+
import { TextDecoder, TextEncoder } from "util";
|
|
3
|
+
var __webpack_require__ = {};
|
|
4
|
+
(()=>{
|
|
5
|
+
__webpack_require__.g = (()=>{
|
|
6
|
+
if ('object' == typeof globalThis) return globalThis;
|
|
7
|
+
try {
|
|
8
|
+
return this || new Function('return this')();
|
|
9
|
+
} catch (e) {
|
|
10
|
+
if ('object' == typeof window) return window;
|
|
11
|
+
}
|
|
12
|
+
})();
|
|
13
|
+
})();
|
|
14
|
+
process.env.AWS_ACCESS_KEY_ID = "test-access-key";
|
|
15
|
+
process.env.AWS_SECRET_ACCESS_KEY = "test-secret-key";
|
|
16
|
+
process.env.AWS_DEFAULT_REGION = "us-east-1";
|
|
17
|
+
const testS3Config = {
|
|
18
|
+
endpoint: "http://localhost:8000",
|
|
19
|
+
region: "us-east-1",
|
|
20
|
+
realHost: "s3.amazonaws.com",
|
|
21
|
+
forcePathStyle: true
|
|
22
|
+
};
|
|
23
|
+
const testDevConfig = {
|
|
24
|
+
useProxy: false,
|
|
25
|
+
proxyEndpoint: "http://localhost:3000/api/s3",
|
|
26
|
+
proxyBasePath: "/api/s3",
|
|
27
|
+
proxyHost: "localhost",
|
|
28
|
+
proxyPort: 3000
|
|
29
|
+
};
|
|
30
|
+
globalThis.__S3_CONFIG__ = testS3Config;
|
|
31
|
+
globalThis.__DEV_CONFIG__ = testDevConfig;
|
|
32
|
+
globalThis.__IS_DEVELOPMENT__ = true;
|
|
33
|
+
globalThis.__IS_PRODUCTION__ = false;
|
|
34
|
+
jest.setTimeout(10000);
|
|
35
|
+
Object.assign(__webpack_require__.g, {
|
|
36
|
+
TextDecoder: TextDecoder,
|
|
37
|
+
TextEncoder: TextEncoder
|
|
38
|
+
});
|
|
39
|
+
Object.defineProperty(HTMLCanvasElement.prototype, "getContext", {
|
|
40
|
+
value: ()=>null
|
|
41
|
+
});
|
|
42
|
+
jest.mock("pretty-bytes", ()=>({
|
|
43
|
+
__esModule: true,
|
|
44
|
+
default: (bytes)=>{
|
|
45
|
+
const sizes = [
|
|
46
|
+
"B",
|
|
47
|
+
"KB",
|
|
48
|
+
"MB",
|
|
49
|
+
"GB"
|
|
50
|
+
];
|
|
51
|
+
let i = 0;
|
|
52
|
+
let num = bytes;
|
|
53
|
+
while(num >= 1024 && i < sizes.length - 1){
|
|
54
|
+
num /= 1024;
|
|
55
|
+
i++;
|
|
56
|
+
}
|
|
57
|
+
return `${Math.round(num)} ${sizes[i]}`;
|
|
58
|
+
}
|
|
59
|
+
}));
|
|
60
|
+
if (!File.prototype.arrayBuffer) File.prototype.arrayBuffer = function() {
|
|
61
|
+
return new Promise((resolve)=>{
|
|
62
|
+
const reader = new FileReader();
|
|
63
|
+
reader.onload = ()=>resolve(reader.result);
|
|
64
|
+
reader.readAsArrayBuffer(this);
|
|
65
|
+
});
|
|
66
|
+
};
|
|
67
|
+
const originalError = console.error;
|
|
68
|
+
const originalWarn = console.warn;
|
|
69
|
+
beforeAll(()=>{
|
|
70
|
+
console.error = (...args)=>{
|
|
71
|
+
if ("string" == typeof args[0] && (args[0].includes("AWS") || args[0].includes("S3") || args[0].includes("Warning: An update to") || args[0].includes('Warning: A props object containing a "key" prop'))) return;
|
|
72
|
+
originalError(...args);
|
|
73
|
+
};
|
|
74
|
+
console.warn = (...args)=>{
|
|
75
|
+
if ("string" == typeof args[0] && (args[0].includes("AWS") || args[0].includes("S3") || args[0].includes("Warning: An update to") || args[0].includes('Warning: A props object containing a "key" prop'))) return;
|
|
76
|
+
originalWarn(...args);
|
|
77
|
+
};
|
|
78
|
+
});
|
|
79
|
+
afterAll(()=>{
|
|
80
|
+
console.error = originalError;
|
|
81
|
+
console.warn = originalWarn;
|
|
82
|
+
});
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { S3Client, PutObjectCommand } from "@aws-sdk/client-s3";
|
|
2
|
+
import React from "react";
|
|
3
|
+
import { S3BrowserConfig, S3Credentials } from "../types";
|
|
4
|
+
export declare const testConfig: S3BrowserConfig;
|
|
5
|
+
export declare const testCredentials: S3Credentials;
|
|
6
|
+
export declare const mockS3Client: {
|
|
7
|
+
send: jest.Mock<any, any, any>;
|
|
8
|
+
};
|
|
9
|
+
export declare const MockedS3Client: jest.MockedClass<typeof S3Client>;
|
|
10
|
+
export declare const MockedPutObjectCommand: jest.MockedClass<typeof PutObjectCommand>;
|
|
11
|
+
export declare function mockOffsetSize(width: number, height: number): void;
|
|
12
|
+
/**
|
|
13
|
+
* Creates a simple QueryClient wrapper for tests that don't need DataBrowser context
|
|
14
|
+
*/
|
|
15
|
+
export declare const createQueryWrapper: () => ({ children }: {
|
|
16
|
+
children: React.ReactNode;
|
|
17
|
+
}) => import("react/jsx-runtime").JSX.Element;
|
|
18
|
+
/**
|
|
19
|
+
* Creates a test wrapper with DataBrowser context and QueryClient
|
|
20
|
+
*/
|
|
21
|
+
export declare const createTestWrapper: (config?: S3BrowserConfig, credentials?: S3Credentials) => ({ children }: {
|
|
22
|
+
children: React.ReactNode;
|
|
23
|
+
}) => import("react/jsx-runtime").JSX.Element;
|
|
24
|
+
/**
|
|
25
|
+
* Renders a hook with the standard test wrapper
|
|
26
|
+
*/
|
|
27
|
+
export declare const renderHookWithWrapper: <TProps, TResult>(hook: (props: TProps) => TResult, options?: {
|
|
28
|
+
initialProps?: TProps;
|
|
29
|
+
config?: S3BrowserConfig;
|
|
30
|
+
credentials?: S3Credentials;
|
|
31
|
+
}) => import("@testing-library/react").RenderHookResult<TResult, TProps>;
|
|
32
|
+
/**
|
|
33
|
+
* Creates a test File object
|
|
34
|
+
*/
|
|
35
|
+
export declare const createTestFile: (name: string, content: string, type?: string) => File;
|
|
36
|
+
/**
|
|
37
|
+
* Sets up S3 mocks for testing
|
|
38
|
+
*/
|
|
39
|
+
export declare const setupS3Mocks: () => void;
|
|
40
|
+
/**
|
|
41
|
+
* Common mock setup that should be run before each test
|
|
42
|
+
*/
|
|
43
|
+
export declare const setupCommonMocks: () => void;
|
|
44
|
+
/**
|
|
45
|
+
* Configuration test utilities for overriding build-time globals
|
|
46
|
+
*/
|
|
47
|
+
import type { S3Configuration, DevelopmentConfiguration } from "../config/types";
|
|
48
|
+
type GlobalConfigOverrides = {
|
|
49
|
+
s3?: Partial<S3Configuration>;
|
|
50
|
+
dev?: Partial<DevelopmentConfiguration>;
|
|
51
|
+
environment?: {
|
|
52
|
+
isDevelopment?: boolean;
|
|
53
|
+
isProduction?: boolean;
|
|
54
|
+
};
|
|
55
|
+
};
|
|
56
|
+
/**
|
|
57
|
+
* Override global configuration for testing specific scenarios
|
|
58
|
+
* Useful for testing different deployment environments or proxy configurations
|
|
59
|
+
*/
|
|
60
|
+
export declare const overrideGlobalConfig: (overrides: GlobalConfigOverrides) => void;
|
|
61
|
+
/**
|
|
62
|
+
* Reset global configuration to test defaults
|
|
63
|
+
* Should be called in afterEach or afterAll to ensure test isolation
|
|
64
|
+
*/
|
|
65
|
+
export declare const resetGlobalConfig: () => void;
|
|
66
|
+
/**
|
|
67
|
+
* Test helper for running tests with specific global configuration
|
|
68
|
+
*/
|
|
69
|
+
export declare const withGlobalConfig: (overrides: GlobalConfigOverrides, testFn: () => void | Promise<void>) => () => Promise<void>;
|
|
70
|
+
/**
|
|
71
|
+
* Validates that a hook follows the expected factory pattern
|
|
72
|
+
*/
|
|
73
|
+
export declare const validateFactoryHook: (hook: any, operationName: string) => void;
|
|
74
|
+
/**
|
|
75
|
+
* Creates a factory test error
|
|
76
|
+
*/
|
|
77
|
+
export declare const createFactoryTestError: (testContext: string, operationName: string, details?: string) => Error;
|
|
78
|
+
/**
|
|
79
|
+
* Validates that a hook result has expected React Query properties
|
|
80
|
+
*/
|
|
81
|
+
export declare const validateHookResult: (result: any, hookType: "query" | "mutation" | "infiniteQuery") => void;
|
|
82
|
+
export { setupMswServer, overrideHandlers } from "./msw";
|