diff options
Diffstat (limited to 'src')
21 files changed, 1972 insertions, 11 deletions
diff --git a/src/app/tierSupport/selectedNodeDetails/SelectedNodeDetails.jsx b/src/app/tierSupport/selectedNodeDetails/SelectedNodeDetails.jsx index 88536e6..5750fd9 100644 --- a/src/app/tierSupport/selectedNodeDetails/SelectedNodeDetails.jsx +++ b/src/app/tierSupport/selectedNodeDetails/SelectedNodeDetails.jsx @@ -39,7 +39,7 @@ let mapStateToProps = ({tierSupport: {selectedNodeDetails}}) => { }; }; -class SelectedNodeDetails extends Component { +export class SelectedNodeDetails extends Component { static propTypes = { nodeData: React.PropTypes.object, nodeType: React.PropTypes.string, diff --git a/src/app/tierSupport/selectedNodeDetails/SelectedNodeDetails.test.js b/src/app/tierSupport/selectedNodeDetails/SelectedNodeDetails.test.js new file mode 100644 index 0000000..60f5530 --- /dev/null +++ b/src/app/tierSupport/selectedNodeDetails/SelectedNodeDetails.test.js @@ -0,0 +1,141 @@ +import React from 'react'; +import { shallow, mount } from 'enzyme'; +import {Provider} from 'react-redux' +import configureStore from 'redux-mock-store'; +import Table from 'react-bootstrap/lib/Table'; + +import ConnectedSelectedNodeDetails, { SelectedNodeDetails } from './SelectedNodeDetails.jsx'; +import { SELECTED_NODE_TABLE_COLUMN_NAMES } from './SelectedNodeDetailsConstants.js'; +import LaunchInContext from '../launchExternalResource/LaunchExternalResource.jsx'; + +describe('SelectedNodeDetails - Shallow render of component', () => { + let wrapper; + const nodeTypeProp = 'VNF'; + const uidProp = 'SomeValidUIDName'; + const nodeDataProp = { + 'interface-role': 'MPLS', + 'in-maint': 'false', + 'interface-type': 'WAN', + 'port-description': 'MPLS port on 10_NSG16_location4', + 'resource-version': '123456789', + 'interface-name': '10_port1_location4', + 'uri': 'network/pnfs/pnf/10_NSG14_location4/p-interfaces/p-interface/10_port1_location4' + }; + + beforeEach( () => { + wrapper = shallow( + <SelectedNodeDetails + nodeType={nodeTypeProp} + nodeData={nodeDataProp} + uid={uidProp} + />); + }) + + it('Render basic component', () => { + expect(wrapper.length).toEqual(1); + }); + + it('Verify node type is displayed as a header', () => { + expect(wrapper.contains(<h2>{nodeTypeProp}</h2>)).toBe(true); + expect(wrapper.find('h2')).toHaveLength(1); + }); + + it('Verify uid is displayed', () => { + expect(wrapper.contains(<span>{uidProp} <LaunchInContext/></span>)).toBe(true); + }); + + it('Verify node data table is displayed', () => { + // verify table has a row for each node data prop plus one row for the column headers + expect(wrapper.find(Table)).toHaveLength(1); + expect(wrapper.find(Table).props().bsClass).toEqual('ts-selected-node-table'); + expect(wrapper.find(Table).children()).toHaveLength(2); // thead and tbody + + // validate the table header content + expect(wrapper.find('thead')).toHaveLength(1); + let cellClassName; + for (let index = 1; index <= SELECTED_NODE_TABLE_COLUMN_NAMES.length; index++) { + cellClassName = (index % 2 ? 'left-column-cell' : 'right-column-cell'); + expect(wrapper.contains( + <th className={cellClassName} key={index}>{SELECTED_NODE_TABLE_COLUMN_NAMES[index-1]}</th> + )).toBe(true); + } + + // validate the table body content + expect(wrapper.find('tbody')).toHaveLength(1); + expect(wrapper.find('tbody').children()).toHaveLength(7); // 1 row for each of the 7 properties + for (let prop in nodeDataProp) { + expect(wrapper.contains( + <td className='left-column-cell'>{prop}</td> + )).toBe(true); + expect(wrapper.contains( + <td className='right-column-cell'>{nodeDataProp[prop]}</td> + )).toBe(true); + } + }); +}) + +describe('SelectedNodeDetails - Shallow render of component with no node data', () => { + let wrapper; + const nodeTypeProp = 'VNF'; + const uidProp = 'SomeValidUIDName'; + const nodeDataProp = {}; + + beforeEach( () => { + wrapper = shallow( + <SelectedNodeDetails + nodeType={nodeTypeProp} + nodeData={nodeDataProp} + uid={uidProp} + />); + }) + + it('Render basic component', () => { + expect(wrapper.length).toEqual(1); + }); + + it('Verify node data table is hidden', () => { + // verify table is hidden + expect(wrapper.find(Table)).toHaveLength(1); + expect(wrapper.find(Table).props().bsClass).toEqual('hidden'); + }); +}) + +describe('SelectedNodeDetails - Render React Component (wrapped in <Provider>)', () => { + const initialState = { + tierSupport: { + launchExternalResourceReducer: { + externalResourcePayload: {} + }, + selectedNodeDetails: { + nodeType: 'VNF', + uid: 'AAI/CLYMR/000509/SD_WAN', + nodeData: { + 'interface-role': 'MPLS', + 'in-maint': 'false', + 'interface-type': 'WAN', + 'port-description': 'MPLS port on 10_NSG16_location4', + 'resource-version': '123456789', + 'interface-name': '10_port1_location4', + 'uri': 'network/pnfs/pnf/10_NSG14_location4/p-interfaces/p-interface/10_port1_location4' + } + } + } + }; + const mockStore = configureStore(); + let store, wrapper; + + beforeEach( () => { + store = mockStore(initialState); + wrapper = mount(<Provider store={store}><ConnectedSelectedNodeDetails /></Provider>); + }) + + it('Render the connected component', () => { + expect(wrapper.find(ConnectedSelectedNodeDetails).length).toEqual(1); + }); + + it('Validate props from store', () => { + expect(wrapper.find(SelectedNodeDetails).props().uid).toEqual(initialState.tierSupport.selectedNodeDetails.uid); + expect(wrapper.find(SelectedNodeDetails).props().nodeType).toEqual(initialState.tierSupport.selectedNodeDetails.nodeType); + expect(wrapper.find(SelectedNodeDetails).props().nodeData).toEqual(initialState.tierSupport.selectedNodeDetails.nodeData); + }); +}) diff --git a/src/app/tierSupport/selectedNodeDetails/SelectedNodeDetailsReducer.test.js b/src/app/tierSupport/selectedNodeDetails/SelectedNodeDetailsReducer.test.js new file mode 100644 index 0000000..2544a80 --- /dev/null +++ b/src/app/tierSupport/selectedNodeDetails/SelectedNodeDetailsReducer.test.js @@ -0,0 +1,248 @@ +import SelectedNodeDetailsReducer from './SelectedNodeDetailsReducer.js'; +import {tierSupportActionTypes} from 'app/tierSupport/TierSupportConstants.js'; +import { + globalAutoCompleteSearchBarActionTypes +} from 'app/globalAutoCompleteSearchBar/GlobalAutoCompleteSearchBarConstants.js'; + +describe('SelectedNodeDetails - Reducer Tests', () => { + it('Action Type: TS_NODE_SEARCH_RESULTS', () => { + const action = { + type: tierSupportActionTypes.TS_NODE_SEARCH_RESULTS, + data: { + nodes: [ + { + 'id': 'AAI/CLYMR/000509/SD_WAN', + 'itemType': 'service-instance', + 'itemNameKey': 'service-instance.AAI/SPRKY/000509/SD_WAN', + 'itemNameValue': 'AAI/SPRKY/000509/SD_WAN', + 'itemProperties': { + 'service-instance-id': 'AAI/SPRKY/000509/SD_WAN', + 'resource-version':'1508078039815' + }, + 'itemIntegrity' : { + 'entityId' : 'AEEhny_vnf1_under_fw-si1', + 'entityType' : 'vnf', + 'entityLink' : 'cloud-infrastr084-1377-4f49-9c72-f0_location2', + 'initialTimestamp' :'2017-11-13T16:58:01Z', + 'latestValidationTimestamp':'2017-11-13T16:58:01Z', + 'resourceVersion':'1510592264096', + 'violations': [] + }, + 'nodeMeta': { + 'className': 'selectedSearchedNodeClass', + 'nodeDebug': null, + 'selfLinkResponseTimeInMs': 628, + 'relationshipNode': false, + 'searchTarget': true, + 'enrichableNode': false, + 'nodeValidated': true, + 'nodeIssue': false, + 'maxAltitude': 4, + 'nodeType': 'serviceInstance', + 'nodeLabel1':'service-instance', + 'nodeLabel2':'AAI/SPRKY/000509/SD_WAN' + }, + 'rootNode' : false + } + ] + } + }; + let state = { + nodeType: '', + uid: '', + nodeData: {} + }; + state = SelectedNodeDetailsReducer(state, action); + expect(state).toEqual({ + nodeType: action['data']['nodes'][0]['itemType'], + uid: action['data']['nodes'][0]['itemNameValue'], + nodeData: action['data']['nodes'][0]['itemProperties'] + }); + }); + + it('Action Type: TS_NODE_SEARCH_RESULTS - searchTarget === false', () => { + const action = { + type: tierSupportActionTypes.TS_NODE_SEARCH_RESULTS, + data: { + nodes: [ + { + 'id': 'AAI/CLYMR/000509/SD_WAN', + 'itemType': 'service-instance', + 'itemNameKey': 'service-instance.AAI/SPRKY/000509/SD_WAN', + 'itemNameValue': 'AAI/SPRKY/000509/SD_WAN', + 'itemProperties': { + 'service-instance-id': 'AAI/SPRKY/000509/SD_WAN', + 'resource-version':'1508078039815' + }, + 'itemIntegrity' : { + 'entityId' : 'AEEhny_vnf1_under_fw-si1', + 'entityType' : 'vnf', + 'entityLink' : 'cloud-infrastr084-1377-4f49-9c72-f0_location2', + 'initialTimestamp' :'2017-11-13T16:58:01Z', + 'latestValidationTimestamp':'2017-11-13T16:58:01Z', + 'resourceVersion':'1510592264096', + 'violations': [] + }, + 'nodeMeta': { + 'className': 'selectedSearchedNodeClass', + 'nodeDebug': null, + 'selfLinkResponseTimeInMs': 628, + 'relationshipNode': false, + 'searchTarget': false, + 'enrichableNode': false, + 'nodeValidated': true, + 'nodeIssue': false, + 'maxAltitude': 4, + 'nodeType': 'serviceInstance', + 'nodeLabel1':'service-instance', + 'nodeLabel2':'AAI/SPRKY/000509/SD_WAN' + }, + 'rootNode' : false + } + ] + } + }; + let state = { + nodeType: 'Complex', + uid: 'ABC', + nodeData: { + 'service-instance-id': 'blah/blah/blah', + 'resource-version':'123456' + } + }; + state = SelectedNodeDetailsReducer(state, action); + expect(state).toEqual({ + nodeType: '', + uid: '', + nodeData: {} + }); + }); + + it('Action Type: TS_GRAPH_NODE_SELECTED', () => { + const action = { + type: tierSupportActionTypes.TS_GRAPH_NODE_SELECTED, + data: { + itemProperties: { + 'service-instance-id': 'AAI/SPRKY/000509/SD_WAN', + 'resource-version':'1508078039815' + }, + itemType: 'Complex', + itemNameValue: '123456' + } + }; + let state = { + nodeType: '', + uid: '', + nodeData: {} + }; + state = SelectedNodeDetailsReducer(state, action); + expect(state).toEqual({ + nodeType: action['data']['itemType'], + uid: action['data']['itemNameValue'], + nodeData: action['data']['itemProperties'] + }); + }); + + it('Action Type: TIER_SUPPORT_NETWORK_ERROR', () => { + const action = { + type: tierSupportActionTypes.TIER_SUPPORT_NETWORK_ERROR, + }; + let state = { + nodeType: 'Complex', + uid: '12345', + nodeData: { + 'service-instance-id': 'AAI/SPRKY/000509/SD_WAN', + 'resource-version':'1508078039815' + } + }; + state = SelectedNodeDetailsReducer(state, action); + expect(state).toEqual({ + nodeType: '', + uid: '', + nodeData: {} + }); + }); + + it('Action Type: TIER_SUPPORT_CLEAR_DATA', () => { + const action = { + type: tierSupportActionTypes.TIER_SUPPORT_CLEAR_DATA, + }; + let state = { + nodeType: 'Complex', + uid: '12345', + nodeData: { + 'service-instance-id': 'AAI/SPRKY/000509/SD_WAN', + 'resource-version':'1508078039815' + } + }; + state = SelectedNodeDetailsReducer(state, action); + expect(state).toEqual({ + nodeType: '', + uid: '', + nodeData: {} + }); + }); + + it('Action Type: TS_NODE_SEARCH_NO_RESULTS', () => { + const action = { + type: tierSupportActionTypes.TS_NODE_SEARCH_NO_RESULTS, + }; + let state = { + nodeType: 'Complex', + uid: '12345', + nodeData: { + 'service-instance-id': 'AAI/SPRKY/000509/SD_WAN', + 'resource-version':'1508078039815' + } + }; + state = SelectedNodeDetailsReducer(state, action); + expect(state).toEqual({ + nodeType: '', + uid: '', + nodeData: {} + }); + }); + + it('Action Type: SEARCH_WARNING_EVENT', () => { + const action = { + type: globalAutoCompleteSearchBarActionTypes.SEARCH_WARNING_EVENT, + }; + let state = { + nodeType: 'Complex', + uid: '12345', + nodeData: { + 'service-instance-id': 'AAI/SPRKY/000509/SD_WAN', + 'resource-version':'1508078039815' + } + }; + state = SelectedNodeDetailsReducer(state, action); + expect(state).toEqual({ + nodeType: '', + uid: '', + nodeData: {} + }); + }); + + it('Invalid Action Type', () => { + const action = { + type: 'Nonexistent Action Type', + }; + let state = { + nodeType: 'Complex', + uid: '12345', + nodeData: { + 'service-instance-id': 'AAI/SPRKY/000509/SD_WAN', + 'resource-version':'1508078039815' + } + }; + state = SelectedNodeDetailsReducer(state, action); + expect(state).toEqual({ + nodeType: 'Complex', + uid: '12345', + nodeData: { + 'service-instance-id': 'AAI/SPRKY/000509/SD_WAN', + 'resource-version':'1508078039815' + } + }); + }); +}) diff --git a/src/app/vnfSearch/VnfSearch.jsx b/src/app/vnfSearch/VnfSearch.jsx index dbcc73d..a409ce2 100644 --- a/src/app/vnfSearch/VnfSearch.jsx +++ b/src/app/vnfSearch/VnfSearch.jsx @@ -157,7 +157,7 @@ let mapActionToProps = (dispatch) => { }; }; -class vnfSearch extends Component { +export class vnfSearch extends Component { static propTypes = { feedbackMsgText: React.PropTypes.string, feedbackSeverity: React.PropTypes.string, diff --git a/src/app/vnfSearch/VnfSearch.test.js b/src/app/vnfSearch/VnfSearch.test.js new file mode 100644 index 0000000..c6c63fc --- /dev/null +++ b/src/app/vnfSearch/VnfSearch.test.js @@ -0,0 +1,49 @@ +import React from 'react'; +import { shallow, mount } from 'enzyme'; +import {Provider} from 'react-redux' +import configureStore from 'redux-mock-store'; + +import ConnectedVnfSearch, { vnfSearch } from './VnfSearch.jsx'; + +describe('VnfSearch - Shallow render of component', () => { + let wrapper; + const vnfFilters = {}; + const vnfVisualizationPanelClass = 'collapsible-panel-main-panel'; + const unifiedFilterValues = {}; + + beforeEach( () => { + wrapper = shallow( + <vnfSearch + vnfFilters={vnfFilters} + unifiedFilterValues={unifiedFilterValues} + vnfVisualizationPanelClass={vnfVisualizationPanelClass} + /> + ); + }) + + it('Render basic component', () => { + expect(wrapper.length).toEqual(1); + }); +}) +// +// describe('VnfSearch - Render React Component (wrapped in <Provider>)', () => { +// const initialState = { +// vnfSearch: {} +// }; +// const mockStore = configureStore(); +// let store, wrapper; +// +// beforeEach( () => { +// store = mockStore(initialState); +// wrapper = mount(<Provider store={store}><ConnectedVnfSearch /></Provider>); +// }) +// +// it('Render the connected component', () => { +// expect(wrapper.find(ConnectedVnfSearch).length).toEqual(1); +// }); +// +// it('Validate props from store', () => { +// expect(wrapper.find(VnfSearchNfRoleVisualization).props().enableBusyFeedback).toEqual(initialState.vnfSearch.enableBusyFeedback); +// expect(wrapper.find(VnfSearchNfRoleVisualization).props().processedNfRoleCountChartData).toEqual(initialState.vnfSearch.processedNfRoleCountChartData); +// }); +// }) diff --git a/src/app/vnfSearch/VnfSearchActions.js b/src/app/vnfSearch/VnfSearchActions.js index 4ca149d..20290d6 100644 --- a/src/app/vnfSearch/VnfSearchActions.js +++ b/src/app/vnfSearch/VnfSearchActions.js @@ -39,9 +39,6 @@ import { } from 'app/globalInlineMessageBar/GlobalInlineMessageBarActions.js'; import {MESSAGE_LEVEL_WARNING} from 'utils/GlobalConstants.js'; -let fetch = require('node-fetch'); -fetch.Promise = require('es6-promise').Promise; - const itemKeyWord = 'key'; const countKeyWord = 'doc_count'; diff --git a/src/app/vnfSearch/VnfSearchActions.test.js b/src/app/vnfSearch/VnfSearchActions.test.js new file mode 100644 index 0000000..927e6ab --- /dev/null +++ b/src/app/vnfSearch/VnfSearchActions.test.js @@ -0,0 +1,215 @@ +import configureStore from 'redux-mock-store'; +import thunk from 'redux-thunk' +import fetchMock from 'fetch-mock'; + +import { + processVnfFilterPanelCollapse, + clearVnfSearchData, + setNotificationText, + processVnfVisualizationsOnFilterChange +} from './VnfSearchActions.js'; +import { + vnfActionTypes, + CHART_PROV_STATUS, + CHART_ORCH_STATUS, + CHART_NF_TYPE, + CHART_NF_ROLE, + TOTAL_VNF_COUNT, + VNF_FILTER_EMPTY_RESULT +} from 'app/vnfSearch/VnfSearchConstants.js'; +import { globalInlineMessageBarActionTypes } from 'app/globalInlineMessageBar/GlobalInlineMessageBarConstants.js'; +import { ERROR_RETRIEVING_DATA } from 'app/networking/NetworkConstants.js'; + +describe('VnfSearchAction - Action Tests', () => { + it('Action: processVnfFilterPanelCollapse - open', () => { + const result = processVnfFilterPanelCollapse(true); + expect(result).toEqual({ + type: vnfActionTypes.VNF_FILTER_PANEL_TOGGLED, + data: { + vnfVisualizationPanelClass: 'collapsible-panel-main-panel vertical-filter-panel-is-open' + } + }); + }); + + it('Action: processVnfFilterPanelCollapse - close', () => { + const result = processVnfFilterPanelCollapse(false); + expect(result).toEqual({ + type: vnfActionTypes.VNF_FILTER_PANEL_TOGGLED, + data: { + vnfVisualizationPanelClass: 'collapsible-panel-main-panel' + } + }); + }); + + it('Action: clearVnfSearchData', () => { + const result = clearVnfSearchData(); + expect(result).toEqual({ + type: vnfActionTypes.VNF_SEARCH_RESULTS_RECEIVED, + data: { + count: '', + provStatusData: CHART_PROV_STATUS.emptyData, + orchStatusData: CHART_ORCH_STATUS.emptyData, + nfTypeData: CHART_NF_TYPE.emptyData, + nfRoleData: CHART_NF_ROLE.emptyData + } + }); + }); + + it('Action: setNotificationText - with message', () => { + const middlewares = [thunk]; + const mockStore = configureStore(middlewares); + const store = mockStore({ vnfSearch: {} }); + store.dispatch(setNotificationText('test error message', 'WARNING')); + const actions = store.getActions(); + expect(actions).toEqual([{ + type: globalInlineMessageBarActionTypes.SET_GLOBAL_MESSAGE, + data: { + msgText: 'test error message', + msgSeverity: 'WARNING' + } + }]); + }); + + it('Action: processVnfVisualizationsOnFilterChange - data for filter values', () => { + const middlewares = [thunk]; + const mockStore = configureStore(middlewares); + const store = mockStore({ vnfSearch: {} }); + const filterValueMap = { + 1: 'Running', + 2: 'Junk', + 7: 'Blah', + 8: 'Doh' + }; + const expectedActions = [ + { type: vnfActionTypes.VNF_ACTIVATE_BUSY_FEEDBACK }, + { type: globalInlineMessageBarActionTypes.CLEAR_GLOBAL_MESSAGE }, + { + type: vnfActionTypes.VNF_SEARCH_RESULTS_RECEIVED, + data: { + count: 10, + provStatusData: { + values: [ + { x: 'junk', y: 10 } + ] + }, + orchStatusData: { + values: [ + { x: 'running', y: 10 } + ] + }, + nfTypeData: { + values: [ + { x: 'doh', y: 10 } + ] + }, + nfRoleData: { + values: [ + { x: 'blah', y: 10 } + ] + } + } + }, + { type: vnfActionTypes.VNF_DISABLE_BUSY_FEEDBACK } + ]; + fetchMock.mock('*', { + "total": 10, + "aggregations":{ + "nf-role":[{"doc_count":10,"key":"blah"}], + "nf-type":[{"doc_count":10,"key":"doh"}], + "prov-status":[{"doc_count":10,"key":"junk"}], + "orchestration-status":[{"doc_count":10,"key":"running"}] + } + }); + + return store.dispatch(processVnfVisualizationsOnFilterChange(filterValueMap)) + .then( () => { + const actions = store.getActions(); + expect(actions).toEqual(expectedActions); + fetchMock.restore(); + }); + }); + + it('Action: processVnfVisualizationsOnFilterChange - no data for filter values', () => { + const middlewares = [thunk]; + const mockStore = configureStore(middlewares); + const store = mockStore({ vnfSearch: {} }); + const filterValueMap = { + 1: 'Running', + 2: 'Junk', + 7: '', + 8: 'Doh' + }; + const expectedActions = [ + { type: vnfActionTypes.VNF_ACTIVATE_BUSY_FEEDBACK }, + { type: globalInlineMessageBarActionTypes.SET_GLOBAL_MESSAGE, + data: { msgSeverity: "warning", msgText: VNF_FILTER_EMPTY_RESULT } + }, + { + type: vnfActionTypes.VNF_SEARCH_RESULTS_RECEIVED, + data: { + count: TOTAL_VNF_COUNT.emptyData, + provStatusData: CHART_PROV_STATUS.emptyData, + orchStatusData: CHART_ORCH_STATUS.emptyData, + nfTypeData: CHART_NF_TYPE.emptyData, + nfRoleData: CHART_NF_ROLE.emptyData + } + }, + { type: vnfActionTypes.VNF_DISABLE_BUSY_FEEDBACK } + ]; + fetchMock.mock('*', { + "total": 0, + "aggregations":{ + "nf-role":[], + "nf-type":[], + "prov-status":[], + "orchestration-status":[] + } + }); + + return store.dispatch(processVnfVisualizationsOnFilterChange(filterValueMap)) + .then( () => { + const actions = store.getActions(); + expect(actions).toEqual(expectedActions); + fetchMock.restore(); + }); + }); + + it('Action: processVnfVisualizationsOnFilterChange - network error', () => { + const middlewares = [thunk]; + const mockStore = configureStore(middlewares); + const store = mockStore({ vnfSearch: {} }); + const filterValueMap = { + 1: 'Running', + 2: 'Junk', + 7: 'Blah', + 8: 'Doh' + }; + const expectedActions = [ + { type: vnfActionTypes.VNF_ACTIVATE_BUSY_FEEDBACK }, + { type: vnfActionTypes.VNF_DISABLE_BUSY_FEEDBACK }, + { + type: vnfActionTypes.VNF_NETWORK_ERROR, + data: { errorMsg: ERROR_RETRIEVING_DATA } + } + ]; + fetchMock.mock('*', 503); + + return store.dispatch(processVnfVisualizationsOnFilterChange(filterValueMap)) + .then( () => { + const actions = store.getActions(); + expect(actions).toEqual(expectedActions); + fetchMock.restore(); + }); + }); + + it('Action: setNotificationText - no message', () => { + const middlewares = [thunk]; + const mockStore = configureStore(middlewares); + const store = mockStore({ vnfSearch: {} }); + store.dispatch(setNotificationText('', '')); + const actions = store.getActions(); + expect(actions).toEqual([{ + type: globalInlineMessageBarActionTypes.CLEAR_GLOBAL_MESSAGE + }]); + }); +}) diff --git a/src/app/vnfSearch/VnfSearchNfRoleVisualization.jsx b/src/app/vnfSearch/VnfSearchNfRoleVisualization.jsx index 5d09ac4..a71b2ab 100644 --- a/src/app/vnfSearch/VnfSearchNfRoleVisualization.jsx +++ b/src/app/vnfSearch/VnfSearchNfRoleVisualization.jsx @@ -48,7 +48,7 @@ let mapStateToProps = ({vnfSearch}) => { }; }; -class VnfSearchNfRoleVisualization extends Component { +export class VnfSearchNfRoleVisualization extends Component { static propTypes = { processedNfRoleCountChartData: React.PropTypes.object, enableBusyFeedback: React.PropTypes.bool diff --git a/src/app/vnfSearch/VnfSearchNfRoleVisualization.test.js b/src/app/vnfSearch/VnfSearchNfRoleVisualization.test.js new file mode 100644 index 0000000..cf94925 --- /dev/null +++ b/src/app/vnfSearch/VnfSearchNfRoleVisualization.test.js @@ -0,0 +1,154 @@ +import React from 'react'; +import { shallow, mount } from 'enzyme'; +import {Provider} from 'react-redux' +import configureStore from 'redux-mock-store'; +import { BarChart } from 'recharts'; + +import ConnectedVnfSearchNfRoleVisualization, + { VnfSearchNfRoleVisualization } from './VnfSearchNfRoleVisualization.jsx'; +import { CHART_NF_ROLE } from './VnfSearchConstants.js'; +import Spinner from 'utils/SpinnerContainer.jsx'; + +describe('VnfSearchNfRoleVisualization - Shallow render of component', () => { + let wrapper; + const processedNfRoleCountChartDataProp = { + values: [ + {x: 'col 1', y: 3}, + {x: 'col 2', y: 7}, + {x: 'col 3', y: 2} + ] + }; + + beforeEach( () => { + wrapper = shallow( + <VnfSearchNfRoleVisualization + enableBusyFeedback={false} + processedNfRoleCountChartData={processedNfRoleCountChartDataProp} + /> + ); + }) + + it('Render basic component', () => { + expect(wrapper.length).toEqual(1); + expect(wrapper.hasClass('visualizations')).toEqual(true); + }); + + it('Verify Spinner is present but not visible', () => { + expect(wrapper.find(Spinner)).toHaveLength(1); + expect(wrapper.find(Spinner).props().loading).toEqual(false); + }); + + it('Verify BarChart is displayed', () => { + expect(wrapper.find(BarChart)).toHaveLength(1); + expect(wrapper.find(BarChart).props().data).toEqual(processedNfRoleCountChartDataProp.values); + }); +}) + +describe('VnfSearchNfRoleVisualization - Shallow render of component with no chart data', () => { + let wrapper; + const processedNfRoleCountChartDataProp = { + values: null + }; + + beforeEach( () => { + wrapper = shallow( + <VnfSearchNfRoleVisualization + enableBusyFeedback={false} + processedNfRoleCountChartData={processedNfRoleCountChartDataProp} + /> + ); + }) + + it('Visualization graph hidden', () => { + expect(wrapper.length).toEqual(1); + expect(['visualizations', 'hidden'].every(className => wrapper.hasClass(className))).toEqual(true); + }); +}) + +describe('VnfSearchNfRoleVisualization - Shallow render of component with busy feedback', () => { + let wrapper; + const processedNfRoleCountChartDataProp = { + values: [ + {x: 'col 1', y: 3}, + {x: 'col 2', y: 7}, + {x: 'col 3', y: 2} + ] + }; + + beforeEach( () => { + wrapper = shallow( + <VnfSearchNfRoleVisualization + enableBusyFeedback={true} + processedNfRoleCountChartData={processedNfRoleCountChartDataProp} + /> + ); + }) + + it('Render basic component', () => { + expect(wrapper.length).toEqual(1); + expect(wrapper.hasClass('visualizations')).toEqual(true); + }); + + it('Verify Spinner is present and visible', () => { + expect(wrapper.find(Spinner)).toHaveLength(1); + expect(wrapper.find(Spinner).props().loading).toEqual(true); + }); + + it('Verify BarChart is displayed', () => { + expect(wrapper.find(BarChart)).toHaveLength(1); + expect(wrapper.find(BarChart).props().data).toEqual(processedNfRoleCountChartDataProp.values); + }); +}) + +describe('VnfSearchNfRoleVisualization - Render React Component (wrapped in <Provider>)', () => { + const initialState = { + vnfSearch: { + processedNfRoleCountChartData: { + values: [ + {x: 'col 1', y: 3}, + {x: 'col 2', y: 7}, + {x: 'col 3', y: 2} + ] + }, + enableBusyFeedback: false + } + }; + const mockStore = configureStore(); + let store, wrapper; + + beforeEach( () => { + store = mockStore(initialState); + wrapper = mount(<Provider store={store}><ConnectedVnfSearchNfRoleVisualization /></Provider>); + }) + + it('Render the connected component', () => { + expect(wrapper.find(ConnectedVnfSearchNfRoleVisualization).length).toEqual(1); + }); + + it('Validate props from store', () => { + expect(wrapper.find(VnfSearchNfRoleVisualization).props().enableBusyFeedback).toEqual(initialState.vnfSearch.enableBusyFeedback); + expect(wrapper.find(VnfSearchNfRoleVisualization).props().processedNfRoleCountChartData).toEqual(initialState.vnfSearch.processedNfRoleCountChartData); + }); +}) + +describe('VnfSearchNfRoleVisualization - Render React Component (wrapped in <Provider>) with default props', () => { + const initialState = { + vnfSearch: {} + }; + const mockStore = configureStore(); + let store, wrapper; + + beforeEach( () => { + store = mockStore(initialState); + wrapper = mount(<Provider store={store}><ConnectedVnfSearchNfRoleVisualization /></Provider>); + }) + + it('Render the connected component', () => { + expect(wrapper.find(ConnectedVnfSearchNfRoleVisualization).length).toEqual(1); + }); + + it('Validate default props loaded', () => { + expect(wrapper.find(VnfSearchNfRoleVisualization).props().enableBusyFeedback).toEqual(false); + expect(wrapper.find(VnfSearchNfRoleVisualization).props().processedNfRoleCountChartData).toEqual(CHART_NF_ROLE.emptyData); + }); +}) diff --git a/src/app/vnfSearch/VnfSearchNfTypeVisualization.jsx b/src/app/vnfSearch/VnfSearchNfTypeVisualization.jsx index 5b540d9..492d1c9 100644 --- a/src/app/vnfSearch/VnfSearchNfTypeVisualization.jsx +++ b/src/app/vnfSearch/VnfSearchNfTypeVisualization.jsx @@ -48,7 +48,7 @@ let mapStateToProps = ({vnfSearch}) => { }; }; -class VnfSearchNfTypeVisualization extends Component { +export class VnfSearchNfTypeVisualization extends Component { static propTypes = { processedNfTypeCountChartData: React.PropTypes.object, enableBusyFeedback: React.PropTypes.bool diff --git a/src/app/vnfSearch/VnfSearchNfTypeVisualization.test.js b/src/app/vnfSearch/VnfSearchNfTypeVisualization.test.js new file mode 100644 index 0000000..bbb2907 --- /dev/null +++ b/src/app/vnfSearch/VnfSearchNfTypeVisualization.test.js @@ -0,0 +1,154 @@ +import React from 'react'; +import { shallow, mount } from 'enzyme'; +import {Provider} from 'react-redux' +import configureStore from 'redux-mock-store'; +import { BarChart } from 'recharts'; + +import ConnectedVnfSearchNfTypeVisualization, + { VnfSearchNfTypeVisualization } from './VnfSearchNfTypeVisualization.jsx'; +import { CHART_NF_TYPE } from './VnfSearchConstants.js'; +import Spinner from 'utils/SpinnerContainer.jsx'; + +describe('VnfSearchNfTypeVisualization - Shallow render of component', () => { + let wrapper; + const processedNfTypeCountChartDataProp = { + values: [ + {x: 'col 1', y: 3}, + {x: 'col 2', y: 7}, + {x: 'col 3', y: 2} + ] + }; + + beforeEach( () => { + wrapper = shallow( + <VnfSearchNfTypeVisualization + enableBusyFeedback={false} + processedNfTypeCountChartData={processedNfTypeCountChartDataProp} + /> + ); + }) + + it('Render basic component', () => { + expect(wrapper.length).toEqual(1); + expect(wrapper.hasClass('visualizations')).toEqual(true); + }); + + it('Verify Spinner is present but not visible', () => { + expect(wrapper.find(Spinner)).toHaveLength(1); + expect(wrapper.find(Spinner).props().loading).toEqual(false); + }); + + it('Verify BarChart is displayed', () => { + expect(wrapper.find(BarChart)).toHaveLength(1); + expect(wrapper.find(BarChart).props().data).toEqual(processedNfTypeCountChartDataProp.values); + }); +}) + +describe('VnfSearchNfTypeVisualization - Shallow render of component with no chart data', () => { + let wrapper; + const processedNfTypeCountChartDataProp = { + values: null + }; + + beforeEach( () => { + wrapper = shallow( + <VnfSearchNfTypeVisualization + enableBusyFeedback={false} + processedNfTypeCountChartData={processedNfTypeCountChartDataProp} + /> + ); + }) + + it('Visualization graph hidden', () => { + expect(wrapper.length).toEqual(1); + expect(['visualizations', 'hidden'].every(className => wrapper.hasClass(className))).toEqual(true); + }); +}) + +describe('VnfSearchNfTypeVisualization - Shallow render of component with busy feedback', () => { + let wrapper; + const processedNfTypeCountChartDataProp = { + values: [ + {x: 'col 1', y: 3}, + {x: 'col 2', y: 7}, + {x: 'col 3', y: 2} + ] + }; + + beforeEach( () => { + wrapper = shallow( + <VnfSearchNfTypeVisualization + enableBusyFeedback={true} + processedNfTypeCountChartData={processedNfTypeCountChartDataProp} + /> + ); + }) + + it('Render basic component', () => { + expect(wrapper.length).toEqual(1); + expect(wrapper.hasClass('visualizations')).toEqual(true); + }); + + it('Verify Spinner is present and visible', () => { + expect(wrapper.find(Spinner)).toHaveLength(1); + expect(wrapper.find(Spinner).props().loading).toEqual(true); + }); + + it('Verify BarChart is displayed', () => { + expect(wrapper.find(BarChart)).toHaveLength(1); + expect(wrapper.find(BarChart).props().data).toEqual(processedNfTypeCountChartDataProp.values); + }); +}) + +describe('VnfSearchNfTypeVisualization - Render React Component (wrapped in <Provider>)', () => { + const initialState = { + vnfSearch: { + processedNfTypeCountChartData: { + values: [ + {x: 'col 1', y: 3}, + {x: 'col 2', y: 7}, + {x: 'col 3', y: 2} + ] + }, + enableBusyFeedback: false + } + }; + const mockStore = configureStore(); + let store, wrapper; + + beforeEach( () => { + store = mockStore(initialState); + wrapper = mount(<Provider store={store}><ConnectedVnfSearchNfTypeVisualization /></Provider>); + }) + + it('Render the connected component', () => { + expect(wrapper.find(ConnectedVnfSearchNfTypeVisualization).length).toEqual(1); + }); + + it('Validate props from store', () => { + expect(wrapper.find(VnfSearchNfTypeVisualization).props().enableBusyFeedback).toEqual(initialState.vnfSearch.enableBusyFeedback); + expect(wrapper.find(VnfSearchNfTypeVisualization).props().processedNfTypeCountChartData).toEqual(initialState.vnfSearch.processedNfTypeCountChartData); + }); +}) + +describe('VnfSearchNfTypeVisualization - Render React Component (wrapped in <Provider>) with default props', () => { + const initialState = { + vnfSearch: {} + }; + const mockStore = configureStore(); + let store, wrapper; + + beforeEach( () => { + store = mockStore(initialState); + wrapper = mount(<Provider store={store}><ConnectedVnfSearchNfTypeVisualization /></Provider>); + }) + + it('Render the connected component', () => { + expect(wrapper.find(ConnectedVnfSearchNfTypeVisualization).length).toEqual(1); + }); + + it('Validate default props loaded', () => { + expect(wrapper.find(VnfSearchNfTypeVisualization).props().enableBusyFeedback).toEqual(false); + expect(wrapper.find(VnfSearchNfTypeVisualization).props().processedNfTypeCountChartData).toEqual(CHART_NF_TYPE.emptyData); + }); +}) diff --git a/src/app/vnfSearch/VnfSearchOrchestratedStatusVisualization.jsx b/src/app/vnfSearch/VnfSearchOrchestratedStatusVisualization.jsx index be13d07..8dc25ca 100644 --- a/src/app/vnfSearch/VnfSearchOrchestratedStatusVisualization.jsx +++ b/src/app/vnfSearch/VnfSearchOrchestratedStatusVisualization.jsx @@ -48,7 +48,7 @@ let mapStateToProps = ({vnfSearch}) => { }; }; -class VnfSearchOrchStatusVisualizations extends Component { +export class VnfSearchOrchStatusVisualizations extends Component { static propTypes = { processedOrchStatusCountChartData: React.PropTypes.object, enableBusyFeedback: React.PropTypes.bool diff --git a/src/app/vnfSearch/VnfSearchOrchestratedStatusVisualization.test.js b/src/app/vnfSearch/VnfSearchOrchestratedStatusVisualization.test.js new file mode 100644 index 0000000..1257f3a --- /dev/null +++ b/src/app/vnfSearch/VnfSearchOrchestratedStatusVisualization.test.js @@ -0,0 +1,154 @@ +import React from 'react'; +import { shallow, mount } from 'enzyme'; +import {Provider} from 'react-redux' +import configureStore from 'redux-mock-store'; +import { BarChart } from 'recharts'; + +import ConnectedVnfSearchOrchStatusVisualizations, + { VnfSearchOrchStatusVisualizations } from './VnfSearchOrchestratedStatusVisualization.jsx'; +import { CHART_ORCH_STATUS } from './VnfSearchConstants.js'; +import Spinner from 'utils/SpinnerContainer.jsx'; + +describe('VnfSearchOrchStatusVisualizations - Shallow render of component', () => { + let wrapper; + const processedOrchStatusCountChartDataProp = { + values: [ + {x: 'col 1', y: 3}, + {x: 'col 2', y: 7}, + {x: 'col 3', y: 2} + ] + }; + + beforeEach( () => { + wrapper = shallow( + <VnfSearchOrchStatusVisualizations + enableBusyFeedback={false} + processedOrchStatusCountChartData={processedOrchStatusCountChartDataProp} + /> + ); + }) + + it('Render basic component', () => { + expect(wrapper.length).toEqual(1); + expect(wrapper.hasClass('visualizations')).toEqual(true); + }); + + it('Verify Spinner is present but not visible', () => { + expect(wrapper.find(Spinner)).toHaveLength(1); + expect(wrapper.find(Spinner).props().loading).toEqual(false); + }); + + it('Verify BarChart is displayed', () => { + expect(wrapper.find(BarChart)).toHaveLength(1); + expect(wrapper.find(BarChart).props().data).toEqual(processedOrchStatusCountChartDataProp.values); + }); +}) + +describe('VnfSearchOrchStatusVisualizations - Shallow render of component with no chart data', () => { + let wrapper; + const processedOrchStatusCountChartDataProp = { + values: null + }; + + beforeEach( () => { + wrapper = shallow( + <VnfSearchOrchStatusVisualizations + enableBusyFeedback={false} + processedOrchStatusCountChartData={processedOrchStatusCountChartDataProp} + /> + ); + }) + + it('Visualization graph hidden', () => { + expect(wrapper.length).toEqual(1); + expect(['visualizations', 'hidden'].every(className => wrapper.hasClass(className))).toEqual(true); + }); +}) + +describe('VnfSearchOrchStatusVisualizations - Shallow render of component with busy feedback', () => { + let wrapper; + const processedOrchStatusCountChartDataProp = { + values: [ + {x: 'col 1', y: 3}, + {x: 'col 2', y: 7}, + {x: 'col 3', y: 2} + ] + }; + + beforeEach( () => { + wrapper = shallow( + <VnfSearchOrchStatusVisualizations + enableBusyFeedback={true} + processedOrchStatusCountChartData={processedOrchStatusCountChartDataProp} + /> + ); + }) + + it('Render basic component', () => { + expect(wrapper.length).toEqual(1); + expect(wrapper.hasClass('visualizations')).toEqual(true); + }); + + it('Verify Spinner is present and visible', () => { + expect(wrapper.find(Spinner)).toHaveLength(1); + expect(wrapper.find(Spinner).props().loading).toEqual(true); + }); + + it('Verify BarChart is displayed', () => { + expect(wrapper.find(BarChart)).toHaveLength(1); + expect(wrapper.find(BarChart).props().data).toEqual(processedOrchStatusCountChartDataProp.values); + }); +}) + +describe('VnfSearchOrchStatusVisualizations - Render React Component (wrapped in <Provider>)', () => { + const initialState = { + vnfSearch: { + processedOrchStatusCountChartData: { + values: [ + {x: 'col 1', y: 3}, + {x: 'col 2', y: 7}, + {x: 'col 3', y: 2} + ] + }, + enableBusyFeedback: false + } + }; + const mockStore = configureStore(); + let store, wrapper; + + beforeEach( () => { + store = mockStore(initialState); + wrapper = mount(<Provider store={store}><ConnectedVnfSearchOrchStatusVisualizations /></Provider>); + }) + + it('Render the connected component', () => { + expect(wrapper.find(ConnectedVnfSearchOrchStatusVisualizations).length).toEqual(1); + }); + + it('Validate props from store', () => { + expect(wrapper.find(VnfSearchOrchStatusVisualizations).props().enableBusyFeedback).toEqual(initialState.vnfSearch.enableBusyFeedback); + expect(wrapper.find(VnfSearchOrchStatusVisualizations).props().processedOrchStatusCountChartData).toEqual(initialState.vnfSearch.processedOrchStatusCountChartData); + }); +}) + +describe('VnfSearchOrchStatusVisualizations - Render React Component (wrapped in <Provider>) with default props', () => { + const initialState = { + vnfSearch: {} + }; + const mockStore = configureStore(); + let store, wrapper; + + beforeEach( () => { + store = mockStore(initialState); + wrapper = mount(<Provider store={store}><ConnectedVnfSearchOrchStatusVisualizations /></Provider>); + }) + + it('Render the connected component', () => { + expect(wrapper.find(ConnectedVnfSearchOrchStatusVisualizations).length).toEqual(1); + }); + + it('Validate default props loaded', () => { + expect(wrapper.find(VnfSearchOrchStatusVisualizations).props().enableBusyFeedback).toEqual(false); + expect(wrapper.find(VnfSearchOrchStatusVisualizations).props().processedOrchStatusCountChartData).toEqual(CHART_ORCH_STATUS.emptyData); + }); +}) diff --git a/src/app/vnfSearch/VnfSearchProvStatusVisualization.jsx b/src/app/vnfSearch/VnfSearchProvStatusVisualization.jsx index a7c31c0..07ba988 100644 --- a/src/app/vnfSearch/VnfSearchProvStatusVisualization.jsx +++ b/src/app/vnfSearch/VnfSearchProvStatusVisualization.jsx @@ -48,7 +48,7 @@ let mapStateToProps = ({vnfSearch}) => { }; }; -class VnfSearchProvStatusVisualization extends Component { +export class VnfSearchProvStatusVisualization extends Component { static propTypes = { processedProvStatusCountChartData: React.PropTypes.object, enableBusyFeedback: React.PropTypes.bool diff --git a/src/app/vnfSearch/VnfSearchProvStatusVisualization.test.js b/src/app/vnfSearch/VnfSearchProvStatusVisualization.test.js new file mode 100644 index 0000000..4812834 --- /dev/null +++ b/src/app/vnfSearch/VnfSearchProvStatusVisualization.test.js @@ -0,0 +1,154 @@ +import React from 'react'; +import { shallow, mount } from 'enzyme'; +import {Provider} from 'react-redux' +import configureStore from 'redux-mock-store'; +import { BarChart } from 'recharts'; + +import ConnectedVnfSearchProvStatusVisualization, + { VnfSearchProvStatusVisualization } from './VnfSearchProvStatusVisualization.jsx'; +import { CHART_PROV_STATUS } from './VnfSearchConstants.js'; +import Spinner from 'utils/SpinnerContainer.jsx'; + +describe('VnfSearchProvStatusVisualization - Shallow render of component', () => { + let wrapper; + const processedProvStatusCountChartDataProp = { + values: [ + {x: 'col 1', y: 3}, + {x: 'col 2', y: 7}, + {x: 'col 3', y: 2} + ] + }; + + beforeEach( () => { + wrapper = shallow( + <VnfSearchProvStatusVisualization + enableBusyFeedback={false} + processedProvStatusCountChartData={processedProvStatusCountChartDataProp} + /> + ); + }) + + it('Render basic component', () => { + expect(wrapper.length).toEqual(1); + expect(wrapper.hasClass('visualizations')).toEqual(true); + }); + + it('Verify Spinner is present but not visible', () => { + expect(wrapper.find(Spinner)).toHaveLength(1); + expect(wrapper.find(Spinner).props().loading).toEqual(false); + }); + + it('Verify BarChart is displayed', () => { + expect(wrapper.find(BarChart)).toHaveLength(1); + expect(wrapper.find(BarChart).props().data).toEqual(processedProvStatusCountChartDataProp.values); + }); +}) + +describe('VnfSearchProvStatusVisualization - Shallow render of component with no chart data', () => { + let wrapper; + const processedProvStatusCountChartDataProp = { + values: null + }; + + beforeEach( () => { + wrapper = shallow( + <VnfSearchProvStatusVisualization + enableBusyFeedback={false} + processedProvStatusCountChartData={processedProvStatusCountChartDataProp} + /> + ); + }) + + it('Visualization graph hidden', () => { + expect(wrapper.length).toEqual(1); + expect(['visualizations', 'hidden'].every(className => wrapper.hasClass(className))).toEqual(true); + }); +}) + +describe('VnfSearchProvStatusVisualization - Shallow render of component with busy feedback', () => { + let wrapper; + const processedProvStatusCountChartDataProp = { + values: [ + {x: 'col 1', y: 3}, + {x: 'col 2', y: 7}, + {x: 'col 3', y: 2} + ] + }; + + beforeEach( () => { + wrapper = shallow( + <VnfSearchProvStatusVisualization + enableBusyFeedback={true} + processedProvStatusCountChartData={processedProvStatusCountChartDataProp} + /> + ); + }) + + it('Render basic component', () => { + expect(wrapper.length).toEqual(1); + expect(wrapper.hasClass('visualizations')).toEqual(true); + }); + + it('Verify Spinner is present and visible', () => { + expect(wrapper.find(Spinner)).toHaveLength(1); + expect(wrapper.find(Spinner).props().loading).toEqual(true); + }); + + it('Verify BarChart is displayed', () => { + expect(wrapper.find(BarChart)).toHaveLength(1); + expect(wrapper.find(BarChart).props().data).toEqual(processedProvStatusCountChartDataProp.values); + }); +}) + +describe('VnfSearchProvStatusVisualization - Render React Component (wrapped in <Provider>)', () => { + const initialState = { + vnfSearch: { + processedProvStatusCountChartData: { + values: [ + {x: 'col 1', y: 3}, + {x: 'col 2', y: 7}, + {x: 'col 3', y: 2} + ] + }, + enableBusyFeedback: false + } + }; + const mockStore = configureStore(); + let store, wrapper; + + beforeEach( () => { + store = mockStore(initialState); + wrapper = mount(<Provider store={store}><ConnectedVnfSearchProvStatusVisualization /></Provider>); + }) + + it('Render the connected component', () => { + expect(wrapper.find(ConnectedVnfSearchProvStatusVisualization).length).toEqual(1); + }); + + it('Validate props from store', () => { + expect(wrapper.find(VnfSearchProvStatusVisualization).props().enableBusyFeedback).toEqual(initialState.vnfSearch.enableBusyFeedback); + expect(wrapper.find(VnfSearchProvStatusVisualization).props().processedProvStatusCountChartData).toEqual(initialState.vnfSearch.processedProvStatusCountChartData); + }); +}) + +describe('VnfSearchProvStatusVisualization - Render React Component (wrapped in <Provider>) with default props', () => { + const initialState = { + vnfSearch: {} + }; + const mockStore = configureStore(); + let store, wrapper; + + beforeEach( () => { + store = mockStore(initialState); + wrapper = mount(<Provider store={store}><ConnectedVnfSearchProvStatusVisualization /></Provider>); + }) + + it('Render the connected component', () => { + expect(wrapper.find(ConnectedVnfSearchProvStatusVisualization).length).toEqual(1); + }); + + it('Validate default props loaded', () => { + expect(wrapper.find(VnfSearchProvStatusVisualization).props().enableBusyFeedback).toEqual(false); + expect(wrapper.find(VnfSearchProvStatusVisualization).props().processedProvStatusCountChartData).toEqual(CHART_PROV_STATUS.emptyData); + }); +}) diff --git a/src/app/vnfSearch/VnfSearchReducer.test.js b/src/app/vnfSearch/VnfSearchReducer.test.js new file mode 100644 index 0000000..ff06770 --- /dev/null +++ b/src/app/vnfSearch/VnfSearchReducer.test.js @@ -0,0 +1,438 @@ +import VnfSearchReducer from './VnfSearchReducer.js'; +import { + vnfActionTypes, + CHART_ORCH_STATUS, + CHART_PROV_STATUS, + CHART_NF_ROLE, + CHART_NF_TYPE, + TOTAL_VNF_COUNT +} from './VnfSearchConstants.js'; +import {ERROR_RETRIEVING_DATA} from 'app/networking/NetworkConstants.js'; +import { + filterBarActionTypes, + MESSAGE_LEVEL_DANGER +} from 'utils/GlobalConstants.js'; +import { + globalAutoCompleteSearchBarActionTypes +} from 'app/globalAutoCompleteSearchBar/GlobalAutoCompleteSearchBarConstants.js'; + +describe('VnfSearchReducer - Reducer Action Type Tests', () => { + it('Action Type: VNF_NETWORK_ERROR', () => { + const action = { + type: vnfActionTypes.VNF_NETWORK_ERROR + }; + let state = { + processedProvStatusCountChartData: { + values: [ + {x: 'col 1', y: 3}, + {x: 'col 2', y: 7}, + {x: 'col 3', y: 2} + ] + }, + processedOrchStatusCountChartData: { + values: [ + {x: 'col 1', y: 3}, + {x: 'col 2', y: 7}, + {x: 'col 3', y: 2} + ] + }, + processedNfTypeCountChartData: { + values: [ + {x: 'col 1', y: 3}, + {x: 'col 2', y: 7}, + {x: 'col 3', y: 2} + ] + }, + processedNfRoleCountChartData: { + values: [ + {x: 'col 1', y: 3}, + {x: 'col 2', y: 7}, + {x: 'col 3', y: 2} + ] + }, + count: 20, + feedbackMsgText: '', + feedbackMsgSeverity: '' + }; + state = VnfSearchReducer(state, action); + expect(state).toEqual({ + processedProvStatusCountChartData: CHART_PROV_STATUS.emptyData, + processedOrchStatusCountChartData: CHART_ORCH_STATUS.emptyData, + processedNfTypeCountChartData: CHART_NF_TYPE.emptyData, + processedNfRoleCountChartData: CHART_NF_ROLE.emptyData, + count: TOTAL_VNF_COUNT.emptyValue, + feedbackMsgText: ERROR_RETRIEVING_DATA, + feedbackMsgSeverity: MESSAGE_LEVEL_DANGER + }); + }); + + it('Action Type: SEARCH_WARNING_EVENT', () => { + const action = { + type: globalAutoCompleteSearchBarActionTypes.SEARCH_WARNING_EVENT + }; + let state = { + processedProvStatusCountChartData: { + values: [ + {x: 'col 1', y: 3}, + {x: 'col 2', y: 7}, + {x: 'col 3', y: 2} + ] + }, + processedOrchStatusCountChartData: { + values: [ + {x: 'col 1', y: 3}, + {x: 'col 2', y: 7}, + {x: 'col 3', y: 2} + ] + }, + processedNfTypeCountChartData: { + values: [ + {x: 'col 1', y: 3}, + {x: 'col 2', y: 7}, + {x: 'col 3', y: 2} + ] + }, + processedNfRoleCountChartData: { + values: [ + {x: 'col 1', y: 3}, + {x: 'col 2', y: 7}, + {x: 'col 3', y: 2} + ] + }, + count: 20, + }; + state = VnfSearchReducer(state, action); + expect(state).toEqual({ + processedProvStatusCountChartData: CHART_PROV_STATUS.emptyData, + processedOrchStatusCountChartData: CHART_ORCH_STATUS.emptyData, + processedNfTypeCountChartData: CHART_NF_TYPE.emptyData, + processedNfRoleCountChartData: CHART_NF_ROLE.emptyData, + count: TOTAL_VNF_COUNT.emptyValue, + }); + }); + + it('Action Type: NEW_SELECTIONS', () => { + const action = { + type: filterBarActionTypes.NEW_SELECTIONS, + data: { + selectedValuesMap: [ + { filter1: ['someValue'] } + ], + unifiedValues: [ + { filter1: ['someValue', 'someOtherValue']} + ] + } + }; + let state = { + vnfFilterValues: {}, + unifiedFilterValues: {} + }; + state = VnfSearchReducer(state, action); + expect(state).toEqual({ + vnfFilterValues: action.data.selectedValuesMap, + unifiedFilterValues: action.data.unifiedValues + }); + }); + + it('Action Type: SET_UNIFIED_VALUES', () => { + const action = { + type: filterBarActionTypes.SET_UNIFIED_VALUES, + data: { + unifiedValues: [ + { filter1: ['someValue', 'someOtherValue']} + ] + } + }; + let state = { + unifiedFilterValues: {} + }; + state = VnfSearchReducer(state, action); + expect(state).toEqual({ + unifiedFilterValues: action.data + }); + }); + + it('Action Type: VNF_SEARCH_RESULTS_RECEIVED', () => { + const action = { + type: vnfActionTypes.VNF_SEARCH_RESULTS_RECEIVED, + data: { + provStatusData: { + values: [ + {x: 'col 1', y: 3}, + {x: 'col 2', y: 7}, + {x: 'col 3', y: 2} + ] + }, + orchStatusData: { + values: [ + {x: 'col 1', y: 3}, + {x: 'col 2', y: 7}, + {x: 'col 3', y: 2} + ] + }, + nfTypeData: { + values: [ + {x: 'col 1', y: 3}, + {x: 'col 2', y: 7}, + {x: 'col 3', y: 2} + ] + }, + nfRoleData: { + values: [ + {x: 'col 1', y: 3}, + {x: 'col 2', y: 7}, + {x: 'col 3', y: 2} + ] + }, + count: 25, + } + }; + let state = { + processedProvStatusCountChartData: {}, + processedOrchStatusCountChartData: {}, + processedNfTypeCountChartData: {}, + processedNfRoleCountChartData: {}, + count: 0, + feedbackMsgText: 'some error msg', + feedbackMsgSeverity: 'someSeverityLevel' + }; + state = VnfSearchReducer(state, action); + expect(state).toEqual({ + processedProvStatusCountChartData: action.data.provStatusData, + processedOrchStatusCountChartData: action.data.orchStatusData, + processedNfTypeCountChartData: action.data.nfTypeData, + processedNfRoleCountChartData: action.data.nfRoleData, + count: action.data.count, + feedbackMsgText: '', + feedbackMsgSeverity: '' + }); + }); + + it('Action Type: VNF_FILTER_PANEL_TOGGLED', () => { + const action = { + type: vnfActionTypes.VNF_FILTER_PANEL_TOGGLED, + data: { + vnfVisualizationPanelClass: 'hide', + } + }; + let state = { + vnfVisualizationPanelClass: 'show' + }; + state = VnfSearchReducer(state, action); + expect(state).toEqual({ + vnfVisualizationPanelClass: 'hide' + }); + }); + + it('Action Type: VNF_SEARCH_FILTERS_RECEIVED', () => { + const action = { + type: vnfActionTypes.VNF_SEARCH_FILTERS_RECEIVED, + data: [ + { filter1: 'value 1' }, + { filter2: 'value 2' } + ] + }; + let state = { + vnfFilters: [] + }; + state = VnfSearchReducer(state, action); + expect(state).toEqual({ + vnfFilters: action.data + }); + }); + + it('Action Type: SET_NON_CONVERTED_VALUES', () => { + const action = { + type: filterBarActionTypes.SET_NON_CONVERTED_VALUES, + data: [ + { value1: 'abc' }, + { value2: 'xyz' } + ] + }; + let state = { + nonConvertedFilters: [] + }; + state = VnfSearchReducer(state, action); + expect(state).toEqual({ + nonConvertedFilters: action.data + }); + }); + + it('Action Type: SET_CONVERTED_VALUES', () => { + const action = { + type: filterBarActionTypes.SET_CONVERTED_VALUES, + data: { + convertedValues: { + value1: 'abc', + value2: 'xyz' + }, + nonConvertedValues: { + value1: 123, + value2: 456 + } + } + }; + let state = { + nonConvertedFilters: { + filter1: 'one', + filter2: 'two' + }, + unifiedFilterValues: {}, + vnfFilterValues: {} + }; + state = VnfSearchReducer(state, action); + expect(state).toEqual({ + nonConvertedFilters: {}, + unifiedFilterValues: action.data.convertedValues, + vnfFilterValues: action.data.nonConvertedValues + }); + }); + + it('Action Type: VNF_ACTIVATE_BUSY_FEEDBACK', () => { + const action = { + type: vnfActionTypes.VNF_ACTIVATE_BUSY_FEEDBACK + }; + let state = { + enableBusyFeedback: false + }; + state = VnfSearchReducer(state, action); + expect(state).toEqual({ + enableBusyFeedback: true + }); + }); + + it('Action Type: VNF_DISABLE_BUSY_FEEDBACK', () => { + const action = { + type: vnfActionTypes.VNF_DISABLE_BUSY_FEEDBACK + }; + let state = { + enableBusyFeedback: true + }; + state = VnfSearchReducer(state, action); + expect(state).toEqual({ + enableBusyFeedback: false + }); + }); + + it('Action Type: CLEAR_FILTERS', () => { + const action = { + type: filterBarActionTypes.CLEAR_FILTERS + }; + let state = { + vnfFilters: { + filter1: 'filterName1' + }, + vnfFilterValues: { + filter1: 'value 1' + }, + nonConvertedFilters: { + nonConvertedFilter1: 'some fitler props' + }, + unifiedFilterValues: { + unifiedFilter1: 'some unified props' + } + }; + state = VnfSearchReducer(state, action); + expect(state).toEqual({ + vnfFilters: {}, + vnfFilterValues: {}, + nonConvertedFilters: {}, + unifiedFilterValues: {} + }); + }); + + it('Invalid Action Type', () => { + const action = { + type: 'Nonexistent Action Type', + }; + let state = { + vnfFilters: { + filter1: 'filterName1' + }, + vnfFilterValues: { + filter1: 'value 1' + }, + nonConvertedFilters: { + nonConvertedFilter1: 'some fitler props' + }, + unifiedFilterValues: { + unifiedFilter1: 'some unified props' + }, + enableBusyFeedback: true, + provStatusData: { + values: [ + {x: 'col 1', y: 3}, + {x: 'col 2', y: 7}, + {x: 'col 3', y: 2} + ] + }, + orchStatusData: { + values: [ + {x: 'col 1', y: 3}, + {x: 'col 2', y: 7}, + {x: 'col 3', y: 2} + ] + }, + nfTypeData: { + values: [ + {x: 'col 1', y: 3}, + {x: 'col 2', y: 7}, + {x: 'col 3', y: 2} + ] + }, + nfRoleData: { + values: [ + {x: 'col 1', y: 3}, + {x: 'col 2', y: 7}, + {x: 'col 3', y: 2} + ] + }, + count: 25 + }; + state = VnfSearchReducer(state, action); + expect(state).toEqual({ + vnfFilters: { + filter1: 'filterName1' + }, + vnfFilterValues: { + filter1: 'value 1' + }, + nonConvertedFilters: { + nonConvertedFilter1: 'some fitler props' + }, + unifiedFilterValues: { + unifiedFilter1: 'some unified props' + }, + enableBusyFeedback: true, + provStatusData: { + values: [ + {x: 'col 1', y: 3}, + {x: 'col 2', y: 7}, + {x: 'col 3', y: 2} + ] + }, + orchStatusData: { + values: [ + {x: 'col 1', y: 3}, + {x: 'col 2', y: 7}, + {x: 'col 3', y: 2} + ] + }, + nfTypeData: { + values: [ + {x: 'col 1', y: 3}, + {x: 'col 2', y: 7}, + {x: 'col 3', y: 2} + ] + }, + nfRoleData: { + values: [ + {x: 'col 1', y: 3}, + {x: 'col 2', y: 7}, + {x: 'col 3', y: 2} + ] + }, + count: 25 + }); + }); +}) diff --git a/src/app/vnfSearch/VnfSearchTotalCountVisualization.jsx b/src/app/vnfSearch/VnfSearchTotalCountVisualization.jsx index 3a767b9..3c73d22 100644 --- a/src/app/vnfSearch/VnfSearchTotalCountVisualization.jsx +++ b/src/app/vnfSearch/VnfSearchTotalCountVisualization.jsx @@ -38,7 +38,7 @@ let mapStateToProps = ({vnfSearch}) => { }; }; -class VnfSearchTotalCountVisualization extends Component { +export class VnfSearchTotalCountVisualization extends Component { static propTypes = { count: React.PropTypes.oneOfType([ React.PropTypes.string, diff --git a/src/app/vnfSearch/VnfSearchTotalCountVisualization.test.js b/src/app/vnfSearch/VnfSearchTotalCountVisualization.test.js new file mode 100644 index 0000000..e891c12 --- /dev/null +++ b/src/app/vnfSearch/VnfSearchTotalCountVisualization.test.js @@ -0,0 +1,131 @@ +import React from 'react'; +import { shallow, mount } from 'enzyme'; +import {Provider} from 'react-redux' +import configureStore from 'redux-mock-store'; + +import ConnectedVnfSearchTotalCountVisualization, + { VnfSearchTotalCountVisualization } from './VnfSearchTotalCountVisualization.jsx'; +import { TOTAL_VNF_COUNT } from './VnfSearchConstants.js'; +import Spinner from 'utils/SpinnerContainer.jsx'; + +describe('VnfSearchTotalCountVisualization - Shallow render of component', () => { + let wrapper; + const countProp = 25; + + beforeEach( () => { + wrapper = shallow( + <VnfSearchTotalCountVisualization + enableBusyFeedback={false} + count={countProp} + /> + ); + }) + + it('Render basic component', () => { + expect(wrapper.length).toEqual(1); + expect(wrapper.hasClass('visualizations')).toEqual(true); + }); + + it('Verify Spinner is present but not visible', () => { + expect(wrapper.find(Spinner)).toHaveLength(1); + expect(wrapper.find(Spinner).props().loading).toEqual(false); + }); + + it('Verify total count is displayed', () => { + expect(wrapper.contains(<span>{countProp}</span>)).toBe(true); + }); +}) + +describe('VnfSearchTotalCountVisualization - Shallow render of component with no chart data', () => { + let wrapper; + const countProp = null; + + beforeEach( () => { + wrapper = shallow( + <VnfSearchTotalCountVisualization + enableBusyFeedback={false} + count={countProp} + /> + ); + }) + + it('Visualization graph hidden', () => { + expect(wrapper.length).toEqual(1); + expect(['visualizations', 'hidden'].every(className => wrapper.hasClass(className))).toEqual(true); + }); +}) + +describe('VnfSearchTotalCountVisualization - Shallow render of component with busy feedback', () => { + let wrapper; + const countProp = 25; + + beforeEach( () => { + wrapper = shallow( + <VnfSearchTotalCountVisualization + enableBusyFeedback={true} + count={countProp} + /> + ); + }) + + it('Render basic component', () => { + expect(wrapper.length).toEqual(1); + expect(wrapper.hasClass('visualizations')).toEqual(true); + }); + + it('Verify Spinner is present and visible', () => { + expect(wrapper.find(Spinner)).toHaveLength(1); + expect(wrapper.find(Spinner).props().loading).toEqual(true); + }); + + it('Verify total count is displayed', () => { + expect(wrapper.contains(<span>{countProp}</span>)).toBe(true); + }); +}) + +describe('VnfSearchTotalCountVisualization - Render React Component (wrapped in <Provider>)', () => { + const initialState = { + vnfSearch: { + count: 25, + enableBusyFeedback: false + } + }; + const mockStore = configureStore(); + let store, wrapper; + + beforeEach( () => { + store = mockStore(initialState); + wrapper = mount(<Provider store={store}><ConnectedVnfSearchTotalCountVisualization /></Provider>); + }) + + it('Render the connected component', () => { + expect(wrapper.find(ConnectedVnfSearchTotalCountVisualization).length).toEqual(1); + }); + + it('Validate props from store', () => { + expect(wrapper.find(VnfSearchTotalCountVisualization).props().enableBusyFeedback).toEqual(initialState.vnfSearch.enableBusyFeedback); + expect(wrapper.find(VnfSearchTotalCountVisualization).props().count).toEqual(initialState.vnfSearch.count); + }); +}) + +describe('VnfSearchTotalCountVisualization - Render React Component (wrapped in <Provider>) with default props', () => { + const initialState = { + vnfSearch: {} + }; + const mockStore = configureStore(); + let store, wrapper; + + beforeEach( () => { + store = mockStore(initialState); + wrapper = mount(<Provider store={store}><ConnectedVnfSearchTotalCountVisualization /></Provider>); + }) + + it('Render the connected component', () => { + expect(wrapper.find(ConnectedVnfSearchTotalCountVisualization).length).toEqual(1); + }); + + it('Validate default props loaded', () => { + expect(wrapper.find(VnfSearchTotalCountVisualization).props().enableBusyFeedback).toEqual(false); + expect(wrapper.find(VnfSearchTotalCountVisualization).props().count).toEqual(TOTAL_VNF_COUNT.emptyValue); + }); +}) diff --git a/src/utils/DateTimeChartUtil.test.js b/src/utils/DateTimeChartUtil.test.js new file mode 100644 index 0000000..b1e9d69 --- /dev/null +++ b/src/utils/DateTimeChartUtil.test.js @@ -0,0 +1,92 @@ +import { + sortDataByField, + dateFormatLocalTimeZoneMMDDYYYY, + dateFormatLocalTimeZoneYYYYMMDD, + getTicks, + getTicksData +} from './DateTimeChartUtil.js'; + +describe('DateTimeChartUtil Tests', () => { + it('sortDataByField', () => { + let initialData = [ + {word: 'plum', number: 2}, + {word: 'apple', number: 3}, + {word: 'banana', number: 1} + ]; + + sortDataByField(initialData, 'number'); + expect(initialData[0]['number']).toBe(1); + expect(initialData[0]['word']).toBe('banana'); + expect(initialData[1]['number']).toBe(2); + expect(initialData[1]['word']).toBe('plum'); + expect(initialData[2]['number']).toBe(3); + expect(initialData[2]['word']).toBe('apple'); + }); + + it('dateFormatLocalTimeZoneMMDDYYYY', () => { + const timestamp = Date.parse('Mon, 25 Dec 1995 13:30:00 GMT'); + let formattedDate = dateFormatLocalTimeZoneMMDDYYYY(timestamp); + expect(formattedDate).toBe('12/25/1995'); + }); + + it('dateFormatLocalTimeZoneYYYYMMDD', () => { + const timestamp = Date.parse('Mon, 25 Dec 1995 13:30:00 GMT'); + let formattedDate = dateFormatLocalTimeZoneYYYYMMDD(timestamp); + expect(formattedDate).toBe('1995-12-25'); + }); + + it('getTicks', () => { + const timestamps = [ + {timestamp: 1521691200000, date: 'Thu, 22 Mar 2018 04:00:00 GMT'}, + {timestamp: 1521777600000, date: 'Thu, 23 Mar 2018 04:00:00 GMT'}, + {timestamp: 1521950400000, date: 'Thu, 25 Mar 2018 04:00:00 GMT'}, + {timestamp: 1522296000000, date: 'Thu, 29 Mar 2018 04:00:00 GMT'} + ]; + let ticksPerDay = getTicks(timestamps, 'timestamp'); + // expect 1 tick (timestamp) for each day between March 22 - March 29 + expect(ticksPerDay.length).toBe(8); + }); + + it('getTicks - empty data', () => { + const timestamps = []; + let ticksPerDay = getTicks(timestamps, 'timestamp'); + expect(ticksPerDay.length).toBe(0); + }); + + it('getTicksData', () => { + const timestamps = [ + {timestamp: 1521691200000, date: 'Thu, 22 Mar 2018 04:00:00 GMT'}, + {timestamp: 1521777600000, date: 'Thu, 23 Mar 2018 04:00:00 GMT'}, + {timestamp: 1521950400000, date: 'Thu, 25 Mar 2018 04:00:00 GMT'}, + {timestamp: 1522296000000, date: 'Thu, 29 Mar 2018 04:00:00 GMT'} + ]; + let ticksPerDay = getTicks(timestamps, 'timestamp'); + let mergedData = getTicksData(timestamps, ticksPerDay, 'timestamp'); + // expect original 4 objects plus 4 additional objects for the missing days + // (4 additional objects will only have timestamp attribute, no date attribute) + expect(mergedData.length).toBe(8); + expect(mergedData[0]['timestamp']).toBe(1521691200000); + expect(mergedData[0]['date']).toBe('Thu, 22 Mar 2018 04:00:00 GMT'); + expect(mergedData[1]['timestamp']).toBe(1521777600000); + expect(mergedData[1]['date']).toBe('Thu, 23 Mar 2018 04:00:00 GMT'); + expect(mergedData[2]['timestamp']).toBe(1521950400000); + expect(mergedData[2]['date']).toBe('Thu, 25 Mar 2018 04:00:00 GMT'); + expect(mergedData[3]['timestamp']).toBe(1522296000000); + expect(mergedData[3]['date']).toBe('Thu, 29 Mar 2018 04:00:00 GMT'); + expect(mergedData[4]['timestamp']).toBeTruthy(); + expect(mergedData[4]['date']).toBeUndefined(); + expect(mergedData[5]['timestamp']).toBeTruthy(); + expect(mergedData[5]['date']).toBeUndefined(); + expect(mergedData[6]['timestamp']).toBeTruthy(); + expect(mergedData[6]['date']).toBeUndefined(); + expect(mergedData[7]['timestamp']).toBeTruthy(); + expect(mergedData[7]['date']).toBeUndefined(); + }); + + it('getTicksData - empty data', () => { + const timestamps = []; + let ticksPerDay = getTicks(timestamps, 'timestamp'); + let mergedData = getTicksData(timestamps, ticksPerDay, 'timestamp'); + expect(mergedData.length).toBe(0); + }); +}) diff --git a/src/utils/SpinnerContainer.jsx b/src/utils/SpinnerContainer.jsx index d787554..1c8b1cd 100644 --- a/src/utils/SpinnerContainer.jsx +++ b/src/utils/SpinnerContainer.jsx @@ -47,4 +47,3 @@ SpinnerContainer.propTypes = { SpinnerContainer.defaultProps = { loading: false }; - diff --git a/src/utils/SpinnerContainer.test.js b/src/utils/SpinnerContainer.test.js new file mode 100644 index 0000000..a217b8a --- /dev/null +++ b/src/utils/SpinnerContainer.test.js @@ -0,0 +1,35 @@ +import React from 'react'; +import { ClipLoader } from 'react-spinners'; +import { mount } from 'enzyme'; + +import SpinnerContainer from './SpinnerContainer.jsx'; +import {COLOR_BLUE} from 'utils/GlobalConstants.js'; + +describe('SpinnerContainer', () => { + it('render spinner - visible', () => { + const spinner = mount( + <SpinnerContainer loading={true}> + <div class='test-div'>Testing Spinner Child</div> + <div class='test-div'>Testing Spinner Child</div> + </SpinnerContainer> + ); + expect(spinner.props().loading).toEqual(true); // check that the props match + expect(spinner.find(ClipLoader)).toHaveLength(1); // ensure the ClipLoader is mounted + expect(spinner.find(ClipLoader).props().color).toEqual(COLOR_BLUE); // ensure spinner is blue + expect(spinner.find(ClipLoader).props().loading).toEqual(true); // ensure spinner is showing + expect(spinner.find('div.spinner-content')).toHaveLength(1); // ensure the children are grayed out + expect(spinner.find('div.spinner-content').children()).toHaveLength(2); // ensure number of children is accurate + }); + + it('render spinner - not visible', () => { + const spinner = mount( + <SpinnerContainer loading={false}> + <div class='test-div'>Testing Spinner</div> + </SpinnerContainer> + ); + expect(spinner.props().loading).toEqual(false); + expect(spinner.find(ClipLoader)).toHaveLength(1); + expect(spinner.find(ClipLoader).props().loading).toEqual(false); // ensure spinner is not showing + expect(spinner.find('div.spinner-content')).toHaveLength(0); + }); +}) |