diff options
Diffstat (limited to 'ui-react')
18 files changed, 800 insertions, 55 deletions
diff --git a/ui-react/src/LoopUI.js b/ui-react/src/LoopUI.js index fb595ded0..ff3c4445a 100644 --- a/ui-react/src/LoopUI.js +++ b/ui-react/src/LoopUI.js @@ -33,6 +33,7 @@ import LoopLogs from './components/loop_viewer/logs/LoopLogs'; import LoopStatus from './components/loop_viewer/status/LoopStatus'; import UserService from './api/UserService'; import LoopCache from './api/LoopCache'; +import LoopActionService from './api/LoopActionService'; import { Route } from 'react-router-dom' import OpenLoopModal from './components/dialogs/OpenLoop/OpenLoopModal'; @@ -44,6 +45,7 @@ import LoopService from './api/LoopService'; import PerformAction from './components/dialogs/PerformActions'; import RefreshStatus from './components/dialogs/RefreshStatus'; import DeployLoop from './components/dialogs/DeployLoop'; +import Alert from 'react-bootstrap/Alert'; import { Link } from 'react-router-dom'; @@ -100,7 +102,8 @@ export default class LoopUI extends React.Component { state = { userName: null, loopName: LoopUI.defaultLoopName, - loopCache: new LoopCache({}) + loopCache: new LoopCache({}), + showAlert: false }; constructor() { @@ -110,6 +113,8 @@ export default class LoopUI extends React.Component { this.updateLoopCache = this.updateLoopCache.bind(this); this.loadLoop = this.loadLoop.bind(this); this.closeLoop = this.closeLoop.bind(this); + this.showAlert = this.showAlert.bind(this); + this.disableAlert = this.disableAlert.bind(this); } componentWillMount() { @@ -155,6 +160,14 @@ export default class LoopUI extends React.Component { ); } + renderAlertBar() { + return ( + <Alert variant="danger" show={this.state.showAlert} onClose={this.disableAlert} dismissible> + {this.state.showMessage} + </Alert> + ); + } + renderNavBar() { return ( <Navbar > @@ -199,14 +212,30 @@ export default class LoopUI extends React.Component { } updateLoopCache(loopJson) { - this.setState({ loopCache: new LoopCache(loopJson), loopName: this.state.loopCache.getLoopName() }); + this.setState({ loopCache: new LoopCache(loopJson) }); + this.setState({ loopName: this.state.loopCache.getLoopName() }); console.info(this.state.loopName+" loop loaded successfully"); } + showAlert(message) { + this.setState ({ showAlert: true, showMessage:message }); + } + + disableAlert() { + this.setState ({ showAlert: false }); + } + loadLoop(loopName) { LoopService.getLoop(loopName).then(loop => { console.debug("Updating loopCache"); - this.updateLoopCache(loop); + LoopActionService.refreshStatus(loopName).then(data => { + this.updateLoopCache(data); + this.props.history.push('/'); + }) + .catch(error => { + this.updateLoopCache(loop); + this.props.history.push('/'); + }); }); } @@ -219,21 +248,22 @@ export default class LoopUI extends React.Component { return ( <StyledMainDiv id="main_div"> <Route path="/operationalPolicyModal" - render={(routeProps) => (<OperationalPolicyModal {...routeProps} loopCache={this.getLoopCache()} loadLoopFunction={this.loadLoop}/>)} /> + render={(routeProps) => (<OperationalPolicyModal {...routeProps} loopCache={this.getLoopCache()} loadLoopFunction={this.loadLoop} showAlert={this.showAlert}/>)} /> <Route path="/configurationPolicyModal/:componentName" render={(routeProps) => (<ConfigurationPolicyModal {...routeProps} loopCache={this.getLoopCache()} loadLoopFunction={this.loadLoop}/>)} /> <Route path="/openLoop" render={(routeProps) => (<OpenLoopModal {...routeProps} loadLoopFunction={this.loadLoop} />)} /> <Route path="/loopProperties" render={(routeProps) => (<LoopProperties {...routeProps} loopCache={this.getLoopCache()} loadLoopFunction={this.loadLoop}/>)} /> <Route path="/userInfo" render={(routeProps) => (<UserInfo {...routeProps} />)} /> <Route path="/closeLoop" render={this.closeLoop} /> - <Route path="/submit" render={(routeProps) => (<PerformAction {...routeProps} loopAction="submit" loopCache={this.getLoopCache()} updateLoopFunction={this.updateLoopCache}/>)} /> - <Route path="/stop" render={(routeProps) => (<PerformAction {...routeProps} loopAction="stop" loopCache={this.getLoopCache()} updateLoopFunction={this.updateLoopCache}/>)} /> - <Route path="/restart" render={(routeProps) => (<PerformAction {...routeProps} loopAction="restart" loopCache={this.getLoopCache()} updateLoopFunction={this.updateLoopCache}/>)} /> - <Route path="/delete" render={(routeProps) => (<PerformAction {...routeProps} loopAction="delete" loopCache={this.getLoopCache()} updateLoopFunction={this.updateLoopCache}/>)} /> - <Route path="/undeploy" render={(routeProps) => (<PerformAction {...routeProps} loopAction="undeploy" loopCache={this.getLoopCache()} updateLoopFunction={this.updateLoopCache}/>)} /> - <Route path="/deploy" render={(routeProps) => (<DeployLoop {...routeProps} loopCache={this.getLoopCache()} updateLoopFunction={this.updateLoopCache}/>)} /> - <Route path="/refreshStatus" render={(routeProps) => (<RefreshStatus {...routeProps} loopCache={this.getLoopCache()} updateLoopFunction={this.updateLoopCache}/>)} /> + <Route path="/submit" render={(routeProps) => (<PerformAction {...routeProps} loopAction="submit" loopCache={this.getLoopCache()} updateLoopFunction={this.updateLoopCache} showAlert={this.showAlert}/>)} /> + <Route path="/stop" render={(routeProps) => (<PerformAction {...routeProps} loopAction="stop" loopCache={this.getLoopCache()} updateLoopFunction={this.updateLoopCache} showAlert={this.showAlert}/>)} /> + <Route path="/restart" render={(routeProps) => (<PerformAction {...routeProps} loopAction="restart" loopCache={this.getLoopCache()} updateLoopFunction={this.updateLoopCache} showAlert={this.showAlert}/>)} /> + <Route path="/delete" render={(routeProps) => (<PerformAction {...routeProps} loopAction="delete" loopCache={this.getLoopCache()} updateLoopFunction={this.updateLoopCache} showAlert={this.showAlert}/>)} /> + <Route path="/undeploy" render={(routeProps) => (<PerformAction {...routeProps} loopAction="undeploy" loopCache={this.getLoopCache()} updateLoopFunction={this.updateLoopCache} showAlert={this.showAlert}/>)} /> + <Route path="/deploy" render={(routeProps) => (<DeployLoop {...routeProps} loopCache={this.getLoopCache()} updateLoopFunction={this.updateLoopCache} showAlert={this.showAlert}/>)} /> + <Route path="/refreshStatus" render={(routeProps) => (<RefreshStatus {...routeProps} loopCache={this.getLoopCache()} updateLoopFunction={this.updateLoopCache} showAlert={this.showAlert}/>)} /> <Route path="/logout" render={this.logout} /> <GlobalClampStyle /> + {this.renderAlertBar()} {this.renderNavBar()} {this.renderLoopViewer()} </StyledMainDiv> diff --git a/ui-react/src/LoopUI.test.js b/ui-react/src/LoopUI.test.js new file mode 100644 index 000000000..e28096bd4 --- /dev/null +++ b/ui-react/src/LoopUI.test.js @@ -0,0 +1,171 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP CLAMP + * ================================================================================ + * Copyright (C) 2019 AT&T Intellectual Property. All rights + * reserved. + * ================================================================================ + * 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. + * ============LICENSE_END============================================ + * =================================================================== + * + */ +import React from 'react'; +import { shallow } from 'enzyme'; +import LoopUI from './LoopUI'; + +import LoopCache from './api/LoopCache'; +import LoopActionService from './api/LoopActionService'; +import LoopService from './api/LoopService'; + +describe('Verify LoopUI', () => { + beforeEach(() => { + fetch.resetMocks(); + fetch.mockImplementation(() => { + return Promise.resolve({ + ok: true, + status: 200, + text: () => "testUser" + + }); + }); + }) + + const loopCache = new LoopCache({ + "name": "LOOP_Jbv1z_v1_0_ResourceInstanceName1_tca", + "components": { + "POLICY": { + "componentState": { + "stateName": "UNKNOWN", + "description": "The policies defined have NOT yet been created on the policy engine" + } + }, + "DCAE": { + "componentState": { + "stateName": "BLUEPRINT_DEPLOYED", + "description": "The DCAE blueprint has been found in the DCAE inventory but not yet instancianted for this loop" + } + } + } + }); + + it('Test the render method', async () => { + const flushPromises = () => new Promise(setImmediate); + + const component = shallow(<LoopUI />) + component.setState({ + loopName: "testLoopName", + showAlert: false + }); + await flushPromises(); + expect(component).toMatchSnapshot(); + }); + + test('Test closeLoop method', () => { + const historyMock = { push: jest.fn() }; + const component = shallow(<LoopUI history={historyMock}/>) + const instance = component.instance(); + instance.closeLoop(); + + expect(component.state('loopName')).toEqual("Empty (NO loop loaded yet)"); + expect(historyMock.push.mock.calls[0]).toEqual([ '/']); + }) + + test('Test logout method', async () => { + const flushPromises = () => new Promise(setImmediate); + const component = shallow(<LoopUI />) + const instance = component.instance(); + instance.logout(); + await flushPromises(); + expect(component.state('userName')).toEqual("testUser"); + }) + + test('Test loadLoop method refresh suc', async () => { + const historyMock = { push: jest.fn() }; + LoopService.getLoop = jest.fn().mockImplementation(() => { + return Promise.resolve({ + ok: true, + status: 200, + text: () => {} + }); + }); + + LoopActionService.refreshStatus = jest.fn().mockImplementation(() => { + return Promise.resolve({name: "LOOP_Jbv1z_v1_0_ResourceInstanceName1_tca"}); + }); + + const flushPromises = () => new Promise(setImmediate); + const component = shallow(<LoopUI history={historyMock}/>) + const instance = component.instance(); + instance.loadLoop("LOOP_Jbv1z_v1_0_ResourceInstanceName1_tca"); + + await flushPromises(); + + const resLoopCache = instance.getLoopCache(); + + expect(resLoopCache.getComponentStates()).toBeUndefined(); + expect(component.state('loopName')).toEqual("LOOP_Jbv1z_v1_0_ResourceInstanceName1_tca"); + }) + + test('Test loadLoop method refresh fail', async () => { + const historyMock = { push: jest.fn() }; + LoopService.getLoop = jest.fn().mockImplementation(() => { + return Promise.resolve({ + name: "LOOP_Jbv1z_v1_0_ResourceInstanceName1_tca", + "components": { + "POLICY": { + "componentState": { + "stateName": "UNKNOWN", + "description": "The policies defined have NOT yet been created on the policy engine" + } + }, + "DCAE": { + "componentState": { + "stateName": "BLUEPRINT_DEPLOYED", + "description": "The DCAE blueprint has been found in the DCAE inventory but not yet instancianted for this loop" + } + } + }}); + }); + + LoopActionService.refreshStatus = jest.fn().mockImplementation(() => { + return Promise.reject({error: "whatever"}); + }); + + const flushPromises = () => new Promise(setImmediate); + const component = shallow(<LoopUI history={historyMock}/>) + const instance = component.instance(); + instance.loadLoop("LOOP_Jbv1z_v1_0_ResourceInstanceName1_tca"); + + await flushPromises(); + + const resLoopCache = instance.getLoopCache(); + + expect(resLoopCache).toEqual(loopCache); + expect(component.state('loopName')).toEqual("LOOP_Jbv1z_v1_0_ResourceInstanceName1_tca"); + }) + + test('Test alert methods', () => { + const component = shallow(<LoopUI />) + expect(component.state('showAlert')).toEqual(false); + + const instance = component.instance(); + instance.showAlert("testAlert"); + expect(component.state('showAlert')).toEqual(true); + expect(component.state('showMessage')).toEqual("testAlert"); + + instance.disableAlert(); + + expect(component.state('showAlert')).toEqual(false); + }) +}); diff --git a/ui-react/src/NotFound.test.js b/ui-react/src/NotFound.test.js new file mode 100644 index 000000000..3a5fc107d --- /dev/null +++ b/ui-react/src/NotFound.test.js @@ -0,0 +1,36 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP CLAMP + * ================================================================================ + * Copyright (C) 2019 AT&T Intellectual Property. All rights + * reserved. + * ================================================================================ + * 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. + * ============LICENSE_END============================================ + * =================================================================== + * + */ +import React from 'react'; +import { shallow } from 'enzyme'; +import NotFound from './NotFound'; + +describe('Verify OnapClamp', () => { + + it('Test the render method', () => { + + const component = shallow(<NotFound />) + + expect(component).toMatchSnapshot(); + }); + +}); diff --git a/ui-react/src/OnapClamp.test.js b/ui-react/src/OnapClamp.test.js new file mode 100644 index 000000000..c3336a9ab --- /dev/null +++ b/ui-react/src/OnapClamp.test.js @@ -0,0 +1,36 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP CLAMP + * ================================================================================ + * Copyright (C) 2019 AT&T Intellectual Property. All rights + * reserved. + * ================================================================================ + * 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. + * ============LICENSE_END============================================ + * =================================================================== + * + */ +import React from 'react'; +import { shallow } from 'enzyme'; +import OnapClamp from './OnapClamp'; + +describe('Verify OnapClamp', () => { + + it('Test the render method', () => { + + const component = shallow(<OnapClamp />) + + expect(component).toMatchSnapshot(); + }); + +}); diff --git a/ui-react/src/__snapshots__/LoopUI.test.js.snap b/ui-react/src/__snapshots__/LoopUI.test.js.snap new file mode 100644 index 000000000..ecf439e4e --- /dev/null +++ b/ui-react/src/__snapshots__/LoopUI.test.js.snap @@ -0,0 +1,154 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Verify LoopUI Test the render method 1`] = ` +<styled.div + id="main_div" +> + <Route + path="/operationalPolicyModal" + render={[Function]} + /> + <Route + path="/configurationPolicyModal/:componentName" + render={[Function]} + /> + <Route + path="/openLoop" + render={[Function]} + /> + <Route + path="/loopProperties" + render={[Function]} + /> + <Route + path="/userInfo" + render={[Function]} + /> + <Route + path="/closeLoop" + render={[Function]} + /> + <Route + path="/submit" + render={[Function]} + /> + <Route + path="/stop" + render={[Function]} + /> + <Route + path="/restart" + render={[Function]} + /> + <Route + path="/delete" + render={[Function]} + /> + <Route + path="/undeploy" + render={[Function]} + /> + <Route + path="/deploy" + render={[Function]} + /> + <Route + path="/refreshStatus" + render={[Function]} + /> + <Route + path="/logout" + render={[Function]} + /> + <GlobalStyleComponent /> + <Alert + closeLabel="Close alert" + dismissible={true} + onClose={[Function]} + show={false} + transition={ + Object { + "$$typeof": Symbol(react.forward_ref), + "defaultProps": Object { + "appear": false, + "in": false, + "mountOnEnter": false, + "timeout": 300, + "unmountOnExit": false, + }, + "displayName": "Fade", + "render": [Function], + } + } + variant="danger" + /> + <Navbar + collapseOnSelect={false} + expand={true} + variant="light" + > + <NavbarBrand> + <img + alt="" + height="50px" + src={null} + width="234px" + /> + <styled.a> + CLAMP + </styled.a> + </NavbarBrand> + <NavbarToggle + aria-controls="responsive-navbar-nav" + label="Toggle navigation" + /> + <MenuBar + loopName="testLoopName" + /> + <NavbarText> + <styled.a> + Signed in as: + </styled.a> + <Styled(Link) + to="/userInfo" + > + testUser + </Styled(Link)> + <Styled(Link) + to="/logout/" + > + (logout) + </Styled(Link)> + </NavbarText> + </Navbar> + <styled.div> + <styled.div> + Loop Viewer - + testLoopName + </styled.div> + <styled.div> + <withRouter(LoopViewSvg) + loopCache={ + LoopCache { + "loopJsonCache": Object {}, + } + } + /> + <LoopStatus + loopCache={ + LoopCache { + "loopJsonCache": Object {}, + } + } + /> + <LoopLogs + loopCache={ + LoopCache { + "loopJsonCache": Object {}, + } + } + /> + </styled.div> + </styled.div> +</styled.div> +`; diff --git a/ui-react/src/__snapshots__/NotFound.test.js.snap b/ui-react/src/__snapshots__/NotFound.test.js.snap new file mode 100644 index 000000000..86bcfd1c4 --- /dev/null +++ b/ui-react/src/__snapshots__/NotFound.test.js.snap @@ -0,0 +1,26 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Verify OnapClamp Test the render method 1`] = ` +<div + id="main" +> + <div + class="divRow" + > + <b> + Page Not Found! + </b> + </div> + <div + class="divRow" + > + Please cick + <a + href="/" + > + here + </a> + to go back to the main page. + </div> +</div> +`; diff --git a/ui-react/src/__snapshots__/OnapClamp.test.js.snap b/ui-react/src/__snapshots__/OnapClamp.test.js.snap new file mode 100644 index 000000000..751c94b3b --- /dev/null +++ b/ui-react/src/__snapshots__/OnapClamp.test.js.snap @@ -0,0 +1,176 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Verify OnapClamp Test the render method 1`] = ` +<ThemeProvider + theme={ + Object { + "backgroundColor": "#eeeeee", + "fontDanger": "#eb238e", + "fontDark": "#888888", + "fontFamily": "Arial, Sans-serif", + "fontHighlight": "#ffff00", + "fontLight": "#ffffff", + "fontNormal": "black", + "fontSize": "16px", + "fontWarning": "#eb238e", + "loopViewerBackgroundColor": "white", + "loopViewerFontColor": "yellow", + "loopViewerHeaderBackgroundColor": "#337ab7", + "loopViewerHeaderFontColor": "white", + "menuBackgroundColor": "white", + "menuFontColor": "black", + "menuHighlightedBackgroundColor": "#337ab7", + "menuHighlightedFontColor": "white", + } + } +> + <styled.div + id="main_div" + > + <Route + path="/operationalPolicyModal" + render={[Function]} + /> + <Route + path="/configurationPolicyModal/:componentName" + render={[Function]} + /> + <Route + path="/openLoop" + render={[Function]} + /> + <Route + path="/loopProperties" + render={[Function]} + /> + <Route + path="/userInfo" + render={[Function]} + /> + <Route + path="/closeLoop" + render={[Function]} + /> + <Route + path="/submit" + render={[Function]} + /> + <Route + path="/stop" + render={[Function]} + /> + <Route + path="/restart" + render={[Function]} + /> + <Route + path="/delete" + render={[Function]} + /> + <Route + path="/undeploy" + render={[Function]} + /> + <Route + path="/deploy" + render={[Function]} + /> + <Route + path="/refreshStatus" + render={[Function]} + /> + <Route + path="/logout" + render={[Function]} + /> + <GlobalStyleComponent /> + <Alert + closeLabel="Close alert" + dismissible={true} + onClose={[Function]} + show={false} + transition={ + Object { + "$$typeof": Symbol(react.forward_ref), + "defaultProps": Object { + "appear": false, + "in": false, + "mountOnEnter": false, + "timeout": 300, + "unmountOnExit": false, + }, + "displayName": "Fade", + "render": [Function], + } + } + variant="danger" + /> + <Navbar + collapseOnSelect={false} + expand={true} + variant="light" + > + <NavbarBrand> + <img + alt="" + height="50px" + src={null} + width="234px" + /> + <styled.a> + CLAMP + </styled.a> + </NavbarBrand> + <NavbarToggle + aria-controls="responsive-navbar-nav" + label="Toggle navigation" + /> + <MenuBar + loopName="Empty (NO loop loaded yet)" + /> + <NavbarText> + <styled.a> + Signed in as: + </styled.a> + <Styled(Link) + to="/userInfo" + /> + <Styled(Link) + to="/logout/" + > + (logout) + </Styled(Link)> + </NavbarText> + </Navbar> + <styled.div> + <styled.div> + Loop Viewer - + Empty (NO loop loaded yet) + </styled.div> + <styled.div> + <withRouter(LoopViewSvg) + loopCache={ + LoopCache { + "loopJsonCache": Object {}, + } + } + /> + <LoopStatus + loopCache={ + LoopCache { + "loopJsonCache": Object {}, + } + } + /> + <LoopLogs + loopCache={ + LoopCache { + "loopJsonCache": Object {}, + } + } + /> + </styled.div> + </styled.div> + </styled.div> +</ThemeProvider> +`; diff --git a/ui-react/src/api/LoopActionService.js b/ui-react/src/api/LoopActionService.js index 7e20e2f6c..7cea3ff9f 100644 --- a/ui-react/src/api/LoopActionService.js +++ b/ui-react/src/api/LoopActionService.js @@ -24,7 +24,7 @@ export default class LoopActionService{ static performAction(cl_name, uiAction) { - console.log("LoopActionService perform action: " + uiAction + " closedloopName=" + cl_name); + console.info("LoopActionService perform action: " + uiAction + " closedloopName=" + cl_name); const svcAction = uiAction.toLowerCase(); return fetch("/restservices/clds/v2/loop/" + svcAction + "/" + cl_name, { method: 'PUT', @@ -38,18 +38,18 @@ export default class LoopActionService{ } }) .then(function (data) { - alert("Action Successful: " + uiAction); + console.info("Action Successful: " + uiAction); return data; }) .catch(function(error) { - console.log("Action Failure: " + uiAction); + console.info("Action Failure: " + uiAction); return Promise.reject(error); }); } static refreshStatus(cl_name) { - console.log("Refresh the status for closedloopName=" + cl_name); + console.info("Refresh the status for closedloopName=" + cl_name); return fetch("/restservices/clds/v2/loop/getstatus/" + cl_name, { method: 'GET', diff --git a/ui-react/src/components/dialogs/DeployLoop.js b/ui-react/src/components/dialogs/DeployLoop.js index 805f0f29b..d71af9240 100644 --- a/ui-react/src/components/dialogs/DeployLoop.js +++ b/ui-react/src/components/dialogs/DeployLoop.js @@ -64,14 +64,13 @@ export default class DeployLoop extends React.Component { LoopService.updateGlobalProperties(loopName, this.state.temporaryPropertiesJson).then(resp => { this.setState({ show: false }); - console.log("Perform action: deploy"); LoopActionService.performAction(loopName, "deploy").then(pars => { - alert("Action deploy successfully performed"); + this.props.showAlert("Action deploy successfully performed"); // refresh status and update loop logs this.refreshStatus(loopName); }) .catch(error => { - alert("Action deploy failed"); + this.props.showAlert("Action deploy failed"); // refresh status and update loop logs this.refreshStatus(loopName); }); @@ -84,7 +83,7 @@ export default class DeployLoop extends React.Component { this.props.history.push('/'); }) .catch(error => { - alert("Refresh status failed"); + this.props.showAlert("Refresh status failed"); this.props.history.push('/'); }); } diff --git a/ui-react/src/components/dialogs/DeployLoop.test.js b/ui-react/src/components/dialogs/DeployLoop.test.js index 2959ed652..44bc78379 100644 --- a/ui-react/src/components/dialogs/DeployLoop.test.js +++ b/ui-react/src/components/dialogs/DeployLoop.test.js @@ -61,6 +61,7 @@ describe('Verify DeployLoop', () => { const flushPromises = () => new Promise(setImmediate); const historyMock = { push: jest.fn() }; const updateLoopFunction = jest.fn(); + const showAlert = jest.fn(); const handleSave = jest.spyOn(DeployLoop.prototype,'handleSave'); LoopService.updateGlobalProperties = jest.fn().mockImplementation(() => { return Promise.resolve({ @@ -83,10 +84,9 @@ describe('Verify DeployLoop', () => { json: () => {} }); }); - const jsdomAlert = window.alert; - window.alert = () => {}; + const component = shallow(<DeployLoop history={historyMock} - loopCache={loopCache} updateLoopFunction={updateLoopFunction} />) + loopCache={loopCache} updateLoopFunction={updateLoopFunction} showAlert={showAlert} />) component.find('[variant="primary"]').prop('onClick')(); await flushPromises(); @@ -95,7 +95,6 @@ describe('Verify DeployLoop', () => { expect(handleSave).toHaveBeenCalledTimes(1); expect(component.state('show')).toEqual(false); expect(historyMock.push.mock.calls[0]).toEqual([ '/']); - window.alert = jsdomAlert; handleSave.mockClear(); }); diff --git a/ui-react/src/components/dialogs/OperationalPolicy/OperationalPolicyModal.js b/ui-react/src/components/dialogs/OperationalPolicy/OperationalPolicyModal.js index 4dc1f90a0..5c5f0241a 100644 --- a/ui-react/src/components/dialogs/OperationalPolicy/OperationalPolicyModal.js +++ b/ui-react/src/components/dialogs/OperationalPolicy/OperationalPolicyModal.js @@ -54,7 +54,7 @@ export default class OperationalPolicyModal extends React.Component { if (errors.length !== 0) { console.error("Errors detected during config policy data validation ", errors); - alert(errors); + this.props.showAlert(errors); } else { console.info("NO validation errors found in config policy data"); diff --git a/ui-react/src/components/dialogs/PerformActions.js b/ui-react/src/components/dialogs/PerformActions.js index 9c34e141b..66b192863 100644 --- a/ui-react/src/components/dialogs/PerformActions.js +++ b/ui-react/src/components/dialogs/PerformActions.js @@ -50,14 +50,14 @@ export default class PerformActions extends React.Component { componentDidMount() { const action = this.state.loopAction; const loopName = this.state.loopName; - console.log("Perform action:" + action); + LoopActionService.performAction(loopName, action).then(pars => { - alert("Action " + action + " successfully performed"); + this.props.showAlert("Action " + action + " successfully performed"); // refresh status and update loop logs this.refreshStatus(loopName); }) .catch(error => { - alert("Action " + action + " failed"); + this.props.showAlert("Action " + action + " failed"); // refresh status and update loop logs this.refreshStatus(loopName); }); diff --git a/ui-react/src/components/dialogs/PerformActions.test.js b/ui-react/src/components/dialogs/PerformActions.test.js index 56fdcf39b..0b0786290 100644 --- a/ui-react/src/components/dialogs/PerformActions.test.js +++ b/ui-react/src/components/dialogs/PerformActions.test.js @@ -36,6 +36,7 @@ describe('Verify PerformActions', () => { const flushPromises = () => new Promise(setImmediate); const historyMock = { push: jest.fn() }; const updateLoopFunction = jest.fn(); + const showAlert = jest.fn(); LoopActionService.refreshStatus = jest.fn().mockImplementation(() => { return Promise.resolve({ @@ -44,21 +45,19 @@ describe('Verify PerformActions', () => { json: () => {} }); }); - const jsdomAlert = window.alert; - window.alert = () => {}; const component = shallow(<PerformActions loopCache={loopCache} - loopAction="submit" history={historyMock} updateLoopFunction={updateLoopFunction} />) + loopAction="submit" history={historyMock} updateLoopFunction={updateLoopFunction} showAlert={showAlert} />) await flushPromises(); component.update(); expect(historyMock.push.mock.calls[0]).toEqual([ '/']); - window.alert = jsdomAlert; }); it('Test the render method action successful', async () => { const flushPromises = () => new Promise(setImmediate); const historyMock = { push: jest.fn() }; const updateLoopFunction = jest.fn(); + const showAlert = jest.fn(); LoopActionService.performAction = jest.fn().mockImplementation(() => { return Promise.resolve({ @@ -74,15 +73,12 @@ describe('Verify PerformActions', () => { json: () => {} }); }); - const jsdomAlert = window.alert; - window.alert = () => {}; const component = shallow(<PerformActions loopCache={loopCache} - loopAction="submit" history={historyMock} updateLoopFunction={updateLoopFunction} />) + loopAction="submit" history={historyMock} updateLoopFunction={updateLoopFunction} showAlert={showAlert} />) await flushPromises(); component.update(); expect(historyMock.push.mock.calls[0]).toEqual([ '/']); - window.alert = jsdomAlert; }); }); diff --git a/ui-react/src/components/dialogs/RefreshStatus.js b/ui-react/src/components/dialogs/RefreshStatus.js index cf08655ee..64b35d99b 100644 --- a/ui-react/src/components/dialogs/RefreshStatus.js +++ b/ui-react/src/components/dialogs/RefreshStatus.js @@ -22,7 +22,7 @@ */ import React from 'react'; import LoopActionService from '../../api/LoopActionService'; -import Spinner from 'react-bootstrap/Spinner' +import Spinner from 'react-bootstrap/Spinner'; import styled from 'styled-components'; const StyledSpinnerDiv = styled.div` @@ -42,15 +42,14 @@ export default class RefreshStatus extends React.Component { } componentDidMount() { - console.log("Refresh status for: " + this.state.loopName); // refresh status and update loop logs LoopActionService.refreshStatus(this.state.loopName).then(data => { - alert("Status successfully refreshed") + this.props.showAlert("Status successfully refreshed"); this.props.updateLoopFunction(data); this.props.history.push('/'); }) .catch(error => { - alert("Status refreshing failed"); + this.props.showAlert("Status refreshing failed"); this.props.history.push('/'); }); } diff --git a/ui-react/src/components/dialogs/RefreshStatus.test.js b/ui-react/src/components/dialogs/RefreshStatus.test.js index cb782ad23..3038eb321 100644 --- a/ui-react/src/components/dialogs/RefreshStatus.test.js +++ b/ui-react/src/components/dialogs/RefreshStatus.test.js @@ -35,21 +35,20 @@ describe('Verify RefreshStatus', () => { it('Test refresh status failed', async () => { const flushPromises = () => new Promise(setImmediate); const historyMock = { push: jest.fn() }; + const showAlert = jest.fn(); - const jsdomAlert = window.alert; - window.alert = () => {}; - const component = shallow(<RefreshStatus loopCache={loopCache} history={historyMock} />) + const component = shallow(<RefreshStatus loopCache={loopCache} history={historyMock} showAlert={showAlert} />) await flushPromises(); component.update(); expect(historyMock.push.mock.calls[0]).toEqual([ '/']); - window.alert = jsdomAlert; }); it('Test refresh status successful', async () => { const flushPromises = () => new Promise(setImmediate); const historyMock = { push: jest.fn() }; const updateLoopFunction = jest.fn(); + const showAlert = jest.fn(); LoopActionService.refreshStatus = jest.fn().mockImplementation(() => { return Promise.resolve({ @@ -58,15 +57,13 @@ describe('Verify RefreshStatus', () => { json: () => {} }); }); - const jsdomAlert = window.alert; - window.alert = () => {}; + const component = shallow(<RefreshStatus loopCache={loopCache} - loopAction="submit" history={historyMock} updateLoopFunction={updateLoopFunction} />) + loopAction="submit" history={historyMock} updateLoopFunction={updateLoopFunction} showAlert={showAlert} />) await flushPromises(); component.update(); expect(historyMock.push.mock.calls[0]).toEqual([ '/']); - window.alert = jsdomAlert; }); }); diff --git a/ui-react/src/components/loop_viewer/svg/LoopSvg.js b/ui-react/src/components/loop_viewer/svg/LoopSvg.js index 48f0335fc..06cfd238f 100644 --- a/ui-react/src/components/loop_viewer/svg/LoopSvg.js +++ b/ui-react/src/components/loop_viewer/svg/LoopSvg.js @@ -61,7 +61,7 @@ class LoopViewSvg extends React.Component { return this.state.svgContent !== nextState.svgContent; } - componentWillReceiveProps(newProps) { + componentWillReceiveProps(newProps) { if (this.state.loopCache !== newProps.loopCache) { this.setState({ loopCache: newProps.loopCache, diff --git a/ui-react/src/components/loop_viewer/svg/LoopSvg.test.js b/ui-react/src/components/loop_viewer/svg/LoopSvg.test.js index 5a28328c9..635185463 100644 --- a/ui-react/src/components/loop_viewer/svg/LoopSvg.test.js +++ b/ui-react/src/components/loop_viewer/svg/LoopSvg.test.js @@ -23,12 +23,111 @@ import React from 'react'; import { shallow } from 'enzyme'; import LoopSvg from './LoopSvg'; +import LoopCache from '../../../api/LoopCache'; +import LoopService from '../../../api/LoopService'; describe('Verify LoopSvg', () => { + const loopCache = new LoopCache({ + "name": "LOOP_Jbv1z_v1_0_ResourceInstanceName1_tca", + "microServicePolicies": [{ + "name": "TCA_h2NMX_v1_0_ResourceInstanceName1_tca", + "modelType": "onap.policies.monitoring.cdap.tca.hi.lo.app", + "properties": {"domain": "measurementsForVfScaling"}, + "shared": false, + "jsonRepresentation": {"schema": {}} + }], + "operationalPolicies": [{ + "name": "OPERATIONAL_h2NMX_v1_0_ResourceInstanceName1_tca", + "configurationsJson": { + "guard_policies": {}, + "operational_policy": { + "controlLoop": {}, + "policies": [] + } + } + }] + }); - it('Test the render method', () => { - const component = shallow(<LoopSvg />) + it('Test the render method no loopName', () => { + const localLoopCache = new LoopCache({ + "microServicePolicies": [{ + "name": "TCA_h2NMX_v1_0_ResourceInstanceName1_tca", + "modelType": "onap.policies.monitoring.cdap.tca.hi.lo.app", + "properties": {"domain": "measurementsForVfScaling"}, + "shared": false, + "jsonRepresentation": {"schema": {}} + }] + }); + const component = shallow( + <LoopSvg.WrappedComponent loopCache={localLoopCache}/> + ); - expect(component).toMatchSnapshot(); - }); + expect(component).toMatchSnapshot(); + }); + + it('Test the render method', () => { + const component = shallow( + <LoopSvg.WrappedComponent loopCache={loopCache}/> + ); + + expect(component).toMatchSnapshot(); + }); + + it('Test the render method svg not empty', async () => { + const flushPromises = () => new Promise(setImmediate); + LoopService.getSvg = jest.fn().mockImplementation(() => { + return Promise.resolve("<svg><text test</text></svg>"); + }); + const component = shallow( + <LoopSvg.WrappedComponent loopCache={loopCache}/> + ); + await flushPromises(); + expect(component).toMatchSnapshot(); + }); + + it('Test handleSvgClick', () => { + const historyMock = { push: jest.fn() }; + + const component = shallow( + <LoopSvg.WrappedComponent loopCache={loopCache} history={historyMock}/> + ); + let dummyElement = document.createElement('div'); + dummyElement.setAttribute("data-element-id","TCA_h2NMX_v1_0_ResourceInstanceName1_tca"); + + const event = { target: { parentNode: { parentNode:{ parentNode: dummyElement }}}}; + + component.simulate('click', event); + component.update(); + + expect(historyMock.push.mock.calls[0]).toEqual([ '/configurationPolicyModal/TCA_h2NMX_v1_0_ResourceInstanceName1_tca']); + + //click operational policy + dummyElement.setAttribute("data-element-id","OPERATIONAL_h2NMX_v1_0_ResourceInstanceName1_tca"); + const event2 = { target: { parentNode: { parentNode:{ parentNode: dummyElement }}}}; + + component.simulate('click', event2); + component.update(); + + expect(historyMock.push.mock.calls[1]).toEqual([ '/operationalPolicyModal']); + }); + + it('Test componentWillReceiveProps method', () => { + const localLoopCache = new LoopCache({ + "microServicePolicies": [{ + "name": "TCA_h2NMX_v1_0_ResourceInstanceName1_tca", + "modelType": "onap.policies.monitoring.cdap.tca.hi.lo.app", + "properties": {"domain": "measurementsForVfScaling"}, + "shared": false, + "jsonRepresentation": {"schema": {}} + }] + }); + const component = shallow( + <LoopSvg.WrappedComponent loopCache={localLoopCache}/> + ); + + expect(component.state('componentModalMapping').size).toEqual(2); + + component.setProps({loopCache: loopCache}); + expect(component.state('componentModalMapping').size).toEqual(3); + }); }); diff --git a/ui-react/src/components/loop_viewer/svg/__snapshots__/LoopSvg.test.js.snap b/ui-react/src/components/loop_viewer/svg/__snapshots__/LoopSvg.test.js.snap index 23d22256f..cecfb425a 100644 --- a/ui-react/src/components/loop_viewer/svg/__snapshots__/LoopSvg.test.js.snap +++ b/ui-react/src/components/loop_viewer/svg/__snapshots__/LoopSvg.test.js.snap @@ -1,7 +1,34 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`Verify LoopSvg Test the render method 1`] = ` -<ContextConsumer> - <Component /> -</ContextConsumer> +<styled.div + dangerouslySetInnerHTML={ + Object { + "__html": "<svg><text x=\\"20\\" y=\\"40\\">No LOOP (SVG)</text></svg>", + } + } + onClick={[Function]} +/> +`; + +exports[`Verify LoopSvg Test the render method no loopName 1`] = ` +<styled.div + dangerouslySetInnerHTML={ + Object { + "__html": "<svg><text x=\\"20\\" y=\\"40\\">No LOOP (SVG)</text></svg>", + } + } + onClick={[Function]} +/> +`; + +exports[`Verify LoopSvg Test the render method svg not empty 1`] = ` +<styled.div + dangerouslySetInnerHTML={ + Object { + "__html": "<svg><text test</text></svg>", + } + } + onClick={[Function]} +/> `; |