Browser: Update UI with new components and elements (#5671)

This commit is contained in:
Rushan
2018-03-21 23:39:23 +05:30
committed by Harshavardhana
parent 384b4fdf28
commit 1459c4be1e
199 changed files with 10549 additions and 4702 deletions

View File

@@ -20,25 +20,19 @@ import BucketDropdown from "./BucketDropdown"
export const Bucket = ({ bucket, isActive, selectBucket }) => {
return (
<li
<div
className={classNames({
active: isActive
buckets__item: true,
"buckets__item--active": isActive,
})}
onClick={e => {
e.preventDefault()
selectBucket(bucket)
}}
>
<a
href=""
className={classNames({
"fesli-loading": false
})}
>
{bucket}
</a>
<BucketDropdown bucket={bucket}/>
</li>
<a href="">{bucket}</a>
<BucketDropdown bucket={bucket} />
</div>
)
}

View File

@@ -22,13 +22,13 @@ import Bucket from "./Bucket"
const mapStateToProps = (state, ownProps) => {
return {
isActive: getCurrentBucket(state) === ownProps.bucket
isActive: getCurrentBucket(state) === ownProps.bucket,
}
}
const mapDispatchToProps = dispatch => {
return {
selectBucket: bucket => dispatch(actionsBuckets.selectBucket(bucket))
selectBucket: bucket => dispatch(actionsBuckets.selectBucket(bucket)),
}
}

View File

@@ -19,24 +19,25 @@ import classNames from "classnames"
import { connect } from "react-redux"
import * as actionsBuckets from "./actions"
import { getCurrentBucket } from "./selectors"
import Dropdown from "react-bootstrap/lib/Dropdown"
import { Dropdown } from "react-bootstrap"
import { MenuItem } from "react-bootstrap"
export class BucketDropdown extends React.Component {
constructor(props) {
super(props)
this.state = {
showBucketDropdown: false
showBucketDropdown: false,
}
}
toggleDropdown() {
if (this.state.showBucketDropdown) {
this.setState({
showBucketDropdown: false
showBucketDropdown: false,
})
} else {
this.setState({
showBucketDropdown: true
showBucketDropdown: true,
})
}
}
@@ -44,38 +45,35 @@ export class BucketDropdown extends React.Component {
render() {
const { bucket, showBucketPolicy, deleteBucket, currentBucket } = this.props
return (
<Dropdown
open = {this.state.showBucketDropdown}
onToggle = {this.toggleDropdown.bind(this)}
className="bucket-dropdown"
<Dropdown
pullRight
open={this.state.showBucketDropdown}
onToggle={this.toggleDropdown.bind(this)}
className="buckets__item__actions"
id="bucket-dropdown"
>
<Dropdown.Toggle noCaret>
<Dropdown.Toggle noCaret className="dropdown-toggle--icon">
<i className="zmdi zmdi-more-vert" />
</Dropdown.Toggle>
<Dropdown.Menu className="dropdown-menu-right">
<li>
<a
onClick={e => {
e.stopPropagation()
this.toggleDropdown()
showBucketPolicy()
}}
>
Edit policy
</a>
</li>
<li>
<a
onClick={e => {
e.stopPropagation()
this.toggleDropdown()
deleteBucket(bucket)
}}
>
Delete
</a>
</li>
<Dropdown.Menu>
<MenuItem
onClick={e => {
e.stopPropagation()
showBucketPolicy()
}}
>
{" "}
Edit Policy
</MenuItem>
<MenuItem
onClick={e => {
e.stopPropagation()
deleteBucket(bucket)
}}
>
{" "}
Delete Bucket
</MenuItem>
</Dropdown.Menu>
</Dropdown>
)
@@ -85,7 +83,7 @@ export class BucketDropdown extends React.Component {
const mapDispatchToProps = dispatch => {
return {
deleteBucket: bucket => dispatch(actionsBuckets.deleteBucket(bucket)),
showBucketPolicy: () => dispatch(actionsBuckets.showBucketPolicy())
showBucketPolicy: () => dispatch(actionsBuckets.showBucketPolicy()),
}
}

View File

@@ -42,16 +42,10 @@ export class BucketList extends React.Component {
render() {
const { visibleBuckets } = this.props
return (
<div className="fesl-inner">
<Scrollbars
renderTrackVertical={props => <div className="scrollbar-vertical" />}
>
<ul>
{visibleBuckets.map(bucket => (
<BucketContainer key={bucket} bucket={bucket} />
))}
</ul>
</Scrollbars>
<div className="buckets__list">
{visibleBuckets.map(bucket => (
<BucketContainer key={bucket} bucket={bucket} />
))}
</div>
)
}
@@ -59,7 +53,7 @@ export class BucketList extends React.Component {
const mapStateToProps = state => {
return {
visibleBuckets: getVisibleBuckets(state)
visibleBuckets: getVisibleBuckets(state),
}
}
@@ -67,7 +61,7 @@ const mapDispatchToProps = dispatch => {
return {
fetchBuckets: () => dispatch(actionsBuckets.fetchBuckets()),
setBucketList: buckets => dispatch(actionsBuckets.setList(buckets)),
selectBucket: bucket => dispatch(actionsBuckets.selectBucket(bucket))
selectBucket: bucket => dispatch(actionsBuckets.selectBucket(bucket)),
}
}

View File

@@ -21,24 +21,29 @@ import * as actionsBuckets from "./actions"
import PolicyInput from "./PolicyInput"
import Policy from "./Policy"
export const BucketPolicyModal = ({ showBucketPolicy, currentBucket, hideBucketPolicy, policies }) => {
export const BucketPolicyModal = ({
showBucketPolicy,
currentBucket,
hideBucketPolicy,
policies,
}) => {
return (
<Modal className="modal-policy"
animation={ false }
show={ showBucketPolicy }
onHide={ hideBucketPolicy }
<Modal
className="policy"
animation={false}
show={showBucketPolicy}
onHide={hideBucketPolicy}
>
<ModalHeader>
Bucket Policy (
{ currentBucket })
<button className="close close-alt" onClick={ hideBucketPolicy }>
<span>×</span>
</button>
</ModalHeader>
<div className="pm-body">
<Modal.Header>
Bucket Policy
<small>Bucket Name: {currentBucket}</small>
<i className="close" onClick={hideBucketPolicy} />
</Modal.Header>
<div className="policy__content">
<PolicyInput />
{ policies.map((policy, i) => <Policy key={ i } prefix={ policy.prefix } policy={ policy.policy } />
) }
{policies.map((policy, i) => (
<Policy key={i} prefix={policy.prefix} policy={policy.policy} />
))}
</div>
</Modal>
)
@@ -48,14 +53,14 @@ const mapStateToProps = state => {
return {
currentBucket: state.buckets.currentBucket,
showBucketPolicy: state.buckets.showBucketPolicy,
policies: state.buckets.policies
policies: state.buckets.policies,
}
}
const mapDispatchToProps = dispatch => {
return {
hideBucketPolicy: () => dispatch(actionsBuckets.hideBucketPolicy())
hideBucketPolicy: () => dispatch(actionsBuckets.hideBucketPolicy()),
}
}
export default connect(mapStateToProps, mapDispatchToProps)(BucketPolicyModal)
export default connect(mapStateToProps, mapDispatchToProps)(BucketPolicyModal)

View File

@@ -19,17 +19,17 @@ import { connect } from "react-redux"
import * as actionsBuckets from "./actions"
export const BucketSearch = ({ onChange }) => (
<div
className="input-group ig-dark ig-left ig-search"
style={{ display: "block" }}
>
<input
className="ig-text"
type="text"
onChange={e => onChange(e.target.value)}
placeholder="Search Buckets..."
/>
<i className="ig-helpers" />
<div className="buckets__search">
<div className="form-group form-group--icon">
<i className="form-group__icon zmdi zmdi-search" />
<input
className="form-group__field"
type="text"
onChange={e => onChange(e.target.value)}
placeholder="Search Buckets..."
/>
<i className="form-group__helper" />
</div>
</div>
)
@@ -37,7 +37,7 @@ const mapDispatchToProps = dispatch => {
return {
onChange: filter => {
dispatch(actionsBuckets.setFilter(filter))
}
},
}
}

View File

@@ -23,7 +23,7 @@ export class MakeBucketModal extends React.Component {
constructor(props) {
super(props)
this.state = {
bucketName: ""
bucketName: "",
}
}
onSubmit(e) {
@@ -37,7 +37,7 @@ export class MakeBucketModal extends React.Component {
}
hideModal() {
this.setState({
bucketName: ""
bucketName: "",
})
this.props.hideMakeBucketModal()
}
@@ -45,30 +45,32 @@ export class MakeBucketModal extends React.Component {
const { showMakeBucketModal } = this.props
return (
<Modal
className="modal-create-bucket"
className="create-bucket"
bsSize="small"
animation={false}
show={showMakeBucketModal}
onHide={this.hideModal.bind(this)}
>
<button className="close close-alt" onClick={this.hideModal.bind(this)}>
<span>×</span>
</button>
<ModalBody>
<i className="close" onClick={this.hideModal.bind(this)} />
<Modal.Body>
<form onSubmit={this.onSubmit.bind(this)}>
<div className="input-group">
<div className="form-group form-group--centered">
<input
className="ig-text"
className="form-group__field"
type="text"
placeholder="Bucket Name"
value={this.state.bucketName}
onChange={e => this.setState({ bucketName: e.target.value })}
onChange={e =>
this.setState({
bucketName: e.target.value,
})
}
autoFocus
/>
<i className="ig-helpers" />
<i className="form-group__helper" />
</div>
</form>
</ModalBody>
</Modal.Body>
</Modal>
)
}
@@ -76,14 +78,14 @@ export class MakeBucketModal extends React.Component {
const mapStateToProps = state => {
return {
showMakeBucketModal: state.buckets.showMakeBucketModal
showMakeBucketModal: state.buckets.showMakeBucketModal,
}
}
const mapDispatchToProps = dispatch => {
return {
makeBucket: bucket => dispatch(actionsBuckets.makeBucket(bucket)),
hideMakeBucketModal: () => dispatch(actionsBuckets.hideMakeBucketModal())
hideMakeBucketModal: () => dispatch(actionsBuckets.hideMakeBucketModal()),
}
}

View File

@@ -14,11 +14,8 @@
* limitations under the License.
*/
import { READ_ONLY, WRITE_ONLY, READ_WRITE } from '../constants'
import React from "react"
import { connect } from "react-redux"
import classnames from "classnames"
import * as actionsBuckets from "./actions"
import * as actionsAlert from "../alert/actions"
import web from "../web"
@@ -26,51 +23,55 @@ import web from "../web"
export class Policy extends React.Component {
removePolicy(e) {
e.preventDefault()
const {currentBucket, prefix, fetchPolicies, showAlert} = this.props
web.
SetBucketPolicy({
const { currentBucket, prefix, fetchPolicies, showAlert } = this.props
web
.SetBucketPolicy({
bucketName: currentBucket,
prefix: prefix,
policy: 'none'
policy: "none",
})
.then(() => {
fetchPolicies(currentBucket)
})
.catch(e => showAlert('danger', e.message))
.catch(e => showAlert("danger", e.message))
}
render() {
const {policy, prefix} = this.props
const { policy, prefix } = this.props
let newPrefix = prefix
if (newPrefix === '')
newPrefix = '*'
if (newPrefix === "") newPrefix = "*"
let policyUpdated =
policy == "readonly"
? "Read Only"
: policy == "writeonly"
? "Write Only"
: policy == "readwrite" ? "Read and Write" : ""
return (
<div className="pmb-list">
<div className="pmbl-item">
{ newPrefix }
<div className="policy__row">
<div className="form-group">
<input
type="text"
value={newPrefix}
className="form-group__field form-group__field--static"
readOnly
/>
</div>
<div className="pmbl-item">
<select className="form-control"
disabled
value={ policy }>
<option value={ READ_ONLY }>
Read Only
</option>
<option value={ WRITE_ONLY }>
Write Only
</option>
<option value={ READ_WRITE }>
Read and Write
</option>
</select>
</div>
<div className="pmbl-item">
<button className="btn btn-block btn-danger" onClick={ this.removePolicy.bind(this) }>
Remove
</button>
<div className="form-group policy__access">
<input
type="text"
value={policyUpdated}
className="form-group__field form-group__field--static"
readOnly
/>
</div>
<button
className="btn btn--sm btn--danger"
onClick={this.removePolicy.bind(this)}
>
Remove
</button>
</div>
)
}
@@ -78,7 +79,7 @@ export class Policy extends React.Component {
const mapStateToProps = state => {
return {
currentBucket: state.buckets.currentBucket
currentBucket: state.buckets.currentBucket,
}
}
@@ -86,8 +87,13 @@ const mapDispatchToProps = dispatch => {
return {
fetchPolicies: bucket => dispatch(actionsBuckets.fetchPolicies(bucket)),
showAlert: (type, message) =>
dispatch(actionsAlert.set({ type: type, message: message }))
dispatch(
actionsAlert.set({
type: type,
message: message,
}),
),
}
}
export default connect(mapStateToProps, mapDispatchToProps)(Policy)
export default connect(mapStateToProps, mapDispatchToProps)(Policy)

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
import { READ_ONLY, WRITE_ONLY, READ_WRITE } from '../constants'
import { READ_ONLY, WRITE_ONLY, READ_WRITE } from "../constants"
import React from "react"
import { connect } from "react-redux"
@@ -37,61 +37,61 @@ export class PolicyInput extends React.Component {
handlePolicySubmit(e) {
e.preventDefault()
const { currentBucket, fetchPolicies, showAlert } = this.props
if (this.prefix.value === "*")
this.prefix.value = ""
if (this.prefix.value === "*") this.prefix.value = ""
let policyAlreadyExists = this.props.policies.some(
elem => this.prefix.value === elem.prefix && this.policy.value === elem.policy
elem =>
this.prefix.value === elem.prefix && this.policy.value === elem.policy,
)
if (policyAlreadyExists) {
showAlert("danger", "Policy for this prefix already exists.")
return
}
web.
SetBucketPolicy({
web
.SetBucketPolicy({
bucketName: currentBucket,
prefix: this.prefix.value,
policy: this.policy.value
policy: this.policy.value,
})
.then(() => {
fetchPolicies(currentBucket)
this.prefix.value = ''
this.prefix.value = ""
})
.catch(e => showAlert("danger", e.message))
}
render() {
return (
<header className="pmb-list">
<div className="pmbl-item">
<input
<div className="policy__row policy__row--add">
<div className="form-group">
<input
type="text"
ref={ prefix => this.prefix = prefix }
className="form-control"
ref={prefix => (this.prefix = prefix)}
className="form-group__field"
placeholder="Prefix"
/>
<i className="form-group__helper" />
</div>
<div className="pmbl-item">
<select ref={ policy => this.policy = policy } className="form-control">
<option value={ READ_ONLY }>
Read Only
</option>
<option value={ WRITE_ONLY }>
Write Only
</option>
<option value={ READ_WRITE }>
Read and Write
</option>
<div className="form-group policy__access">
<select
ref={policy => (this.policy = policy)}
className="form-group__field select"
>
<option value={READ_ONLY}>Read Only</option>
<option value={WRITE_ONLY}>Write Only</option>
<option value={READ_WRITE}>Read and Write</option>
</select>
<i className="form-group__helper" />
</div>
<div className="pmbl-item">
<button className="btn btn-block btn-primary" onClick={ this.handlePolicySubmit.bind(this) }>
Add
</button>
</div>
</header>
<button
className="btn btn--sm btn--primary"
onClick={this.handlePolicySubmit.bind(this)}
>
Add
</button>
</div>
)
}
}
@@ -99,7 +99,7 @@ export class PolicyInput extends React.Component {
const mapStateToProps = state => {
return {
currentBucket: state.buckets.currentBucket,
policies: state.buckets.policies
policies: state.buckets.policies,
}
}
@@ -108,8 +108,13 @@ const mapDispatchToProps = dispatch => {
fetchPolicies: bucket => dispatch(actionsBuckets.fetchPolicies(bucket)),
setPolicies: policies => dispatch(actionsBuckets.setPolicies(policies)),
showAlert: (type, message) =>
dispatch(actionsAlert.set({ type: type, message: message }))
dispatch(
actionsAlert.set({
type: type,
message: message,
}),
),
}
}
export default connect(mapStateToProps, mapDispatchToProps)(PolicyInput)
export default connect(mapStateToProps, mapDispatchToProps)(PolicyInput)

View File

@@ -26,9 +26,11 @@ describe("Bucket", () => {
it("should call selectBucket when clicked", () => {
const selectBucket = jest.fn()
const wrapper = shallow(
<Bucket bucket={"test"} selectBucket={selectBucket} />
<Bucket bucket={"test"} selectBucket={selectBucket} />,
)
wrapper.find("li").simulate("click", { preventDefault: jest.fn() })
wrapper.find("li").simulate("click", {
preventDefault: jest.fn(),
})
expect(selectBucket).toHaveBeenCalledWith("test")
})

View File

@@ -26,26 +26,28 @@ describe("BucketContainer", () => {
beforeEach(() => {
store = mockStore({
buckets: {
currentBucket: "Test"
}
currentBucket: "Test",
},
})
store.dispatch = jest.fn()
})
it("should render without crashing", () => {
shallow(<BucketContainer store={store}/>)
shallow(<BucketContainer store={store} />)
})
it('maps state and dispatch to props', () => {
const wrapper = shallow(<BucketContainer store={store}/>)
expect(wrapper.props()).toEqual(expect.objectContaining({
isActive: expect.any(Boolean),
selectBucket: expect.any(Function)
}))
it("maps state and dispatch to props", () => {
const wrapper = shallow(<BucketContainer store={store} />)
expect(wrapper.props()).toEqual(
expect.objectContaining({
isActive: expect.any(Boolean),
selectBucket: expect.any(Function),
}),
)
})
it('maps selectBucket to dispatch action', () => {
const wrapper = shallow(<BucketContainer store={store}/>)
it("maps selectBucket to dispatch action", () => {
const wrapper = shallow(<BucketContainer store={store} />)
wrapper.props().selectBucket()
expect(store.dispatch).toHaveBeenCalled()
})

View File

@@ -24,13 +24,9 @@ describe("BucketDropdown", () => {
})
it("should call toggleDropdown on dropdown toggle", () => {
const spy = jest.spyOn(BucketDropdown.prototype, 'toggleDropdown')
const wrapper = shallow(
<BucketDropdown />
)
wrapper
.find("Uncontrolled(Dropdown)")
.simulate("toggle")
const spy = jest.spyOn(BucketDropdown.prototype, "toggleDropdown")
const wrapper = shallow(<BucketDropdown />)
wrapper.find("Uncontrolled(Dropdown)").simulate("toggle")
expect(spy).toHaveBeenCalled()
spy.mockReset()
spy.mockRestore()
@@ -39,24 +35,28 @@ describe("BucketDropdown", () => {
it("should call showBucketPolicy when Edit Policy link is clicked", () => {
const showBucketPolicy = jest.fn()
const wrapper = shallow(
<BucketDropdown showBucketPolicy={showBucketPolicy} />
<BucketDropdown showBucketPolicy={showBucketPolicy} />,
)
wrapper
.find("li a")
.at(0)
.simulate("click", { stopPropagation: jest.fn() })
.simulate("click", {
stopPropagation: jest.fn(),
})
expect(showBucketPolicy).toHaveBeenCalled()
})
it("should call deleteBucket when Delete link is clicked", () => {
const deleteBucket = jest.fn()
const wrapper = shallow(
<BucketDropdown bucket={"test"} deleteBucket={deleteBucket} />
<BucketDropdown bucket={"test"} deleteBucket={deleteBucket} />,
)
wrapper
.find("li a")
.at(1)
.simulate("click", { stopPropagation: jest.fn() })
.simulate("click", {
stopPropagation: jest.fn(),
})
expect(deleteBucket).toHaveBeenCalledWith("test")
})
})

View File

@@ -23,7 +23,7 @@ jest.mock("../../web", () => ({
LoggedIn: jest
.fn(() => false)
.mockReturnValueOnce(true)
.mockReturnValueOnce(true)
.mockReturnValueOnce(true),
}))
describe("BucketList", () => {
@@ -35,7 +35,7 @@ describe("BucketList", () => {
it("should call fetchBuckets before component is mounted", () => {
const fetchBuckets = jest.fn()
const wrapper = shallow(
<BucketList visibleBuckets={[]} fetchBuckets={fetchBuckets} />
<BucketList visibleBuckets={[]} fetchBuckets={fetchBuckets} />,
)
expect(fetchBuckets).toHaveBeenCalled()
})
@@ -49,7 +49,7 @@ describe("BucketList", () => {
visibleBuckets={[]}
setBucketList={setBucketList}
selectBucket={selectBucket}
/>
/>,
)
expect(setBucketList).toHaveBeenCalledWith(["bk1"])
expect(selectBucket).toHaveBeenCalledWith("bk1", "pre1")

View File

@@ -21,13 +21,13 @@ import { READ_ONLY, WRITE_ONLY, READ_WRITE } from "../../constants"
describe("BucketPolicyModal", () => {
it("should render without crashing", () => {
shallow(<BucketPolicyModal policies={[]}/>)
shallow(<BucketPolicyModal policies={[]} />)
})
it("should call hideBucketPolicy when close button is clicked", () => {
const hideBucketPolicy = jest.fn()
const wrapper = shallow(
<BucketPolicyModal hideBucketPolicy={hideBucketPolicy} policies={[]} />
<BucketPolicyModal hideBucketPolicy={hideBucketPolicy} policies={[]} />,
)
wrapper.find("button").simulate("click")
expect(hideBucketPolicy).toHaveBeenCalled()
@@ -35,7 +35,7 @@ describe("BucketPolicyModal", () => {
it("should include the PolicyInput and Policy components when there are any policies", () => {
const wrapper = shallow(
<BucketPolicyModal policies={ [{prefix: "test", policy: READ_ONLY}] } />
<BucketPolicyModal policies={[{ prefix: "test", policy: READ_ONLY }]} />,
)
expect(wrapper.find("Connect(PolicyInput)").length).toBe(1)
expect(wrapper.find("Connect(Policy)").length).toBe(1)

View File

@@ -26,7 +26,11 @@ describe("BucketSearch", () => {
it("should call onChange with search text", () => {
const onChange = jest.fn()
const wrapper = shallow(<BucketSearch onChange={onChange} />)
wrapper.find("input").simulate("change", { target: { value: "test" } })
wrapper.find("input").simulate("change", {
target: {
value: "test",
},
})
expect(onChange).toHaveBeenCalledWith("test")
})
})

View File

@@ -26,7 +26,7 @@ describe("MakeBucketModal", () => {
it("should call hideMakeBucketModal when close button is clicked", () => {
const hideMakeBucketModal = jest.fn()
const wrapper = shallow(
<MakeBucketModal hideMakeBucketModal={hideMakeBucketModal} />
<MakeBucketModal hideMakeBucketModal={hideMakeBucketModal} />,
)
wrapper.find("button").simulate("click")
expect(hideMakeBucketModal).toHaveBeenCalled()
@@ -35,10 +35,12 @@ describe("MakeBucketModal", () => {
it("bucketName should be cleared before hiding the modal", () => {
const hideMakeBucketModal = jest.fn()
const wrapper = shallow(
<MakeBucketModal hideMakeBucketModal={hideMakeBucketModal} />
<MakeBucketModal hideMakeBucketModal={hideMakeBucketModal} />,
)
wrapper.find("input").simulate("change", {
target: { value: "test" }
target: {
value: "test",
},
})
expect(wrapper.state("bucketName")).toBe("test")
wrapper.find("button").simulate("click")
@@ -52,12 +54,16 @@ describe("MakeBucketModal", () => {
<MakeBucketModal
makeBucket={makeBucket}
hideMakeBucketModal={hideMakeBucketModal}
/>
/>,
)
wrapper.find("input").simulate("change", {
target: { value: "test" }
target: {
value: "test",
},
})
wrapper.find("form").simulate("submit", {
preventDefault: jest.fn(),
})
wrapper.find("form").simulate("submit", { preventDefault: jest.fn() })
expect(makeBucket).toHaveBeenCalledWith("test")
})
@@ -68,12 +74,16 @@ describe("MakeBucketModal", () => {
<MakeBucketModal
makeBucket={makeBucket}
hideMakeBucketModal={hideMakeBucketModal}
/>
/>,
)
wrapper.find("input").simulate("change", {
target: { value: "test" }
target: {
value: "test",
},
})
wrapper.find("form").simulate("submit", {
preventDefault: jest.fn(),
})
wrapper.find("form").simulate("submit", { preventDefault: jest.fn() })
expect(hideMakeBucketModal).toHaveBeenCalled()
expect(wrapper.state("bucketName")).toBe("")
})

View File

@@ -23,32 +23,36 @@ import web from "../../web"
jest.mock("../../web", () => ({
SetBucketPolicy: jest.fn(() => {
return Promise.resolve()
})
}),
}))
describe("Policy", () => {
it("should render without crashing", () => {
shallow(<Policy currentBucket={"bucket"} prefix={"foo"} policy={READ_ONLY} />)
shallow(
<Policy currentBucket={"bucket"} prefix={"foo"} policy={READ_ONLY} />,
)
})
it("should call web.setBucketPolicy and fetchPolicies on submit", () => {
const fetchPolicies = jest.fn()
const wrapper = shallow(
<Policy
<Policy
currentBucket={"bucket"}
prefix={"foo"}
policy={READ_ONLY}
fetchPolicies={fetchPolicies}
/>
/>,
)
wrapper.find("button").simulate("click", { preventDefault: jest.fn() })
wrapper.find("button").simulate("click", {
preventDefault: jest.fn(),
})
expect(web.SetBucketPolicy).toHaveBeenCalledWith({
bucketName: "bucket",
prefix: "foo",
policy: "none"
policy: "none",
})
setImmediate(() => {
expect(fetchPolicies).toHaveBeenCalledWith("bucket")
})
@@ -56,8 +60,13 @@ describe("Policy", () => {
it("should change the empty string to '*' while displaying prefixes", () => {
const wrapper = shallow(
<Policy currentBucket={"bucket"} prefix={""} policy={READ_ONLY} />
<Policy currentBucket={"bucket"} prefix={""} policy={READ_ONLY} />,
)
expect(wrapper.find(".pmbl-item").at(0).text()).toEqual("*")
expect(
wrapper
.find(".pmbl-item")
.at(0)
.text(),
).toEqual("*")
})
})

View File

@@ -23,19 +23,21 @@ import web from "../../web"
jest.mock("../../web", () => ({
SetBucketPolicy: jest.fn(() => {
return Promise.resolve()
})
}),
}))
describe("PolicyInput", () => {
it("should render without crashing", () => {
const fetchPolicies = jest.fn()
shallow(<PolicyInput currentBucket={"bucket"} fetchPolicies={fetchPolicies}/>)
shallow(
<PolicyInput currentBucket={"bucket"} fetchPolicies={fetchPolicies} />,
)
})
it("should call fetchPolicies after the component has mounted", () => {
const fetchPolicies = jest.fn()
const wrapper = shallow(
<PolicyInput currentBucket={"bucket"} fetchPolicies={fetchPolicies} />
<PolicyInput currentBucket={"bucket"} fetchPolicies={fetchPolicies} />,
)
setImmediate(() => {
expect(fetchPolicies).toHaveBeenCalled()
@@ -45,16 +47,26 @@ describe("PolicyInput", () => {
it("should call web.setBucketPolicy and fetchPolicies on submit", () => {
const fetchPolicies = jest.fn()
const wrapper = shallow(
<PolicyInput currentBucket={"bucket"} policies={[]} fetchPolicies={fetchPolicies}/>
<PolicyInput
currentBucket={"bucket"}
policies={[]}
fetchPolicies={fetchPolicies}
/>,
)
wrapper.instance().prefix = { value: "baz" }
wrapper.instance().policy = { value: READ_ONLY }
wrapper.find("button").simulate("click", { preventDefault: jest.fn() })
wrapper.instance().prefix = {
value: "baz",
}
wrapper.instance().policy = {
value: READ_ONLY,
}
wrapper.find("button").simulate("click", {
preventDefault: jest.fn(),
})
expect(web.SetBucketPolicy).toHaveBeenCalledWith({
bucketName: "bucket",
prefix: "baz",
policy: READ_ONLY
policy: READ_ONLY,
})
setImmediate(() => {
@@ -65,13 +77,25 @@ describe("PolicyInput", () => {
it("should change the prefix '*' to an empty string", () => {
const fetchPolicies = jest.fn()
const wrapper = shallow(
<PolicyInput currentBucket={"bucket"} policies={[]} fetchPolicies={fetchPolicies}/>
<PolicyInput
currentBucket={"bucket"}
policies={[]}
fetchPolicies={fetchPolicies}
/>,
)
wrapper.instance().prefix = { value: "*" }
wrapper.instance().policy = { value: READ_ONLY }
wrapper.instance().prefix = {
value: "*",
}
wrapper.instance().policy = {
value: READ_ONLY,
}
wrapper.find("button").simulate("click", { preventDefault: jest.fn() })
wrapper.find("button").simulate("click", {
preventDefault: jest.fn(),
})
expect(wrapper.instance().prefix).toEqual({ value: "" })
expect(wrapper.instance().prefix).toEqual({
value: "",
})
})
})

View File

@@ -17,23 +17,31 @@
import configureStore from "redux-mock-store"
import thunk from "redux-thunk"
import * as actionsBuckets from "../actions"
import * as objectActions from "../../objects/actions"
import history from "../../history"
jest.mock("../../web", () => ({
ListBuckets: jest.fn(() => {
return Promise.resolve({ buckets: [{ name: "test1" }, { name: "test2" }] })
return Promise.resolve({
buckets: [
{
name: "test1",
},
{
name: "test2",
},
],
})
}),
MakeBucket: jest.fn(() => {
return Promise.resolve()
}),
DeleteBucket: jest.fn(() => {
return Promise.resolve()
})
}),
}))
jest.mock("../../objects/actions", () => ({
selectPrefix: () => dispatch => {}
selectPrefix: () => dispatch => {},
}))
const middlewares = [thunk]
@@ -43,8 +51,14 @@ describe("Buckets actions", () => {
it("creates buckets/SET_LIST and buckets/SET_CURRENT_BUCKET with first bucket after fetching the buckets", () => {
const store = mockStore()
const expectedActions = [
{ type: "buckets/SET_LIST", buckets: ["test1", "test2"] },
{ type: "buckets/SET_CURRENT_BUCKET", bucket: "test1" }
{
type: "buckets/SET_LIST",
buckets: ["test1", "test2"],
},
{
type: "buckets/SET_CURRENT_BUCKET",
bucket: "test1",
},
]
return store.dispatch(actionsBuckets.fetchBuckets()).then(() => {
const actions = store.getActions()
@@ -56,8 +70,14 @@ describe("Buckets actions", () => {
history.push("/test2")
const store = mockStore()
const expectedActions = [
{ type: "buckets/SET_LIST", buckets: ["test1", "test2"] },
{ type: "buckets/SET_CURRENT_BUCKET", bucket: "test2" }
{
type: "buckets/SET_LIST",
buckets: ["test1", "test2"],
},
{
type: "buckets/SET_CURRENT_BUCKET",
bucket: "test2",
},
]
window.location
return store.dispatch(actionsBuckets.fetchBuckets()).then(() => {
@@ -70,8 +90,14 @@ describe("Buckets actions", () => {
history.push("/test3")
const store = mockStore()
const expectedActions = [
{ type: "buckets/SET_LIST", buckets: ["test1", "test2"] },
{ type: "buckets/SET_CURRENT_BUCKET", bucket: "test1" }
{
type: "buckets/SET_LIST",
buckets: ["test1", "test2"],
},
{
type: "buckets/SET_CURRENT_BUCKET",
bucket: "test1",
},
]
window.location
return store.dispatch(actionsBuckets.fetchBuckets()).then(() => {
@@ -83,7 +109,10 @@ describe("Buckets actions", () => {
it("creates buckets/SET_CURRENT_BUCKET action when selectBucket is called", () => {
const store = mockStore()
const expectedActions = [
{ type: "buckets/SET_CURRENT_BUCKET", bucket: "test1" }
{
type: "buckets/SET_CURRENT_BUCKET",
bucket: "test1",
},
]
store.dispatch(actionsBuckets.selectBucket("test1"))
const actions = store.getActions()
@@ -93,7 +122,10 @@ describe("Buckets actions", () => {
it("creates buckets/SHOW_MAKE_BUCKET_MODAL for showMakeBucketModal", () => {
const store = mockStore()
const expectedActions = [
{ type: "buckets/SHOW_MAKE_BUCKET_MODAL", show: true }
{
type: "buckets/SHOW_MAKE_BUCKET_MODAL",
show: true,
},
]
store.dispatch(actionsBuckets.showMakeBucketModal())
const actions = store.getActions()
@@ -103,7 +135,10 @@ describe("Buckets actions", () => {
it("creates buckets/SHOW_MAKE_BUCKET_MODAL for hideMakeBucketModal", () => {
const store = mockStore()
const expectedActions = [
{ type: "buckets/SHOW_MAKE_BUCKET_MODAL", show: false }
{
type: "buckets/SHOW_MAKE_BUCKET_MODAL",
show: false,
},
]
store.dispatch(actionsBuckets.hideMakeBucketModal())
const actions = store.getActions()
@@ -113,7 +148,10 @@ describe("Buckets actions", () => {
it("creates buckets/SHOW_BUCKET_POLICY for showBucketPolicy", () => {
const store = mockStore()
const expectedActions = [
{ type: "buckets/SHOW_BUCKET_POLICY", show: true }
{
type: "buckets/SHOW_BUCKET_POLICY",
show: true,
},
]
store.dispatch(actionsBuckets.showBucketPolicy())
const actions = store.getActions()
@@ -123,7 +161,10 @@ describe("Buckets actions", () => {
it("creates buckets/SHOW_BUCKET_POLICY for hideBucketPolicy", () => {
const store = mockStore()
const expectedActions = [
{ type: "buckets/SHOW_BUCKET_POLICY", show: false }
{
type: "buckets/SHOW_BUCKET_POLICY",
show: false,
},
]
store.dispatch(actionsBuckets.hideBucketPolicy())
const actions = store.getActions()
@@ -133,7 +174,10 @@ describe("Buckets actions", () => {
it("creates buckets/SET_POLICIES action", () => {
const store = mockStore()
const expectedActions = [
{ type: "buckets/SET_POLICIES", policies: ["test1", "test2"] }
{
type: "buckets/SET_POLICIES",
policies: ["test1", "test2"],
},
]
store.dispatch(actionsBuckets.setPolicies(["test1", "test2"]))
const actions = store.getActions()
@@ -142,7 +186,12 @@ describe("Buckets actions", () => {
it("creates buckets/ADD action", () => {
const store = mockStore()
const expectedActions = [{ type: "buckets/ADD", bucket: "test" }]
const expectedActions = [
{
type: "buckets/ADD",
bucket: "test",
},
]
store.dispatch(actionsBuckets.addBucket("test"))
const actions = store.getActions()
expect(actions).toEqual(expectedActions)
@@ -150,7 +199,12 @@ describe("Buckets actions", () => {
it("creates buckets/REMOVE action", () => {
const store = mockStore()
const expectedActions = [{ type: "buckets/REMOVE", bucket: "test" }]
const expectedActions = [
{
type: "buckets/REMOVE",
bucket: "test",
},
]
store.dispatch(actionsBuckets.removeBucket("test"))
const actions = store.getActions()
expect(actions).toEqual(expectedActions)
@@ -159,8 +213,14 @@ describe("Buckets actions", () => {
it("creates buckets/ADD and buckets/SET_CURRENT_BUCKET after creating the bucket", () => {
const store = mockStore()
const expectedActions = [
{ type: "buckets/ADD", bucket: "test1" },
{ type: "buckets/SET_CURRENT_BUCKET", bucket: "test1" }
{
type: "buckets/ADD",
bucket: "test1",
},
{
type: "buckets/SET_CURRENT_BUCKET",
bucket: "test1",
},
]
return store.dispatch(actionsBuckets.makeBucket("test1")).then(() => {
const actions = store.getActions()
@@ -168,18 +228,37 @@ describe("Buckets actions", () => {
})
})
it("creates alert/SET, buckets/REMOVE, buckets/SET_LIST and buckets/SET_CURRENT_BUCKET " +
"after deleting the bucket", () => {
const store = mockStore()
const expectedActions = [
{ type: "alert/SET", alert: {id: 0, message: "Bucket 'test3' has been deleted.", type: "info"} },
{ type: "buckets/REMOVE", bucket: "test3" },
{ type: "buckets/SET_LIST", buckets: ["test1", "test2"] },
{ type: "buckets/SET_CURRENT_BUCKET", bucket: "test1" }
]
return store.dispatch(actionsBuckets.deleteBucket("test3")).then(() => {
const actions = store.getActions()
expect(actions).toEqual(expectedActions)
})
})
it(
"creates alert/SET, buckets/REMOVE, buckets/SET_LIST and buckets/SET_CURRENT_BUCKET " +
"after deleting the bucket",
() => {
const store = mockStore()
const expectedActions = [
{
type: "alert/SET",
alert: {
id: 0,
message: "Bucket 'test3' has been deleted.",
type: "info",
},
},
{
type: "buckets/REMOVE",
bucket: "test3",
},
{
type: "buckets/SET_LIST",
buckets: ["test1", "test2"],
},
{
type: "buckets/SET_CURRENT_BUCKET",
bucket: "test1",
},
]
return store.dispatch(actionsBuckets.deleteBucket("test3")).then(() => {
const actions = store.getActions()
expect(actions).toEqual(expectedActions)
})
},
)
})

View File

@@ -26,36 +26,40 @@ describe("buckets reducer", () => {
filter: "",
currentBucket: "",
showBucketPolicy: false,
showMakeBucketModal: false
showMakeBucketModal: false,
})
})
it("should handle SET_LIST", () => {
const newState = reducer(undefined, {
type: actions.SET_LIST,
buckets: ["bk1", "bk2"]
buckets: ["bk1", "bk2"],
})
expect(newState.list).toEqual(["bk1", "bk2"])
})
it("should handle ADD", () => {
const newState = reducer(
{ list: ["test1", "test2"] },
{
list: ["test1", "test2"],
},
{
type: actions.ADD,
bucket: "test3"
}
bucket: "test3",
},
)
expect(newState.list).toEqual(["test3", "test1", "test2"])
})
it("should handle REMOVE", () => {
const newState = reducer(
{ list: ["test1", "test2"] },
{
list: ["test1", "test2"],
},
{
type: actions.REMOVE,
bucket: "test2"
}
bucket: "test2",
},
)
expect(newState.list).toEqual(["test1"])
})
@@ -63,7 +67,7 @@ describe("buckets reducer", () => {
it("should handle SET_FILTER", () => {
const newState = reducer(undefined, {
type: actions.SET_FILTER,
filter: "test"
filter: "test",
})
expect(newState.filter).toEqual("test")
})
@@ -71,7 +75,7 @@ describe("buckets reducer", () => {
it("should handle SET_CURRENT_BUCKET", () => {
const newState = reducer(undefined, {
type: actions.SET_CURRENT_BUCKET,
bucket: "test"
bucket: "test",
})
expect(newState.currentBucket).toEqual("test")
})
@@ -79,7 +83,7 @@ describe("buckets reducer", () => {
it("should handle SET_POLICIES", () => {
const newState = reducer(undefined, {
type: actions.SET_POLICIES,
policies: ["test1", "test2"]
policies: ["test1", "test2"],
})
expect(newState.policies).toEqual(["test1", "test2"])
})
@@ -87,15 +91,15 @@ describe("buckets reducer", () => {
it("should handle SHOW_BUCKET_POLICY", () => {
const newState = reducer(undefined, {
type: actions.SHOW_BUCKET_POLICY,
show: true
show: true,
})
expect(newState.showBucketPolicy).toBeTruthy()
})
it("should handle SHOW_MAKE_BUCKET_MODAL", () => {
const newState = reducer(undefined, {
type: actions.SHOW_MAKE_BUCKET_MODAL,
show: true
show: true,
})
expect(newState.showMakeBucketModal).toBeTruthy()
})

View File

@@ -21,8 +21,8 @@ describe("getVisibleBuckets", () => {
beforeEach(() => {
state = {
buckets: {
list: ["test1", "test11", "test2"]
}
list: ["test1", "test11", "test2"],
},
}
})

View File

@@ -52,14 +52,14 @@ export const fetchBuckets = () => {
export const setList = buckets => {
return {
type: SET_LIST,
buckets
buckets,
}
}
export const setFilter = filter => {
return {
type: SET_FILTER,
filter
filter,
}
}
@@ -73,7 +73,7 @@ export const selectBucket = (bucket, prefix) => {
export const setCurrentBucket = bucket => {
return {
type: SET_CURRENT_BUCKET,
bucket
bucket,
}
}
@@ -81,7 +81,7 @@ export const makeBucket = bucket => {
return function(dispatch) {
return web
.MakeBucket({
bucketName: bucket
bucketName: bucket,
})
.then(() => {
dispatch(addBucket(bucket))
@@ -91,9 +91,9 @@ export const makeBucket = bucket => {
dispatch(
alertActions.set({
type: "danger",
message: err.message
})
)
message: err.message,
}),
),
)
}
}
@@ -102,24 +102,24 @@ export const deleteBucket = bucket => {
return function(dispatch) {
return web
.DeleteBucket({
bucketName: bucket
bucketName: bucket,
})
.then(() => {
dispatch(
alertActions.set({
type: "info",
message: "Bucket '" + bucket + "' has been deleted."
})
message: "Bucket '" + bucket + "' has been deleted.",
}),
)
dispatch(removeBucket(bucket))
dispatch(fetchBuckets())
})
.catch(err => {
.catch(err => {
dispatch(
alertActions.set({
type: "danger",
message: err.message
})
message: err.message,
}),
)
})
}
@@ -127,43 +127,41 @@ export const deleteBucket = bucket => {
export const addBucket = bucket => ({
type: ADD,
bucket
bucket,
})
export const removeBucket = bucket => ({
type: REMOVE,
bucket
bucket,
})
export const showMakeBucketModal = () => ({
type: SHOW_MAKE_BUCKET_MODAL,
show: true
show: true,
})
export const hideMakeBucketModal = () => ({
type: SHOW_MAKE_BUCKET_MODAL,
show: false
show: false,
})
export const fetchPolicies = bucket => {
return function(dispatch) {
return web
.ListAllBucketPolicies({
bucketName: bucket
bucketName: bucket,
})
.then(res => {
let policies = res.policies
if(policies)
dispatch(setPolicies(policies))
else
dispatch(setPolicies([]))
if (policies) dispatch(setPolicies(policies))
else dispatch(setPolicies([]))
})
.catch(err => {
dispatch(
alertActions.set({
type: "danger",
message: err.message
})
message: err.message,
}),
)
})
}
@@ -171,15 +169,15 @@ export const fetchPolicies = bucket => {
export const setPolicies = policies => ({
type: SET_POLICIES,
policies
policies,
})
export const showBucketPolicy = () => ({
type: SHOW_BUCKET_POLICY,
show: true
show: true,
})
export const hideBucketPolicy = () => ({
type: SHOW_BUCKET_POLICY,
show: false
})
show: false,
})

View File

@@ -31,20 +31,20 @@ export default (
currentBucket: "",
showMakeBucketModal: false,
policies: [],
showBucketPolicy: false
showBucketPolicy: false,
},
action
action,
) => {
switch (action.type) {
case actionsBuckets.SET_LIST:
return {
...state,
list: action.buckets
list: action.buckets,
}
case actionsBuckets.ADD:
return {
...state,
list: [action.bucket, ...state.list]
list: [action.bucket, ...state.list],
}
case actionsBuckets.REMOVE:
return {
@@ -54,27 +54,27 @@ export default (
case actionsBuckets.SET_FILTER:
return {
...state,
filter: action.filter
filter: action.filter,
}
case actionsBuckets.SET_CURRENT_BUCKET:
return {
...state,
currentBucket: action.bucket
currentBucket: action.bucket,
}
case actionsBuckets.SHOW_MAKE_BUCKET_MODAL:
return {
...state,
showMakeBucketModal: action.show
showMakeBucketModal: action.show,
}
case actionsBuckets.SET_POLICIES:
return {
...state,
policies: action.policies
policies: action.policies,
}
case actionsBuckets.SHOW_BUCKET_POLICY:
return {
...state,
showBucketPolicy: action.show
showBucketPolicy: action.show,
}
default:
return state

View File

@@ -22,7 +22,7 @@ const bucketsFilterSelector = state => state.buckets.filter
export const getVisibleBuckets = createSelector(
bucketsSelector,
bucketsFilterSelector,
(buckets, filter) => buckets.filter(bucket => bucket.indexOf(filter) > -1)
(buckets, filter) => buckets.filter(bucket => bucket.indexOf(filter) > -1),
)
export const getCurrentBucket = state => state.buckets.currentBucket