/* * Copyright 2017 Amazon.com, Inc. or its affiliates. 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. * A copy of the License is located at * * http://aws.amazon.com/apache2.0/ * * or in the "license" file accompanying this file. This file is distributed * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either * express or implied. See the License for the specific language governing * permissions and limitations under the License. */ import * as React from 'react'; import {expect} from 'chai'; import * as sinon from 'sinon'; import {mountWithRoute, shallowWithStore} from '../globals'; import ConnectedParticipantTable, {ParticipantTable} from '../../src/components/participant_table/participant_table'; import '../globals'; import {shimData} from '../shim_data'; import {Button} from 'react-bootstrap'; import * as H from 'history'; describe('ParticipantTable', function() { const testWheelId = 'wheel_id_0'; // Props containing route data for mountWithRoute const props = { location: H.createLocation('/'), match: { params: {wheel_id: testWheelId}, isExact: true, path: `/app/wheel/${testWheelId}`, url: 'localhost/' }, history: H.createHashHistory(), }; // Props for shallow mounting (normally set by react-redux-fetch) const shallowProps = { wheelFetch: { fulfilled: true, rejected: false, pending: false, value: shimData.wheels[0], }, listParticipantsFetch: { fulfilled: true, rejected: false, pending: false, value: shimData.participants.filter((e) => e.wheel_id === shimData.wheels[0].id), }, match: { params: {wheel_id: testWheelId}, }, }; // sinon.sandbox lets us group these spies together and reset them after every test const sandbox = sinon.createSandbox(); const dispatchProps = { dispatchWheelGet: sandbox.spy(), dispatchListParticipantsGet: sandbox.spy(), dispatchCreateParticipantPost: sandbox.spy(), dispatchUpdateParticipantPut: sandbox.spy(), dispatchDeleteParticipantDelete: sandbox.spy(), dispatchRigParticipantPost: sandbox.spy(), dispatchUnrigParticipantPost: sandbox.spy(), dispatchResetWheelPost: sandbox.spy(), }; afterEach(() =>{ sandbox.reset(); }); it('Should render before and after loading completely', (done) => { const wrapper = mountWithRoute(); // The wheel table should be be loading when initially mounted expect(wrapper.html()).to.contain('Loading...'); // After 50ms we should have retrieved wheels data from the nocks setTimeout(() => { expect(wrapper.html()).to.contain('participant_name_0'); expect(wrapper.html()).to.contain('participant_name_3'); done(); }, 50); }); it('Should set participantModalOpen to true when Add New Participant button is clicked', () => { const wrapper = shallowWithStore(); // Force pending state so wheel state is updated wrapper.instance().setState({fetchPending: true}); wrapper.instance().componentDidUpdate(); wrapper.update(); wrapper.find(Button).at(2).simulate('click'); expect(wrapper.instance().state.participantModalOpen).to.be.true; }); it('Should set resetModalOpen to true when Reset button is clicked', () => { const wrapper = shallowWithStore(); // Force pending state so wheel state is updated wrapper.instance().setState({fetchPending: true}); wrapper.instance().componentDidUpdate(); wrapper.update(); wrapper.find(Button).at(3).simulate('click'); expect(wrapper.instance().state.resetModalOpen).to.be.true; }); it('Should dispatch a post upon handleCreateParticipant, then update state properly on componentDidUpdate', () => { const postProps = { createParticipantFetch: { fulfilled: false, pending: false, rejected: false, } }; const testParticipant = { id: 'test_id', }; const wrapper = shallowWithStore( ); wrapper.instance().handleCreateParticipant(testParticipant); expect(dispatchProps.dispatchCreateParticipantPost.calledWith(testWheelId, testParticipant)).to.be.true; expect(wrapper.instance().state.createPending).to.be.true; wrapper.setProps({createParticipantFetch: {fulfilled: true}}) wrapper.instance().componentDidUpdate(); expect(wrapper.instance().state.createPending).to.be.false; expect(wrapper.instance().state.fetchPending).to.be.false; }); it('Should dispatch a put upon handleUpdateParticipant, then update state properly on componentDidUpdate', () => { const postProps = { updateParticipantFetch: { fulfilled: false, pending: false, rejected: false, } }; const testParticipant = { id: 'test_id', }; const wrapper = shallowWithStore( ); wrapper.instance().handleUpdateParticipant(testParticipant); expect(dispatchProps.dispatchUpdateParticipantPut.calledWith(testWheelId, testParticipant)).to.be.true; expect(wrapper.instance().state.updatePending).to.be.true; wrapper.setProps({updateParticipantFetch: {fulfilled: true}}) wrapper.instance().componentDidUpdate(); expect(wrapper.instance().state.updatePending).to.be.false; expect(wrapper.instance().state.fetchPending).to.be.false; }); it('Should dispatch a delete upon handleDeleteParticipant, then update state properly on componentDidUpdate', () => { const postProps = { deleteParticipantFetch: { fulfilled: false, pending: false, rejected: false, } }; const testParticipant = { id: 'test_id', }; const wrapper = shallowWithStore( ); wrapper.instance().handleDeleteParticipant(testParticipant); expect(dispatchProps.dispatchDeleteParticipantDelete.calledWith(testWheelId, testParticipant.id)).to.be.true; expect(wrapper.instance().state.deletePending).to.be.true; wrapper.setProps({deleteParticipantFetch: {fulfilled: true}}) wrapper.instance().componentDidUpdate(); expect(wrapper.instance().state.deletePending).to.be.false; expect(wrapper.instance().state.fetchPending).to.be.false; }); it('Should dispatch a reset post on handleResetWheel, then update state properly on componentDidUpdate', () => { const postProps = { resetWheelFetch: { fulfilled: false, pending: false, rejected: false, } }; const wrapper = shallowWithStore( ); wrapper.instance().handleResetWheel(); expect(dispatchProps.dispatchResetWheelPost.calledWith(testWheelId)).to.be.true; expect(wrapper.instance().state.resetPending).to.be.true; wrapper.setProps({resetWheelFetch: {fulfilled: true}}) wrapper.instance().componentDidUpdate(); expect(wrapper.instance().state.resetPending).to.be.false; expect(wrapper.instance().state.fetchPending).to.be.false; }); it('Should dispatch a rig post on handleRigParticipant, then update state properly on componentDidUpdate', () => { const testId = shallowProps.listParticipantsFetch.value[0].id; const testHidden = false; const postProps = { wheelFetch: { fulfilled: true, rejected: false, pending: false, value: Object.assign({}, shimData.wheels[0], {rigging: {participant_id: testId, hidden: testHidden}}), }, resetWheelFetch: { fulfilled: true, pending: false, rejected: false, } }; const testParticipant = { id: testId, }; const wrapper = shallowWithStore( ); wrapper.instance().handleRigParticipant(testParticipant); expect(dispatchProps.dispatchRigParticipantPost .calledWith(testWheelId, testParticipant.id, testHidden)).to.be.true; // We reset the wheel here to set fetchPending which causes rigId and hidden states to be set wrapper.instance().handleResetWheel(); wrapper.instance().componentDidUpdate(); expect(wrapper.instance().state.rigging.participant_id).to.equal(testId); // Re-rigging the same participant should result in no change wrapper.instance().handleRigParticipant(testParticipant); expect(dispatchProps.dispatchRigParticipantPost.calledOnce).to.be.true; expect(wrapper.instance().state.rigging.participant_id).to.equal(testId); }); it('Should dispatch a rig post upon handleHiddenParticipant, then update state properly on componentDidUpdate', () => { const testId = shallowProps.listParticipantsFetch.value[0].id; const testHidden = false; const postProps = { wheelFetch: { fulfilled: true, rejected: false, pending: false, value: Object.assign({}, shimData.wheels[0], {rigging: {participant_id: testId, hidden: testHidden}}), }, resetWheelFetch: { fulfilled: true, pending: false, rejected: false, } }; const testParticipant = { id: testId, }; const wrapper = shallowWithStore( ); // We reset the wheel here to set fetchPending which causes rigId and hidden states to be set wrapper.instance().handleResetWheel(); wrapper.instance().componentDidUpdate(); wrapper.instance().handleHiddenRigParticipant(testParticipant); expect(dispatchProps.dispatchRigParticipantPost .calledWith(testWheelId, testParticipant.id, !testHidden)).to.be.true; expect(wrapper.instance().state.rigging.hidden).to.equal(!testHidden); }); it('Should dispatch an unrig post upon unrigWheel and update rig and hidden states', () => { const testId = shallowProps.listParticipantsFetch.value[0].id; const testHidden = false; const postProps = { wheelFetch: { fulfilled: true, rejected: false, pending: false, value: Object.assign({}, shimData.wheels[0], {rigging: {participant_id: testId, hidden: testHidden}}), }, resetWheelFetch: { fulfilled: true, pending: false, rejected: false, } }; const testParticipant = { id: testId, }; const wrapper = shallowWithStore( ); // We reset the wheel here to set fetchPending which causes rigId and hidden states to be set wrapper.instance().handleResetWheel(); wrapper.instance().componentDidUpdate(); expect(wrapper.instance().state.rigging.participant_id).to.equal(testId); wrapper.instance().unrigWheel(); expect(dispatchProps.dispatchUnrigParticipantPost .calledWith(testWheelId)).to.be.true; expect('participant_id' in wrapper.instance().state.rigging).to.be.false; expect('hidden' in wrapper.instance().state.rigging).to.be.false; }); it('Should render an error message if the wheel could not be fetched', () => { const testProps = { wheelFetch: { fulfilled: false, rejected: true, pending: false, }, }; const wrapper = shallowWithStore( ); expect(wrapper.html()).to.contain('Wheel information could not be loaded'); }); it('Should render an error message if participants could not be fetched and the wheel is rigged', () => { const testProps = { listParticipantsFetch: { fulfilled: false, rejected: true, pending: false, }, }; const wrapper = shallowWithStore( ); wrapper.instance().setState({wheel: {}}); wrapper.instance().setState({rigging: {participant_id: 'test_id', hidden: false}}); wrapper.update(); expect(wrapper.html()).to.contain('Participant information could not be loaded.'); }); it('Should render loading if participants are still fetching and wheel is rigged', () => { const testProps = { listParticipantsFetch: { fulfilled: false, rejected: false, pending: true, }, }; const wrapper = shallowWithStore( ); wrapper.instance().setState({wheel: {}}); wrapper.instance().setState({rigging: {participant_id: 'test_id', hidden: false}}); wrapper.update(); expect(wrapper.html()).to.contain('Loading participant information...'); }); });