Skip to content

Instantly share code, notes, and snippets.

@gbengaoyetade
Created December 15, 2017 18:02
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save gbengaoyetade/7d6e25648f042fff713b4a4847a8f2b4 to your computer and use it in GitHub Desktop.
Save gbengaoyetade/7d6e25648f042fff713b4a4847a8f2b4 to your computer and use it in GitHub Desktop.
import React from 'react';
import { connect } from 'react-redux';
import PropTypes from 'prop-types';
import { Link } from 'react-router-dom';
import ReactPaginate from 'react-paginate';
import AppNav from '../common/AppNav';
import { searchUser } from '../../actions/searchActions';
import { addMember, getGroupMembers, addMemberSuccess }
from '../../actions/groupActions';
/**
*
*
* @class AddMembers
* @extends {React.Component}
*/
export class AddMembers extends React.Component {
/**
* Creates an instance of AddMembers.
* @param {object} props - react props
* @returns {void}
*/
constructor(props) {
super(props);
this.handleSearch = this.handleSearch.bind(this);
this.addMember = this.addMember.bind(this);
this.handlePageClick = this.handlePageClick.bind(this);
this.state = { userInput: '', limit: 3 };
}
/**
*
* @returns {void}
* @memberof AddMembers
*/
componentWillMount() {
this.props.getGroupMembers(this.props.match.params.groupId);
}
/**
*
*
* @param {object} event -javascript event
* @returns {void}
* @memberof AddMembers
*/
handleSearch(event) {
this.setState({ userInput: event.target.value });
if (this.state.userInput.length > 0) {
this.props.searchUsers(this.state.userInput, 0, this.state.limit);
}
}
/**
*
*
* @param {object} page -the current selected page
* @returns {void}
* @memberof AddMembers
*
*/
handlePageClick(page) {
const offset = page.selected * 3;
this.props.searchUsers(this.state.userInput, offset, this.state.limit);
}
/**
*
*
* @param {number} userId -user Id
* @returns {void}
* @memberof AddMembers
*/
addMember(userId) {
const groupId = this.props.match.params.groupId;
this.props.addMember(userId, groupId);
}
/**
*
*
* @returns {object} -React element
* @memberof AddMembers
*/
render() {
let searchResult;
// if member was added successfull, fetch group members again
if (this.props.addMemberSuccess) {
this.props.getGroupMembers(this.props.match.params.groupId);
Materialize.toast('User added successfully', 2000);
this.props.setAddMembersSucces(false);
}
if (this.props.searchResult.searchResult) {
const searchResultArray = this.props.searchResult.searchResult.users;
const groupMemberIds = this.props.groupMembers.users.map(member =>
member.id
);
// show search result only when input length is greater than 1 and
// there is some search result to show
if (searchResultArray.length > 0 && this.state.userInput.length > 0) {
const pageCount = this.props.searchResult.searchResult.pageCount;
searchResult = (
<div>
<ul className="collection" >
{searchResultArray.map(user => (
<li className="collection-item" key={user.id}>
{groupMemberIds.includes(user.id) ?
<span className="right"> Group member </span>
:
<Link
to='#'
className="right small btn light-blue darken-4"
onClick={() => { this.addMember(user.id); }}
> Add
</Link>
}
{user.fullName}
<div className="clearfix" />
</li>
))
}
</ul>
{pageCount > 1 ?
<div className="center">
<ReactPaginate
previousLabel={'previous'}
nextLabel={'next'}
breakLabel={<a href=''>...</a>}
breakClassName={'break-me'}
marginPagesDisplayed={2}
pageRangeDisplayed={5}
pageCount= {pageCount}
containerClassName={'pagination'}
subContainerClassName={'pages pagination'}
activeClassName={'active'}
onPageChange={this.handlePageClick}
className="center col"
/> </div> : null}
</div>
);
} else {
searchResult = '';
}
}
return (
<div className="row">
<AppNav />
<div className="col m6 component-container" >
<h5 className="center">Search users</h5>
<form>
<div className="input-field">
<input
id="search" type="search" autoComplete="off"
name="userSearch" onChange={this.handleSearch}
/>
<label htmlFor="search"> Search users </label>
</div>
</form>
<p className="big center"> Search result appears here</p>
{searchResult}
</div>
</div>
);
}
}
AddMembers.propTypes = {
searchUsers: PropTypes.func.isRequired,
addMember: PropTypes.func.isRequired,
getGroupMembers: PropTypes.func.isRequired,
setAddMembersSucces: PropTypes.func.isRequired,
addMemberSuccess: PropTypes.bool.isRequired,
match: PropTypes.object.isRequired,
searchResult: PropTypes.object,
groupMembers: PropTypes.object,
};
const mapStateToProps = state => (
{
searchResult: state.searchReducer,
addMemberSuccess: state.groupReducer.memberAdded,
groupMembers: state.groupReducer.members,
}
);
const mapDispatchToProps = dispatch => (
{
searchUsers: (userInput, groupId) => {
dispatch(searchUser(userInput, groupId));
},
addMember: (userId, groupId) => {
dispatch(addMember(userId, groupId));
},
getGroupMembers: (groupId) => {
dispatch(getGroupMembers(groupId));
},
setAddMembersSucces: (bool) => {
dispatch(addMemberSuccess(bool));
},
}
);
export default connect(mapStateToProps, mapDispatchToProps)(AddMembers);
import React from 'react';
import 'mock-local-storage';
import configureStore from 'redux-mock-store';
import thunk from 'redux-thunk';
import { BrowserRouter } from 'react-router-dom';
import { AddMembers } from '../../components/group/AddMembers';
import AppNav from '../../components/common/AppNav';
import { searchUser } from '../../actions/searchActions';
jest.mock('../../components/group/UserGroups');
const middlewares = [thunk];
const mockStore = configureStore(middlewares);
describe('AddMembers component', () => {
const store = mockStore({ groupReducer: {}, searchReducer: {} });
const props = {
searchUsers: searchUser,
addMember: () => {},
getGroupMembers: () => {},
setAddMembersSucces: () => {},
addMemberSuccess: true,
match: { params: {} },
searchResult: { }
};
const wrapper = mount(
<BrowserRouter>
<AddMembers {...props} store={store} />
</BrowserRouter>);
it('should render one AppNav component', () => {
expect(wrapper.find(AppNav).length).toBe(1);
});
it('should have a function that receives user input', () => {
const event = {
target: { value: 'jack' },
};
wrapper.instance().handleSearch(event);
expect(wrapper.state().userInput)
.toEqual(event.target.value);
});
it('should have a addmember method', () => {
console.log(wrapper.instance());
const addMemberSpy = jest
.spyOn(wrapper.instance(), 'addMember');
wrapper.instance().addMember(1);
expect(addMemberSpy).toBeDefined();
});
it('should send a message when user is added', () => {
const updatedProps = {
searchUsers: searchUser,
addMember: () => {},
getGroupMembers: () => {},
setAddMembersSucces: () => {},
addMemberSuccess: true,
match: { params: {} },
searchResult: {}
};
const updatedWrapper = shallow(
<AddMembers store={store} {...updatedProps}/>
);
expect(updatedWrapper).toBeDefined();
});
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment