diff --git a/browser/app/js/actions/__tests__/alert.test.js b/browser/app/js/actions/__tests__/alert.test.js index ca5b3e240..2602930cf 100644 --- a/browser/app/js/actions/__tests__/alert.test.js +++ b/browser/app/js/actions/__tests__/alert.test.js @@ -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) + }) }) diff --git a/browser/app/js/actions/__tests__/buckets.test.js b/browser/app/js/actions/__tests__/buckets.test.js index 36bb6ba9f..ac7fee43f 100644 --- a/browser/app/js/actions/__tests__/buckets.test.js +++ b/browser/app/js/actions/__tests__/buckets.test.js @@ -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 = [ diff --git a/browser/app/js/components/Login.js b/browser/app/js/components/Login.js index e74375942..3bc6aa7a2 100644 --- a/browser/app/js/components/Login.js +++ b/browser/app/js/components/Login.js @@ -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" + message = "Access Key cannot be empty" } if (!document.getElementById("secretKey").value) { - message = "Access Key cannot be empty" + 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 } - let alertBox = + let alertBox = // 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) diff --git a/browser/app/js/components/__tests__/Alert.test.js b/browser/app/js/components/__tests__/Alert.test.js new file mode 100644 index 000000000..5b8e3a492 --- /dev/null +++ b/browser/app/js/components/__tests__/Alert.test.js @@ -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() + }) + + it("should call onDismiss when close button is clicked", () => { + const onDismiss = jest.fn() + const wrapper = mount( + + ) + wrapper.find("button").simulate("click", { preventDefault: jest.fn() }) + expect(onDismiss).toHaveBeenCalled() + }) +}) diff --git a/browser/app/js/components/__tests__/App.test.js b/browser/app/js/components/__tests__/App.test.js new file mode 100644 index 000000000..7548cbacd --- /dev/null +++ b/browser/app/js/components/__tests__/App.test.js @@ -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() + }) +}) diff --git a/browser/app/js/components/__tests__/Browser.test.js b/browser/app/js/components/__tests__/Browser.test.js new file mode 100644 index 000000000..3bb5a0e45 --- /dev/null +++ b/browser/app/js/components/__tests__/Browser.test.js @@ -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() + }) +}) diff --git a/browser/app/js/components/__tests__/BucketContainer.test.js b/browser/app/js/components/__tests__/BucketContainer.test.js new file mode 100644 index 000000000..2c3807d8a --- /dev/null +++ b/browser/app/js/components/__tests__/BucketContainer.test.js @@ -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() + }) + + it('maps state and dispatch to props', () => { + const wrapper = shallow() + expect(wrapper.props()).toEqual(expect.objectContaining({ + isActive: expect.any(Boolean), + selectBucket: expect.any(Function) + })) + }) + + it('maps selectBucket to dispatch action', () => { + const wrapper = shallow() + wrapper.props().selectBucket() + expect(store.dispatch).toHaveBeenCalled() + }) +}) diff --git a/browser/app/js/components/__tests__/BucketList.test.js b/browser/app/js/components/__tests__/BucketList.test.js index cda8bf5ad..b64d29192 100644 --- a/browser/app/js/components/__tests__/BucketList.test.js +++ b/browser/app/js/components/__tests__/BucketList.test.js @@ -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() + }) + it("should call fetchBuckets before component is mounted", () => { const fetchBuckets = jest.fn() const wrapper = shallow( diff --git a/browser/app/js/components/__tests__/Host.test.js b/browser/app/js/components/__tests__/Host.test.js new file mode 100644 index 000000000..6fcea1026 --- /dev/null +++ b/browser/app/js/components/__tests__/Host.test.js @@ -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() + }) +}) diff --git a/browser/app/js/components/__tests__/Login.test.js b/browser/app/js/components/__tests__/Login.test.js new file mode 100644 index 000000000..f8e5f8775 --- /dev/null +++ b/browser/app/js/components/__tests__/Login.test.js @@ -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() + }) + + it("should initially have the is-guest class", () => { + const wrapper = shallow( + , + { 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( + , + { 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( + , + { 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" + }) + }) +}) diff --git a/browser/app/js/components/__tests__/SideBar.test.js b/browser/app/js/components/__tests__/SideBar.test.js new file mode 100644 index 000000000..f1020de29 --- /dev/null +++ b/browser/app/js/components/__tests__/SideBar.test.js @@ -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() + }) + + // ClickOutHandler test to be added when corresponding function is added +}) diff --git a/browser/app/js/jest/__mocks__/fileMock.js b/browser/app/js/jest/__mocks__/fileMock.js new file mode 100644 index 000000000..84c1da6fd --- /dev/null +++ b/browser/app/js/jest/__mocks__/fileMock.js @@ -0,0 +1 @@ +module.exports = 'test-file-stub'; \ No newline at end of file diff --git a/browser/app/js/reducers/__tests__/buckets.test.js b/browser/app/js/reducers/__tests__/buckets.test.js index e27e36cb3..38b68515e 100644 --- a/browser/app/js/reducers/__tests__/buckets.test.js +++ b/browser/app/js/reducers/__tests__/buckets.test.js @@ -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" diff --git a/browser/package.json b/browser/package.json index 3860e2d49..9a265d4f8 100644 --- a/browser/package.json +++ b/browser/package.json @@ -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)$": + "/app/js/jest/__mocks__/fileMock.js", + "\\.(css|scss)$": "identity-obj-proxy" } }, "repository": {