Revert "deprecate embedded browser (#12163)"

This reverts commit 736d8cbac4.

Bring contrib files for older contributions
This commit is contained in:
Harshavardhana
2021-04-29 19:01:43 -07:00
parent 64f6020854
commit f7a87b30bf
300 changed files with 38540 additions and 1172 deletions

View File

@@ -0,0 +1,45 @@
/*
* MinIO Object Storage (c) 2021 MinIO, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import React from "react"
import { shallow } from "enzyme"
import { DeleteObjectConfirmModal } from "../DeleteObjectConfirmModal"
describe("DeleteObjectConfirmModal", () => {
it("should render without crashing", () => {
shallow(<DeleteObjectConfirmModal />)
})
it("should call deleteObject when Delete is clicked", () => {
const deleteObject = jest.fn()
const wrapper = shallow(
<DeleteObjectConfirmModal deleteObject={deleteObject} />
)
wrapper.find("ConfirmModal").prop("okHandler")()
expect(deleteObject).toHaveBeenCalled()
})
it("should call hideDeleteConfirmModal when Cancel is clicked", () => {
const hideDeleteConfirmModal = jest.fn()
const wrapper = shallow(
<DeleteObjectConfirmModal
hideDeleteConfirmModal={hideDeleteConfirmModal}
/>
)
wrapper.find("ConfirmModal").prop("cancelHandler")()
expect(hideDeleteConfirmModal).toHaveBeenCalled()
})
})

View File

@@ -0,0 +1,165 @@
/*
* MinIO Object Storage (c) 2021 MinIO, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import React from "react"
import { shallow } from "enzyme"
import { ObjectActions } from "../ObjectActions"
describe("ObjectActions", () => {
it("should render without crashing", () => {
shallow(<ObjectActions object={{ name: "obj1" }} currentPrefix={"pre1/"} />)
})
it("should show DeleteObjectConfirmModal when delete action is clicked", () => {
const wrapper = shallow(
<ObjectActions object={{ name: "obj1" }} currentPrefix={"pre1/"} />
)
wrapper
.find("a")
.last()
.simulate("click", { preventDefault: jest.fn() })
expect(wrapper.state("showDeleteConfirmation")).toBeTruthy()
expect(wrapper.find("DeleteObjectConfirmModal").length).toBe(1)
})
it("should hide DeleteObjectConfirmModal when Cancel button is clicked", () => {
const wrapper = shallow(
<ObjectActions object={{ name: "obj1" }} currentPrefix={"pre1/"} />
)
wrapper
.find("a")
.last()
.simulate("click", { preventDefault: jest.fn() })
wrapper.find("DeleteObjectConfirmModal").prop("hideDeleteConfirmModal")()
wrapper.update()
expect(wrapper.state("showDeleteConfirmation")).toBeFalsy()
expect(wrapper.find("DeleteObjectConfirmModal").length).toBe(0)
})
it("should call deleteObject with object name", () => {
const deleteObject = jest.fn()
const wrapper = shallow(
<ObjectActions
object={{ name: "obj1" }}
currentPrefix={"pre1/"}
deleteObject={deleteObject}
/>
)
wrapper
.find("a")
.last()
.simulate("click", { preventDefault: jest.fn() })
wrapper.find("DeleteObjectConfirmModal").prop("deleteObject")()
expect(deleteObject).toHaveBeenCalledWith("obj1")
})
it("should call downloadObject when single object is selected and download button is clicked", () => {
const downloadObject = jest.fn()
const wrapper = shallow(
<ObjectActions
object={{ name: "obj1" }}
currentPrefix={"pre1/"}
downloadObject={downloadObject} />
)
wrapper
.find("a")
.at(1)
.simulate("click", { preventDefault: jest.fn() })
expect(downloadObject).toHaveBeenCalled()
})
it("should show PreviewObjectModal when preview action is clicked", () => {
const wrapper = shallow(
<ObjectActions
object={{ name: "obj1", contentType: "image/jpeg"}}
currentPrefix={"pre1/"} />
)
wrapper
.find("a")
.at(1)
.simulate("click", { preventDefault: jest.fn() })
expect(wrapper.state("showPreview")).toBeTruthy()
expect(wrapper.find("PreviewObjectModal").length).toBe(1)
})
it("should hide PreviewObjectModal when cancel button is clicked", () => {
const wrapper = shallow(
<ObjectActions
object={{ name: "obj1" , contentType: "image/jpeg"}}
currentPrefix={"pre1/"} />
)
wrapper
.find("a")
.at(1)
.simulate("click", { preventDefault: jest.fn() })
wrapper.find("PreviewObjectModal").prop("hidePreviewModal")()
wrapper.update()
expect(wrapper.state("showPreview")).toBeFalsy()
expect(wrapper.find("PreviewObjectModal").length).toBe(0)
})
it("should not show PreviewObjectModal when preview action is clicked if object is not an image", () => {
const wrapper = shallow(
<ObjectActions
object={{ name: "obj1"}}
currentPrefix={"pre1/"} />
)
expect(wrapper
.find("a")
.length).toBe(3) // find only the other 2
})
it("should call shareObject with object and expiry", () => {
const shareObject = jest.fn()
const wrapper = shallow(
<ObjectActions
object={{ name: "obj1" }}
currentPrefix={"pre1/"}
shareObject={shareObject}
/>
)
wrapper
.find("a")
.first()
.simulate("click", { preventDefault: jest.fn() })
expect(shareObject).toHaveBeenCalledWith("obj1", 5, 0, 0)
})
it("should render ShareObjectModal when an object is shared", () => {
const wrapper = shallow(
<ObjectActions
object={{ name: "obj1" }}
currentPrefix={"pre1/"}
showShareObjectModal={true}
shareObjectName={"obj1"}
/>
)
expect(wrapper.find("Connect(ShareObjectModal)").length).toBe(1)
})
it("shouldn't render ShareObjectModal when the names of the objects don't match", () => {
const wrapper = shallow(
<ObjectActions
object={{ name: "obj1" }}
currentPrefix={"pre1/"}
showShareObjectModal={true}
shareObjectName={"obj2"}
/>
)
expect(wrapper.find("Connect(ShareObjectModal)").length).toBe(0)
})
})

View File

@@ -0,0 +1,49 @@
/*
* MinIO Object Storage (c) 2021 MinIO, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import React from "react"
import { shallow } from "enzyme"
import { ObjectContainer } from "../ObjectContainer"
describe("ObjectContainer", () => {
it("should render without crashing", () => {
shallow(<ObjectContainer object={{ name: "test1.jpg" }} />)
})
it("should render ObjectItem with props", () => {
const wrapper = shallow(<ObjectContainer object={{ name: "test1.jpg" }} />)
expect(wrapper.find("Connect(ObjectItem)").length).toBe(1)
expect(wrapper.find("Connect(ObjectItem)").prop("name")).toBe("test1.jpg")
})
it("should pass actions to ObjectItem", () => {
const wrapper = shallow(
<ObjectContainer object={{ name: "test1.jpg" }} checkedObjectsCount={0} />
)
expect(wrapper.find("Connect(ObjectItem)").prop("actionButtons")).not.toBe(
undefined
)
})
it("should pass empty actions to ObjectItem when checkedObjectCount is more than 0", () => {
const wrapper = shallow(
<ObjectContainer object={{ name: "test1.jpg" }} checkedObjectsCount={1} />
)
expect(wrapper.find("Connect(ObjectItem)").prop("actionButtons")).toBe(
undefined
)
})
})

View File

@@ -0,0 +1,76 @@
/*
* MinIO Object Storage (c) 2021 MinIO, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import React from "react"
import { shallow } from "enzyme"
import { ObjectItem } from "../ObjectItem"
describe("ObjectItem", () => {
it("should render without crashing", () => {
shallow(<ObjectItem name={"test"} />)
})
it("should render with content type", () => {
const wrapper = shallow(<ObjectItem name={"test.jpg"} contentType={""} />)
expect(wrapper.prop("data-type")).toBe("image")
})
it("shouldn't call onClick when the object isclicked", () => {
const onClick = jest.fn()
const checkObject = jest.fn()
const wrapper = shallow(
<ObjectItem name={"test"} checkObject={checkObject} />
)
wrapper.find("a").simulate("click", { preventDefault: jest.fn() })
expect(onClick).not.toHaveBeenCalled()
})
it("should call onClick when the folder isclicked", () => {
const onClick = jest.fn()
const wrapper = shallow(<ObjectItem name={"test/"} onClick={onClick} />)
wrapper.find("a").simulate("click", { preventDefault: jest.fn() })
expect(onClick).toHaveBeenCalled()
})
it("should call checkObject when the object/prefix is checked", () => {
const checkObject = jest.fn()
const wrapper = shallow(
<ObjectItem name={"test"} checked={false} checkObject={checkObject} />
)
wrapper.find("input[type='checkbox']").simulate("change")
expect(checkObject).toHaveBeenCalledWith("test")
})
it("should render checked checkbox", () => {
const wrapper = shallow(<ObjectItem name={"test"} checked={true} />)
expect(wrapper.find("input[type='checkbox']").prop("checked")).toBeTruthy()
})
it("should call uncheckObject when the object/prefix is unchecked", () => {
const checkObject = jest.fn()
const uncheckObject = jest.fn()
const wrapper = shallow(
<ObjectItem
name={"test"}
checked={true}
checkObject={checkObject}
uncheckObject={uncheckObject}
/>
)
wrapper.find("input[type='checkbox']").simulate("change")
expect(uncheckObject).toHaveBeenCalledWith("test")
})
})

View File

@@ -0,0 +1,100 @@
/*
* MinIO Object Storage (c) 2021 MinIO, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import React from "react"
import { shallow } from "enzyme"
import { ObjectsBulkActions } from "../ObjectsBulkActions"
describe("ObjectsBulkActions", () => {
it("should render without crashing", () => {
shallow(<ObjectsBulkActions checkedObjects={[]} />)
})
it("should show actions when checkObjectsCount is more than 0", () => {
const wrapper = shallow(<ObjectsBulkActions checkedObjects={["test"]} />)
expect(wrapper.hasClass("list-actions-toggled")).toBeTruthy()
})
it("should call downloadObject when single object is selected and download button is clicked", () => {
const downloadObject = jest.fn()
const clearChecked = jest.fn()
const wrapper = shallow(
<ObjectsBulkActions
checkedObjects={["test"]}
downloadObject={downloadObject}
clearChecked={clearChecked}
/>
)
wrapper.find("#download-checked").simulate("click")
expect(downloadObject).toHaveBeenCalled()
})
it("should call downloadChecked when a folder is selected and download button is clicked", () => {
const downloadChecked = jest.fn()
const wrapper = shallow(
<ObjectsBulkActions
checkedObjects={["test/"]}
downloadChecked={downloadChecked}
/>
)
wrapper.find("#download-checked").simulate("click")
expect(downloadChecked).toHaveBeenCalled()
})
it("should call downloadChecked when multiple objects are selected and download button is clicked", () => {
const downloadChecked = jest.fn()
const wrapper = shallow(
<ObjectsBulkActions
checkedObjects={["test1", "test2"]}
downloadChecked={downloadChecked}
/>
)
wrapper.find("#download-checked").simulate("click")
expect(downloadChecked).toHaveBeenCalled()
})
it("should call clearChecked when close button is clicked", () => {
const clearChecked = jest.fn()
const wrapper = shallow(
<ObjectsBulkActions checkedObjects={["test"]} clearChecked={clearChecked} />
)
wrapper.find("#close-bulk-actions").simulate("click")
expect(clearChecked).toHaveBeenCalled()
})
it("shoud show DeleteObjectConfirmModal when delete-checked button is clicked", () => {
const wrapper = shallow(<ObjectsBulkActions checkedObjects={["test"]} />)
wrapper.find("#delete-checked").simulate("click")
wrapper.update()
expect(wrapper.find("DeleteObjectConfirmModal").length).toBe(1)
})
it("shoud call deleteChecked when Delete is clicked on confirmation modal", () => {
const deleteChecked = jest.fn()
const wrapper = shallow(
<ObjectsBulkActions
checkedObjects={["test"]}
deleteChecked={deleteChecked}
/>
)
wrapper.find("#delete-checked").simulate("click")
wrapper.update()
wrapper.find("DeleteObjectConfirmModal").prop("deleteObject")()
expect(deleteChecked).toHaveBeenCalled()
wrapper.update()
expect(wrapper.find("DeleteObjectConfirmModal").length).toBe(0)
})
})

View File

@@ -0,0 +1,122 @@
/*
* MinIO Object Storage (c) 2021 MinIO, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import React from "react"
import { shallow } from "enzyme"
import { ObjectsHeader } from "../ObjectsHeader"
import { SORT_ORDER_ASC, SORT_ORDER_DESC } from "../../constants"
describe("ObjectsHeader", () => {
it("should render without crashing", () => {
const sortObjects = jest.fn()
shallow(<ObjectsHeader sortObjects={sortObjects} />)
})
it("should render the name column with asc class when objects are sorted by name asc", () => {
const sortObjects = jest.fn()
const wrapper = shallow(
<ObjectsHeader
sortObjects={sortObjects}
sortedByName={true}
sortOrder={SORT_ORDER_ASC}
/>
)
expect(
wrapper.find("#sort-by-name i").hasClass("fa-sort-alpha-down")
).toBeTruthy()
})
it("should render the name column with desc class when objects are sorted by name desc", () => {
const sortObjects = jest.fn()
const wrapper = shallow(
<ObjectsHeader
sortObjects={sortObjects}
sortedByName={true}
sortOrder={SORT_ORDER_DESC}
/>
)
expect(
wrapper.find("#sort-by-name i").hasClass("fa-sort-alpha-down-alt")
).toBeTruthy()
})
it("should render the size column with asc class when objects are sorted by size asc", () => {
const sortObjects = jest.fn()
const wrapper = shallow(
<ObjectsHeader
sortObjects={sortObjects}
sortedBySize={true}
sortOrder={SORT_ORDER_ASC}
/>
)
expect(
wrapper.find("#sort-by-size i").hasClass("fa-sort-amount-down-alt")
).toBeTruthy()
})
it("should render the size column with desc class when objects are sorted by size desc", () => {
const sortObjects = jest.fn()
const wrapper = shallow(
<ObjectsHeader
sortObjects={sortObjects}
sortedBySize={true}
sortOrder={SORT_ORDER_DESC}
/>
)
expect(
wrapper.find("#sort-by-size i").hasClass("fa-sort-amount-down")
).toBeTruthy()
})
it("should render the date column with asc class when objects are sorted by date asc", () => {
const sortObjects = jest.fn()
const wrapper = shallow(
<ObjectsHeader
sortObjects={sortObjects}
sortedByLastModified={true}
sortOrder={SORT_ORDER_ASC}
/>
)
expect(
wrapper.find("#sort-by-last-modified i").hasClass("fa-sort-numeric-down")
).toBeTruthy()
})
it("should render the date column with desc class when objects are sorted by date desc", () => {
const sortObjects = jest.fn()
const wrapper = shallow(
<ObjectsHeader
sortObjects={sortObjects}
sortedByLastModified={true}
sortOrder={SORT_ORDER_DESC}
/>
)
expect(
wrapper.find("#sort-by-last-modified i").hasClass("fa-sort-numeric-down-alt")
).toBeTruthy()
})
it("should call sortObjects when a column is clicked", () => {
const sortObjects = jest.fn()
const wrapper = shallow(<ObjectsHeader sortObjects={sortObjects} />)
wrapper.find("#sort-by-name").simulate("click")
expect(sortObjects).toHaveBeenCalledWith("name")
wrapper.find("#sort-by-size").simulate("click")
expect(sortObjects).toHaveBeenCalledWith("size")
wrapper.find("#sort-by-last-modified").simulate("click")
expect(sortObjects).toHaveBeenCalledWith("last-modified")
})
})

View File

@@ -0,0 +1,39 @@
/*
* MinIO Object Storage (c) 2021 MinIO, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import React from "react"
import { shallow } from "enzyme"
import { ObjectsList } from "../ObjectsList"
describe("ObjectsList", () => {
it("should render without crashing", () => {
shallow(<ObjectsList objects={[]} />)
})
it("should render ObjectContainer for every object", () => {
const wrapper = shallow(
<ObjectsList objects={[{ name: "test1.jpg" }, { name: "test2.jpg" }]} />
)
expect(wrapper.find("Connect(ObjectContainer)").length).toBe(2)
})
it("should render PrefixContainer for every prefix", () => {
const wrapper = shallow(
<ObjectsList objects={[{ name: "abc/" }, { name: "xyz/" }]} />
)
expect(wrapper.find("Connect(PrefixContainer)").length).toBe(2)
})
})

View File

@@ -0,0 +1,49 @@
/*
* MinIO Object Storage (c) 2021 MinIO, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import React from "react"
import { shallow } from "enzyme"
import { ObjectsListContainer } from "../ObjectsListContainer"
describe("ObjectsList", () => {
it("should render without crashing", () => {
shallow(<ObjectsListContainer filteredObjects={[]} />)
})
it("should render ObjectsList with objects", () => {
const wrapper = shallow(
<ObjectsListContainer
filteredObjects={[{ name: "test1.jpg" }, { name: "test2.jpg" }]}
/>
)
expect(wrapper.find("ObjectsList").length).toBe(1)
expect(wrapper.find("ObjectsList").prop("objects")).toEqual([
{ name: "test1.jpg" },
{ name: "test2.jpg" }
])
})
it("should show the loading indicator when the objects are being loaded", () => {
const wrapper = shallow(
<ObjectsListContainer
currentBucket="test1"
filteredObjects={[]}
listLoading={true}
/>
)
expect(wrapper.find(".loading").exists()).toBeTruthy()
})
})

View File

@@ -0,0 +1,32 @@
/*
* MinIO Object Storage (c) 2021 MinIO, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import React from "react"
import { shallow } from "enzyme"
import { ObjectsSearch } from "../ObjectsSearch"
describe("ObjectsSearch", () => {
it("should render without crashing", () => {
shallow(<ObjectsSearch />)
})
it("should call onChange with search text", () => {
const onChange = jest.fn()
const wrapper = shallow(<ObjectsSearch onChange={onChange} />)
wrapper.find("input").simulate("change", { target: { value: "test" } })
expect(onChange).toHaveBeenCalledWith("test")
})
})

View File

@@ -0,0 +1,25 @@
/*
* MinIO Object Storage (c) 2021 MinIO, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import React from "react"
import { shallow } from "enzyme"
import { ObjectsSection } from "../ObjectsSection"
describe("ObjectsSection", () => {
it("should render without crashing", () => {
shallow(<ObjectsSection />)
})
})

View File

@@ -0,0 +1,143 @@
/*
* MinIO Object Storage (c) 2021 MinIO, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import React from "react"
import { shallow, mount } from "enzyme"
import { Path } from "../Path"
describe("Path", () => {
it("should render without crashing", () => {
shallow(<Path currentBucket={"test1"} currentPrefix={"test2"} />)
})
it("should render only bucket if there is no prefix", () => {
const wrapper = shallow(<Path currentBucket={"test1"} currentPrefix={""} />)
expect(wrapper.find("span").length).toBe(1)
expect(
wrapper
.find("span")
.at(0)
.text()
).toBe("test1")
})
it("should render bucket and prefix", () => {
const wrapper = shallow(
<Path currentBucket={"test1"} currentPrefix={"a/b/"} />
)
expect(wrapper.find("span").length).toBe(3)
expect(
wrapper
.find("span")
.at(0)
.text()
).toBe("test1")
expect(
wrapper
.find("span")
.at(1)
.text()
).toBe("a")
expect(
wrapper
.find("span")
.at(2)
.text()
).toBe("b")
})
it("should call selectPrefix when a prefix part is clicked", () => {
const selectPrefix = jest.fn()
const wrapper = shallow(
<Path
currentBucket={"test1"}
currentPrefix={"a/b/"}
selectPrefix={selectPrefix}
/>
)
wrapper
.find("a")
.at(2)
.simulate("click", { preventDefault: jest.fn() })
expect(selectPrefix).toHaveBeenCalledWith("a/b/")
})
it("should switch to input mode when edit icon is clicked", () => {
const wrapper = mount(<Path currentBucket={"test1"} currentPrefix={""} />)
wrapper.find(".fe-edit").simulate("click", { preventDefault: jest.fn() })
expect(wrapper.find(".form-control--path").exists()).toBeTruthy()
})
it("should navigate to prefix when user types path for existing bucket", () => {
const selectBucket = jest.fn()
const buckets = ["test1", "test2"]
const wrapper = mount(
<Path
buckets={buckets}
currentBucket={"test1"}
currentPrefix={""}
selectBucket={selectBucket}
/>
)
wrapper.setState({
isEditing: true,
path: "test2/dir1/"
})
wrapper.find("form").simulate("submit", { preventDefault: jest.fn() })
expect(selectBucket).toHaveBeenCalledWith("test2", "dir1/")
})
it("should create a new bucket if bucket typed in path doesn't exist", () => {
const makeBucket = jest.fn()
const buckets = ["test1", "test2"]
const wrapper = mount(
<Path
buckets={buckets}
currentBucket={"test1"}
currentPrefix={""}
makeBucket={makeBucket}
/>
)
wrapper.setState({
isEditing: true,
path: "test3/dir1/"
})
wrapper.find("form").simulate("submit", { preventDefault: jest.fn() })
expect(makeBucket).toHaveBeenCalledWith("test3")
})
it("should not make or select bucket if path doesn't point to bucket", () => {
const makeBucket = jest.fn()
const selectBucket = jest.fn()
const buckets = ["test1", "test2"]
const wrapper = mount(
<Path
buckets={buckets}
currentBucket={"test1"}
currentPrefix={""}
makeBucket={makeBucket}
selectBucket={selectBucket}
/>
)
wrapper.setState({
isEditing: true,
path: "//dir1/dir2/"
})
wrapper.find("form").simulate("submit", { preventDefault: jest.fn() })
expect(makeBucket).not.toHaveBeenCalled()
expect(selectBucket).not.toHaveBeenCalled()
})
})

View File

@@ -0,0 +1,84 @@
/*
* MinIO Object Storage (c) 2021 MinIO, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import React from "react"
import { shallow } from "enzyme"
import { PrefixActions } from "../PrefixActions"
describe("PrefixActions", () => {
it("should render without crashing", () => {
shallow(<PrefixActions object={{ name: "abc/" }} currentPrefix={"pre1/"} />)
})
it("should show DeleteObjectConfirmModal when delete action is clicked", () => {
const wrapper = shallow(
<PrefixActions object={{ name: "abc/" }} currentPrefix={"pre1/"} />
)
wrapper
.find("a")
.last()
.simulate("click", { preventDefault: jest.fn() })
expect(wrapper.state("showDeleteConfirmation")).toBeTruthy()
expect(wrapper.find("DeleteObjectConfirmModal").length).toBe(1)
})
it("should hide DeleteObjectConfirmModal when Cancel button is clicked", () => {
const wrapper = shallow(
<PrefixActions object={{ name: "abc/" }} currentPrefix={"pre1/"} />
)
wrapper
.find("a")
.last()
.simulate("click", { preventDefault: jest.fn() })
wrapper.find("DeleteObjectConfirmModal").prop("hideDeleteConfirmModal")()
wrapper.update()
expect(wrapper.state("showDeleteConfirmation")).toBeFalsy()
expect(wrapper.find("DeleteObjectConfirmModal").length).toBe(0)
})
it("should call deleteObject with object name", () => {
const deleteObject = jest.fn()
const wrapper = shallow(
<PrefixActions
object={{ name: "abc/" }}
currentPrefix={"pre1/"}
deleteObject={deleteObject}
/>
)
wrapper
.find("a")
.last()
.simulate("click", { preventDefault: jest.fn() })
wrapper.find("DeleteObjectConfirmModal").prop("deleteObject")()
expect(deleteObject).toHaveBeenCalledWith("abc/")
})
it("should call downloadPrefix when single object is selected and download button is clicked", () => {
const downloadPrefix = jest.fn()
const wrapper = shallow(
<PrefixActions
object={{ name: "abc/" }}
currentPrefix={"pre1/"}
downloadPrefix={downloadPrefix} />
)
wrapper
.find("a")
.first()
.simulate("click", { preventDefault: jest.fn() })
expect(downloadPrefix).toHaveBeenCalled()
})
})

View File

@@ -0,0 +1,62 @@
/*
* MinIO Object Storage (c) 2021 MinIO, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import React from "react"
import { shallow } from "enzyme"
import { PrefixContainer } from "../PrefixContainer"
describe("PrefixContainer", () => {
it("should render without crashing", () => {
shallow(<PrefixContainer object={{ name: "abc/" }} />)
})
it("should render ObjectItem with props", () => {
const wrapper = shallow(<PrefixContainer object={{ name: "abc/" }} />)
expect(wrapper.find("Connect(ObjectItem)").length).toBe(1)
expect(wrapper.find("Connect(ObjectItem)").prop("name")).toBe("abc/")
})
it("should call selectPrefix when the prefix is clicked", () => {
const selectPrefix = jest.fn()
const wrapper = shallow(
<PrefixContainer
object={{ name: "abc/" }}
currentPrefix={"xyz/"}
selectPrefix={selectPrefix}
/>
)
wrapper.find("Connect(ObjectItem)").prop("onClick")()
expect(selectPrefix).toHaveBeenCalledWith("xyz/abc/")
})
it("should pass actions to ObjectItem", () => {
const wrapper = shallow(
<PrefixContainer object={{ name: "abc/" }} checkedObjectsCount={0} />
)
expect(wrapper.find("Connect(ObjectItem)").prop("actionButtons")).not.toBe(
undefined
)
})
it("should pass empty actions to ObjectItem when checkedObjectCount is more than 0", () => {
const wrapper = shallow(
<PrefixContainer object={{ name: "abc/" }} checkedObjectsCount={1} />
)
expect(wrapper.find("Connect(ObjectItem)").prop("actionButtons")).toBe(
undefined
)
})
})

View File

@@ -0,0 +1,211 @@
/*
* MinIO Object Storage (c) 2021 MinIO, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import React from "react"
import { shallow, mount } from "enzyme"
import { ShareObjectModal } from "../ShareObjectModal"
import {
SHARE_OBJECT_EXPIRY_DAYS,
SHARE_OBJECT_EXPIRY_HOURS,
SHARE_OBJECT_EXPIRY_MINUTES
} from "../../constants"
jest.mock("../../web", () => ({
LoggedIn: jest.fn(() => {
return true
})
}))
describe("ShareObjectModal", () => {
it("should render without crashing", () => {
shallow(
<ShareObjectModal
object={{ name: "obj1" }}
shareObjectDetails={{ show: true, object: "obj1", url: "test", showExpiryDate: true }}
/>
)
})
it("shoud call hideShareObject when Cancel is clicked", () => {
const hideShareObject = jest.fn()
const wrapper = shallow(
<ShareObjectModal
object={{ name: "obj1" }}
shareObjectDetails={{ show: true, object: "obj1", url: "test", showExpiryDate: true }}
hideShareObject={hideShareObject}
/>
)
wrapper
.find("button")
.last()
.simulate("click")
expect(hideShareObject).toHaveBeenCalled()
})
it("should show the shareable link", () => {
const wrapper = shallow(
<ShareObjectModal
object={{ name: "obj1" }}
shareObjectDetails={{ show: true, object: "obj1", url: "test", showExpiryDate: true }}
/>
)
expect(
wrapper
.find("input")
.first()
.prop("value")
).toBe(`${window.location.protocol}//test`)
})
it("should call showCopyAlert and hideShareObject when Copy button is clicked", () => {
const hideShareObject = jest.fn()
const showCopyAlert = jest.fn()
const wrapper = shallow(
<ShareObjectModal
object={{ name: "obj1" }}
shareObjectDetails={{ show: true, object: "obj1", url: "test", showExpiryDate: true }}
hideShareObject={hideShareObject}
showCopyAlert={showCopyAlert}
/>
)
wrapper.find("CopyToClipboard").prop("onCopy")()
expect(showCopyAlert).toHaveBeenCalledWith("Link copied to clipboard!")
expect(hideShareObject).toHaveBeenCalled()
})
describe("Update expiry values", () => {
const props = {
object: { name: "obj1" },
shareObjectDetails: { show: true, object: "obj1", url: "test", showExpiryDate: true }
}
it("should not show expiry values if shared with public link", () => {
const shareObjectDetails = { show: true, object: "obj1", url: "test", showExpiryDate: false }
const wrapper = shallow(<ShareObjectModal {...props} shareObjectDetails={shareObjectDetails} />)
expect(wrapper.find('.set-expire').exists()).toEqual(false)
})
it("should have default expiry values", () => {
const wrapper = shallow(<ShareObjectModal {...props} />)
expect(wrapper.state("expiry")).toEqual({
days: SHARE_OBJECT_EXPIRY_DAYS,
hours: SHARE_OBJECT_EXPIRY_HOURS,
minutes: SHARE_OBJECT_EXPIRY_MINUTES
})
})
it("should not allow any increments when days is already max", () => {
const shareObject = jest.fn()
const wrapper = shallow(
<ShareObjectModal {...props} shareObject={shareObject} />
)
wrapper.setState({
expiry: {
days: 7,
hours: 0,
minutes: 0
}
})
wrapper.find("#increase-hours").simulate("click")
expect(wrapper.state("expiry")).toEqual({
days: 7,
hours: 0,
minutes: 0
})
expect(shareObject).not.toHaveBeenCalled()
})
it("should not allow expiry values less than minimum value", () => {
const shareObject = jest.fn()
const wrapper = shallow(
<ShareObjectModal {...props} shareObject={shareObject} />
)
wrapper.setState({
expiry: {
days: 5,
hours: 0,
minutes: 0
}
})
wrapper.find("#decrease-hours").simulate("click")
expect(wrapper.state("expiry").hours).toBe(0)
wrapper.find("#decrease-minutes").simulate("click")
expect(wrapper.state("expiry").minutes).toBe(0)
expect(shareObject).not.toHaveBeenCalled()
})
it("should not allow expiry values more than maximum value", () => {
const shareObject = jest.fn()
const wrapper = shallow(
<ShareObjectModal {...props} shareObject={shareObject} />
)
wrapper.setState({
expiry: {
days: 1,
hours: 23,
minutes: 59
}
})
wrapper.find("#increase-hours").simulate("click")
expect(wrapper.state("expiry").hours).toBe(23)
wrapper.find("#increase-minutes").simulate("click")
expect(wrapper.state("expiry").minutes).toBe(59)
expect(shareObject).not.toHaveBeenCalled()
})
it("should set hours and minutes to 0 when days reaches max", () => {
const shareObject = jest.fn()
const wrapper = shallow(
<ShareObjectModal {...props} shareObject={shareObject} />
)
wrapper.setState({
expiry: {
days: 6,
hours: 5,
minutes: 30
}
})
wrapper.find("#increase-days").simulate("click")
expect(wrapper.state("expiry")).toEqual({
days: 7,
hours: 0,
minutes: 0
})
expect(shareObject).toHaveBeenCalled()
})
it("should set days to MAX when all of them becomes 0", () => {
const shareObject = jest.fn()
const wrapper = shallow(
<ShareObjectModal {...props} shareObject={shareObject} />
)
wrapper.setState({
expiry: {
days: 0,
hours: 1,
minutes: 0
}
})
wrapper.find("#decrease-hours").simulate("click")
expect(wrapper.state("expiry")).toEqual({
days: 7,
hours: 0,
minutes: 0
})
expect(shareObject).toHaveBeenCalledWith("obj1", 7, 0, 0)
})
})
})

View File

@@ -0,0 +1,584 @@
/*
* MinIO Object Storage (c) 2021 MinIO, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import configureStore from "redux-mock-store"
import thunk from "redux-thunk"
import * as actionsObjects from "../actions"
import * as alertActions from "../../alert/actions"
import {
minioBrowserPrefix,
SORT_BY_NAME,
SORT_ORDER_ASC,
SORT_BY_LAST_MODIFIED,
SORT_ORDER_DESC
} from "../../constants"
import history from "../../history"
jest.mock("../../web", () => ({
LoggedIn: jest
.fn(() => true)
.mockReturnValueOnce(true)
.mockReturnValueOnce(false)
.mockReturnValueOnce(true)
.mockReturnValueOnce(true)
.mockReturnValueOnce(true)
.mockReturnValueOnce(false),
ListObjects: jest.fn(({ bucketName }) => {
if (bucketName === "test-deny") {
return Promise.reject({
message: "listobjects is denied"
})
} else {
return Promise.resolve({
objects: [{ name: "test1" }, { name: "test2" }],
writable: false
})
}
}),
RemoveObject: jest.fn(({ bucketName, objects }) => {
if (!bucketName) {
return Promise.reject({ message: "Invalid bucket" })
}
return Promise.resolve({})
}),
PresignedGet: jest.fn(({ bucket, object }) => {
if (!bucket) {
return Promise.reject({ message: "Invalid bucket" })
}
return Promise.resolve({ url: "https://test.com/bk1/pre1/b.txt" })
}),
CreateURLToken: jest
.fn()
.mockImplementationOnce(() => {
return Promise.resolve({ token: "test" })
})
.mockImplementationOnce(() => {
return Promise.reject({ message: "Error in creating token" })
})
.mockImplementationOnce(() => {
return Promise.resolve({ token: "test" })
})
.mockImplementationOnce(() => {
return Promise.resolve({ token: "test" })
}),
GetBucketPolicy: jest.fn(({ bucketName, prefix }) => {
if (!bucketName) {
return Promise.reject({ message: "Invalid bucket" })
}
if (bucketName === 'test-public') return Promise.resolve({ policy: 'readonly' })
return Promise.resolve({})
})
}))
const middlewares = [thunk]
const mockStore = configureStore(middlewares)
describe("Objects actions", () => {
it("creates objects/SET_LIST action", () => {
const store = mockStore()
const expectedActions = [
{
type: "objects/SET_LIST",
objects: [{ name: "test1" }, { name: "test2" }]
}
]
store.dispatch(
actionsObjects.setList([{ name: "test1" }, { name: "test2" }])
)
const actions = store.getActions()
expect(actions).toEqual(expectedActions)
})
it("creates objects/SET_SORT_BY action", () => {
const store = mockStore()
const expectedActions = [
{
type: "objects/SET_SORT_BY",
sortBy: SORT_BY_NAME
}
]
store.dispatch(actionsObjects.setSortBy(SORT_BY_NAME))
const actions = store.getActions()
expect(actions).toEqual(expectedActions)
})
it("creates objects/SET_SORT_ORDER action", () => {
const store = mockStore()
const expectedActions = [
{
type: "objects/SET_SORT_ORDER",
sortOrder: SORT_ORDER_ASC
}
]
store.dispatch(actionsObjects.setSortOrder(SORT_ORDER_ASC))
const actions = store.getActions()
expect(actions).toEqual(expectedActions)
})
it("creates objects/SET_LIST after fetching the objects", () => {
const store = mockStore({
buckets: { currentBucket: "bk1" },
objects: { currentPrefix: "" }
})
const expectedActions = [
{
type: "objects/RESET_LIST"
},
{ listLoading: true, type: "objects/SET_LIST_LOADING" },
{
type: "objects/SET_SORT_BY",
sortBy: SORT_BY_LAST_MODIFIED
},
{
type: "objects/SET_SORT_ORDER",
sortOrder: SORT_ORDER_DESC
},
{
type: "objects/SET_LIST",
objects: [{ name: "test2" }, { name: "test1" }]
},
{
type: "objects/SET_PREFIX_WRITABLE",
prefixWritable: false
},
{ listLoading: false, type: "objects/SET_LIST_LOADING" }
]
return store.dispatch(actionsObjects.fetchObjects()).then(() => {
const actions = store.getActions()
expect(actions).toEqual(expectedActions)
})
})
it("creates objects/RESET_LIST after failing to fetch the objects from bucket with ListObjects denied for LoggedIn users", () => {
const store = mockStore({
buckets: { currentBucket: "test-deny" },
objects: { currentPrefix: "" }
})
const expectedActions = [
{
type: "objects/RESET_LIST"
},
{ listLoading: true, type: "objects/SET_LIST_LOADING" },
{
type: "alert/SET",
alert: {
type: "danger",
message: "listobjects is denied",
id: alertActions.alertId,
autoClear: true
}
},
{
type: "objects/RESET_LIST"
},
{ listLoading: false, type: "objects/SET_LIST_LOADING" }
]
return store.dispatch(actionsObjects.fetchObjects()).then(() => {
const actions = store.getActions()
expect(actions).toEqual(expectedActions)
})
})
it("redirect to login after failing to fetch the objects from bucket for non-LoggedIn users", () => {
const store = mockStore({
buckets: { currentBucket: "test-deny" },
objects: { currentPrefix: "" }
})
return store.dispatch(actionsObjects.fetchObjects()).then(() => {
expect(history.location.pathname.endsWith("/login")).toBeTruthy()
})
})
it("creates objects/SET_SORT_BY and objects/SET_SORT_ORDER when sortObjects is called", () => {
const store = mockStore({
objects: {
list: [],
sortBy: "",
sortOrder: SORT_ORDER_ASC
}
})
const expectedActions = [
{
type: "objects/SET_SORT_BY",
sortBy: SORT_BY_NAME
},
{
type: "objects/SET_SORT_ORDER",
sortOrder: SORT_ORDER_ASC
},
{
type: "objects/SET_LIST",
objects: []
}
]
store.dispatch(actionsObjects.sortObjects(SORT_BY_NAME))
const actions = store.getActions()
expect(actions).toEqual(expectedActions)
})
it("should update browser url and creates objects/SET_CURRENT_PREFIX and objects/CHECKED_LIST_RESET actions when selectPrefix is called", () => {
const store = mockStore({
buckets: { currentBucket: "test" },
objects: { currentPrefix: "" }
})
const expectedActions = [
{ type: "objects/SET_CURRENT_PREFIX", prefix: "abc/" },
{
type: "objects/RESET_LIST"
},
{ listLoading: true, type: "objects/SET_LIST_LOADING" },
{ type: "objects/CHECKED_LIST_RESET" }
]
store.dispatch(actionsObjects.selectPrefix("abc/"))
const actions = store.getActions()
expect(actions).toEqual(expectedActions)
expect(window.location.pathname.endsWith("/test/abc/")).toBeTruthy()
})
it("create objects/SET_PREFIX_WRITABLE action", () => {
const store = mockStore()
const expectedActions = [
{ type: "objects/SET_PREFIX_WRITABLE", prefixWritable: true }
]
store.dispatch(actionsObjects.setPrefixWritable(true))
const actions = store.getActions()
expect(actions).toEqual(expectedActions)
})
it("creates objects/REMOVE action", () => {
const store = mockStore()
const expectedActions = [{ type: "objects/REMOVE", object: "obj1" }]
store.dispatch(actionsObjects.removeObject("obj1"))
const actions = store.getActions()
expect(actions).toEqual(expectedActions)
})
it("creates objects/REMOVE action when object is deleted", () => {
const store = mockStore({
buckets: { currentBucket: "test" },
objects: { currentPrefix: "pre1/" }
})
const expectedActions = [{ type: "objects/REMOVE", object: "obj1" }]
store.dispatch(actionsObjects.deleteObject("obj1")).then(() => {
const actions = store.getActions()
expect(actions).toEqual(expectedActions)
})
})
it("creates alert/SET action when invalid bucket is provided", () => {
const store = mockStore({
buckets: { currentBucket: "" },
objects: { currentPrefix: "pre1/" }
})
const expectedActions = [
{
type: "alert/SET",
alert: {
type: "danger",
message: "Invalid bucket",
id: alertActions.alertId
}
}
]
return store.dispatch(actionsObjects.deleteObject("obj1")).then(() => {
const actions = store.getActions()
expect(actions).toEqual(expectedActions)
})
})
it("creates objects/SET_SHARE_OBJECT action for showShareObject", () => {
const store = mockStore()
const expectedActions = [
{
type: "objects/SET_SHARE_OBJECT",
show: true,
object: "b.txt",
url: "test",
showExpiryDate: true
}
]
store.dispatch(actionsObjects.showShareObject("b.txt", "test"))
const actions = store.getActions()
expect(actions).toEqual(expectedActions)
})
it("creates objects/SET_SHARE_OBJECT action for hideShareObject", () => {
const store = mockStore()
const expectedActions = [
{
type: "objects/SET_SHARE_OBJECT",
show: false,
object: "",
url: ""
}
]
store.dispatch(actionsObjects.hideShareObject())
const actions = store.getActions()
expect(actions).toEqual(expectedActions)
})
it("creates objects/SET_SHARE_OBJECT when object is shared", () => {
const store = mockStore({
buckets: { currentBucket: "bk1" },
objects: { currentPrefix: "pre1/" },
browser: { serverInfo: {} },
})
const expectedActions = [
{
type: "objects/SET_SHARE_OBJECT",
show: true,
object: "a.txt",
url: "https://test.com/bk1/pre1/b.txt",
showExpiryDate: true
},
{
type: "alert/SET",
alert: {
type: "success",
message: "Object shared. Expires in 1 days 0 hours 0 minutes",
id: alertActions.alertId
}
}
]
return store
.dispatch(actionsObjects.shareObject("a.txt", 1, 0, 0))
.then(() => {
const actions = store.getActions()
expect(actions).toEqual(expectedActions)
})
})
it("creates objects/SET_SHARE_OBJECT when object is shared with public link", () => {
const store = mockStore({
buckets: { currentBucket: "test-public" },
objects: { currentPrefix: "pre1/" },
browser: { serverInfo: { info: { domains: ['public.com'] }} },
})
const expectedActions = [
{
type: "objects/SET_SHARE_OBJECT",
show: true,
object: "a.txt",
url: "public.com/test-public/pre1/a.txt",
showExpiryDate: false
},
{
type: "alert/SET",
alert: {
type: "success",
message: "Object shared.",
id: alertActions.alertId
}
}
]
return store
.dispatch(actionsObjects.shareObject("a.txt", 1, 0, 0))
.then(() => {
const actions = store.getActions()
expect(actions).toEqual(expectedActions)
})
})
it("creates alert/SET when shareObject is failed", () => {
const store = mockStore({
buckets: { currentBucket: "" },
objects: { currentPrefix: "pre1/" },
browser: { serverInfo: {} },
})
const expectedActions = [
{
type: "alert/SET",
alert: {
type: "danger",
message: "Invalid bucket",
id: alertActions.alertId
}
}
]
return store
.dispatch(actionsObjects.shareObject("a.txt", 1, 0, 0))
.then(() => {
const actions = store.getActions()
expect(actions).toEqual(expectedActions)
})
})
describe("Download object", () => {
it("should download the object non-LoggedIn users", () => {
const setLocation = jest.fn()
Object.defineProperty(window, "location", {
set(url) {
setLocation(url)
},
get() {
return {
origin: "http://localhost:8080"
}
}
})
const store = mockStore({
buckets: { currentBucket: "bk1" },
objects: { currentPrefix: "pre1/" }
})
store.dispatch(actionsObjects.downloadObject("obj1"))
const url = `${
window.location.origin
}${minioBrowserPrefix}/download/bk1/${encodeURI("pre1/obj1")}?token=`
expect(setLocation).toHaveBeenCalledWith(url)
})
it("should download the object for LoggedIn users", () => {
const setLocation = jest.fn()
Object.defineProperty(window, "location", {
set(url) {
setLocation(url)
},
get() {
return {
origin: "http://localhost:8080"
}
}
})
const store = mockStore({
buckets: { currentBucket: "bk1" },
objects: { currentPrefix: "pre1/" }
})
return store.dispatch(actionsObjects.downloadObject("obj1")).then(() => {
const url = `${
window.location.origin
}${minioBrowserPrefix}/download/bk1/${encodeURI(
"pre1/obj1"
)}?token=test`
expect(setLocation).toHaveBeenCalledWith(url)
})
})
it("create alert/SET action when CreateUrlToken fails", () => {
const store = mockStore({
buckets: { currentBucket: "bk1" },
objects: { currentPrefix: "pre1/" }
})
const expectedActions = [
{
type: "alert/SET",
alert: {
type: "danger",
message: "Error in creating token",
id: alertActions.alertId
}
}
]
return store.dispatch(actionsObjects.downloadObject("obj1")).then(() => {
const actions = store.getActions()
expect(actions).toEqual(expectedActions)
})
})
})
it("should download prefix", () => {
const open = jest.fn()
const send = jest.fn()
const xhrMockClass = () => ({
open: open,
send: send
})
window.XMLHttpRequest = jest.fn().mockImplementation(xhrMockClass)
const store = mockStore({
buckets: { currentBucket: "bk1" },
objects: { currentPrefix: "pre1/" }
})
return store.dispatch(actionsObjects.downloadPrefix("pre2/")).then(() => {
const requestUrl = `${
location.origin
}${minioBrowserPrefix}/zip?token=test`
expect(open).toHaveBeenCalledWith("POST", requestUrl, true)
expect(send).toHaveBeenCalledWith(
JSON.stringify({
bucketName: "bk1",
prefix: "pre1/",
objects: ["pre2/"]
})
)
})
})
it("creates objects/CHECKED_LIST_ADD action", () => {
const store = mockStore()
const expectedActions = [
{
type: "objects/CHECKED_LIST_ADD",
object: "obj1"
}
]
store.dispatch(actionsObjects.checkObject("obj1"))
const actions = store.getActions()
expect(actions).toEqual(expectedActions)
})
it("creates objects/CHECKED_LIST_REMOVE action", () => {
const store = mockStore()
const expectedActions = [
{
type: "objects/CHECKED_LIST_REMOVE",
object: "obj1"
}
]
store.dispatch(actionsObjects.uncheckObject("obj1"))
const actions = store.getActions()
expect(actions).toEqual(expectedActions)
})
it("creates objects/CHECKED_LIST_RESET action", () => {
const store = mockStore()
const expectedActions = [
{
type: "objects/CHECKED_LIST_RESET"
}
]
store.dispatch(actionsObjects.resetCheckedList())
const actions = store.getActions()
expect(actions).toEqual(expectedActions)
})
it("should download checked objects", () => {
const open = jest.fn()
const send = jest.fn()
const xhrMockClass = () => ({
open: open,
send: send
})
window.XMLHttpRequest = jest.fn().mockImplementation(xhrMockClass)
const store = mockStore({
buckets: { currentBucket: "bk1" },
objects: { currentPrefix: "pre1/", checkedList: ["obj1"] }
})
return store.dispatch(actionsObjects.downloadCheckedObjects()).then(() => {
const requestUrl = `${
location.origin
}${minioBrowserPrefix}/zip?token=test`
expect(open).toHaveBeenCalledWith("POST", requestUrl, true)
expect(send).toHaveBeenCalledWith(
JSON.stringify({
bucketName: "bk1",
prefix: "pre1/",
objects: ["obj1"]
})
)
})
})
})

View File

@@ -0,0 +1,148 @@
/*
* MinIO Object Storage (c) 2021 MinIO, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import reducer from "../reducer"
import * as actions from "../actions"
import { SORT_ORDER_ASC, SORT_BY_NAME } from "../../constants"
describe("objects reducer", () => {
it("should return the initial state", () => {
const initialState = reducer(undefined, {})
expect(initialState).toEqual({
list: [],
filter: "",
listLoading: false,
sortBy: "",
sortOrder: SORT_ORDER_ASC,
currentPrefix: "",
prefixWritable: false,
shareObject: {
show: false,
object: "",
url: ""
},
checkedList: []
})
})
it("should handle SET_LIST", () => {
const newState = reducer(undefined, {
type: actions.SET_LIST,
objects: [{ name: "obj1" }, { name: "obj2" }]
})
expect(newState.list).toEqual([{ name: "obj1" }, { name: "obj2" }])
})
it("should handle REMOVE", () => {
const newState = reducer(
{ list: [{ name: "obj1" }, { name: "obj2" }] },
{
type: actions.REMOVE,
object: "obj1"
}
)
expect(newState.list).toEqual([{ name: "obj2" }])
})
it("should handle REMOVE with non-existent object", () => {
const newState = reducer(
{ list: [{ name: "obj1" }, { name: "obj2" }] },
{
type: actions.REMOVE,
object: "obj3"
}
)
expect(newState.list).toEqual([{ name: "obj1" }, { name: "obj2" }])
})
it("should handle SET_SORT_BY", () => {
const newState = reducer(undefined, {
type: actions.SET_SORT_BY,
sortBy: SORT_BY_NAME
})
expect(newState.sortBy).toEqual(SORT_BY_NAME)
})
it("should handle SET_SORT_ORDER", () => {
const newState = reducer(undefined, {
type: actions.SET_SORT_ORDER,
sortOrder: SORT_ORDER_ASC
})
expect(newState.sortOrder).toEqual(SORT_ORDER_ASC)
})
it("should handle SET_CURRENT_PREFIX", () => {
const newState = reducer(
{ currentPrefix: "test1/" },
{
type: actions.SET_CURRENT_PREFIX,
prefix: "test2/"
}
)
expect(newState.currentPrefix).toEqual("test2/")
})
it("should handle SET_PREFIX_WRITABLE", () => {
const newState = reducer(undefined, {
type: actions.SET_PREFIX_WRITABLE,
prefixWritable: true
})
expect(newState.prefixWritable).toBeTruthy()
})
it("should handle SET_SHARE_OBJECT", () => {
const newState = reducer(undefined, {
type: actions.SET_SHARE_OBJECT,
show: true,
object: "a.txt",
url: "test"
})
expect(newState.shareObject).toEqual({
show: true,
object: "a.txt",
url: "test"
})
})
it("should handle CHECKED_LIST_ADD", () => {
const newState = reducer(undefined, {
type: actions.CHECKED_LIST_ADD,
object: "obj1"
})
expect(newState.checkedList).toEqual(["obj1"])
})
it("should handle SELECTED_LIST_REMOVE", () => {
const newState = reducer(
{ checkedList: ["obj1", "obj2"] },
{
type: actions.CHECKED_LIST_REMOVE,
object: "obj1"
}
)
expect(newState.checkedList).toEqual(["obj2"])
})
it("should handle CHECKED_LIST_RESET", () => {
const newState = reducer(
{ checkedList: ["obj1", "obj2"] },
{
type: actions.CHECKED_LIST_RESET
}
)
expect(newState.checkedList).toEqual([])
})
})