Add missing unit tests to JavaScript and React components (#5505)

Add the missing unit tests login, bucket listing, and bucket searching functionalities.
This commit is contained in:
Kaan Kabalak 2018-02-12 13:27:52 -08:00 committed by Harshavardhana
parent feb726dd98
commit ead6337eab
14 changed files with 354 additions and 31 deletions

View File

@ -54,4 +54,16 @@ describe("Alert actions", () => {
const actions = store.getActions()
expect(actions).toEqual(expectedActions)
})
it("creates alert/CLEAR action directly", () => {
const store = mockStore()
const expectedActions = [
{
type: "alert/CLEAR"
}
]
store.dispatch(actionsAlert.clear())
const actions = store.getActions()
expect(actions).toEqual(expectedActions)
})
})

View File

@ -40,6 +40,26 @@ describe("Buckets actions", () => {
})
})
it("creates buckets/SET_LIST directly", () => {
const store = mockStore()
const expectedActions = [
{ type: "buckets/SET_LIST", buckets: ["test1", "test2"] }
]
store.dispatch(actionsBuckets.setList(["test1", "test2"]))
const actions = store.getActions()
expect(actions).toEqual(expectedActions)
})
it("creates buckets/SET_FILTER directly", () => {
const store = mockStore()
const expectedActions = [
{ type: "buckets/SET_FILTER", filter: "test" }
]
store.dispatch(actionsBuckets.setFilter("test"))
const actions = store.getActions()
expect(actions).toEqual(expectedActions)
})
it("should update browser url and creates buckets/SET_CURRENT_BUCKET action when selectBucket is called", () => {
const store = mockStore()
const expectedActions = [

View File

@ -28,21 +28,16 @@ import { Redirect } from "react-router-dom"
export class Login extends React.Component {
handleSubmit(event) {
event.preventDefault()
const { dispatch, history } = this.props
const { showAlert, history } = this.props
let message = ""
if (!document.getElementById("accessKey").value) {
message = "Secret Key cannot be empty"
}
if (!document.getElementById("secretKey").value) {
message = "Access Key cannot be empty"
}
if (!document.getElementById("secretKey").value) {
message = "Secret Key cannot be empty"
}
if (message) {
dispatch(
actionsAlert.set({
type: "danger",
message
})
)
showAlert("danger", message)
return
}
web
@ -54,19 +49,14 @@ export class Login extends React.Component {
history.push(minioBrowserPrefix)
})
.catch(e => {
dispatch(
actionsAlert.set({
type: "danger",
message: e.message
})
)
showAlert("danger", e.message)
})
}
componentWillMount() {
const { dispatch } = this.props
const { clearAlert } = this.props
// Clear out any stale message in the alert of previous page
dispatch(actionsAlert.clear())
clearAlert()
document.body.classList.add("is-guest")
}
@ -74,17 +64,12 @@ export class Login extends React.Component {
document.body.classList.remove("is-guest")
}
clearAlert() {
const { dispatch } = this.props
dispatch(actionsAlert.clear())
}
render() {
const { alert } = this.props
const { clearAlert, alert } = this.props
if (web.LoggedIn()) {
return <Redirect to={minioBrowserPrefix} />
}
let alertBox = <Alert {...alert} onDismiss={this.clearAlert.bind(this)} />
let alertBox = <Alert {...alert} onDismiss={clearAlert} />
// Make sure you don't show a fading out alert box on the initial web-page load.
if (!alert.message) alertBox = ""
return (
@ -128,4 +113,11 @@ export class Login extends React.Component {
}
}
export default connect(state => state)(Login)
const mapDispatchToProps = dispatch => {
return {
showAlert: (type, message) => dispatch(actionsAlert.set({type: type, message: message})),
clearAlert: () => dispatch(actionsAlert.clear())
}
}
export default connect(state => state, mapDispatchToProps)(Login)

View File

@ -0,0 +1,34 @@
/*
* Minio Cloud Storage (C) 2018 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 Alert from "../Alert"
describe("Alert", () => {
it("should render without crashing", () => {
shallow(<Alert />)
})
it("should call onDismiss when close button is clicked", () => {
const onDismiss = jest.fn()
const wrapper = mount(
<Alert show={true} type="danger" message="test" onDismiss={onDismiss}/>
)
wrapper.find("button").simulate("click", { preventDefault: jest.fn() })
expect(onDismiss).toHaveBeenCalled()
})
})

View File

@ -0,0 +1,25 @@
/*
* Minio Cloud Storage (C) 2018 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 App from "../App"
describe("App", () => {
it("should render without crashing", () => {
shallow(<App match={ {url: "/minio"} }/>)
})
})

View File

@ -0,0 +1,29 @@
/*
* Minio Cloud Storage (C) 2018 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 Browser from "../Browser"
import configureStore from "redux-mock-store"
const mockStore = configureStore()
describe("Browser", () => {
it("should render without crashing", () => {
const store = mockStore()
shallow(<Browser store={store}/>)
})
})

View File

@ -0,0 +1,52 @@
/*
* Minio Cloud Storage (C) 2018 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 BucketContainer from "../BucketContainer"
import configureStore from "redux-mock-store"
const mockStore = configureStore()
describe("BucketContainer", () => {
let store
beforeEach(() => {
store = mockStore({
buckets: {
currentBucket: "Test"
}
})
store.dispatch = jest.fn()
})
it("should render without crashing", () => {
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 selectBucket to dispatch action', () => {
const wrapper = shallow(<BucketContainer store={store}/>)
wrapper.props().selectBucket()
expect(store.dispatch).toHaveBeenCalled()
})
})

View File

@ -18,7 +18,12 @@ import React from "react"
import { shallow } from "enzyme"
import { BucketList } from "../BucketList"
describe("Bucket", () => {
describe("BucketList", () => {
it("should render without crashing", () => {
const fetchBuckets = jest.fn()
shallow(<BucketList visibleBuckets={[]} fetchBuckets={fetchBuckets} />)
})
it("should call fetchBuckets before component is mounted", () => {
const fetchBuckets = jest.fn()
const wrapper = shallow(

View File

@ -0,0 +1,25 @@
/*
* Minio Cloud Storage (C) 2018 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 Host from "../Host"
describe("Host", () => {
it("should render without crashing", () => {
shallow(<Host />)
})
})

View File

@ -0,0 +1,99 @@
/*
* Minio Cloud Storage (C) 2018 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 { Login } from "../Login"
import web from "../../web"
jest.mock('../../web', () => ({
Login: jest.fn(() => {
return Promise.resolve({ token: "test", uiVersion: "2018-02-01T01:17:47Z" })
}),
LoggedIn: jest.fn()
}))
describe("Login", () => {
const dispatchMock = jest.fn()
const showAlertMock = jest.fn()
const clearAlertMock = jest.fn()
it("should render without crashing", () => {
shallow(<Login
dispatch={dispatchMock}
alert={{ show: false, type: "danger"}}
showAlert={showAlertMock}
clearAlert={clearAlertMock}
/>)
})
it("should initially have the is-guest class", () => {
const wrapper = shallow(
<Login
dispatch={dispatchMock}
alert={{ show: false, type: "danger"}}
showAlert={showAlertMock}
clearAlert={clearAlertMock}
/>,
{ attachTo: document.body }
)
expect(document.body.classList.contains("is-guest")).toBeTruthy()
})
it("should throw an alert if the keys are empty in login form", () => {
const wrapper = mount(
<Login
dispatch={dispatchMock}
alert={{ show: false, type: "danger"}}
showAlert={showAlertMock}
clearAlert={clearAlertMock}
/>,
{ attachTo: document.body }
)
// case where both keys are empty - displays the second warning
wrapper.find("form").simulate("submit")
expect(showAlertMock).toHaveBeenCalledWith("danger", "Secret Key cannot be empty")
// case where access key is empty
document.getElementById("secretKey").value = "secretKey"
wrapper.find("form").simulate("submit")
expect(showAlertMock).toHaveBeenCalledWith("danger", "Access Key cannot be empty")
// case where secret key is empty
document.getElementById("accessKey").value = "accessKey"
wrapper.find("form").simulate("submit")
expect(showAlertMock).toHaveBeenCalledWith("danger", "Secret Key cannot be empty")
})
it("should call web.Login with correct arguments if both keys are entered", () => {
const wrapper = mount(
<Login
dispatch={dispatchMock}
alert={{ show: false, type: "danger"}}
showAlert={showAlertMock}
clearAlert={clearAlertMock}
/>,
{ attachTo: document.body }
)
document.getElementById("accessKey").value = "accessKey"
document.getElementById("secretKey").value = "secretKey"
wrapper.find("form").simulate("submit")
expect(web.Login).toHaveBeenCalledWith({
"username": "accessKey",
"password": "secretKey"
})
})
})

View File

@ -0,0 +1,27 @@
/*
* Minio Cloud Storage (C) 2018 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 { SideBar } from "../SideBar"
describe("SideBar", () => {
it("should render without crashing", () => {
shallow(<SideBar />)
})
// ClickOutHandler test to be added when corresponding function is added
})

View File

@ -0,0 +1 @@
module.exports = 'test-file-stub';

View File

@ -27,7 +27,7 @@ describe("buckets reducer", () => {
})
})
it("should handle SET_BUCKETS", () => {
it("should handle SET_LIST", () => {
const newState = reducer(undefined, {
type: actions.SET_LIST,
buckets: ["bk1", "bk2"]
@ -35,7 +35,7 @@ describe("buckets reducer", () => {
expect(newState.list).toEqual(["bk1", "bk2"])
})
it("should handle SET_BUCKETS_FILTER", () => {
it("should handle SET_FILTER", () => {
const newState = reducer(undefined, {
type: actions.SET_FILTER,
filter: "test"
@ -43,7 +43,7 @@ describe("buckets reducer", () => {
expect(newState.filter).toEqual("test")
})
it("should handle SELECT_BUCKET", () => {
it("should handle SET_CURRENT_BUCKET", () => {
const newState = reducer(undefined, {
type: actions.SET_CURRENT_BUCKET,
bucket: "test"

View File

@ -13,7 +13,9 @@
"setupTestFrameworkScriptFile": "./app/js/jest/setup.js",
"testURL": "https://localhost:8080",
"moduleNameMapper": {
"\\.(css|scss|svg)$": "identity-obj-proxy"
"\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$":
"<rootDir>/app/js/jest/__mocks__/fileMock.js",
"\\.(css|scss)$": "identity-obj-proxy"
}
},
"repository": {