mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
flattened team state, tests for TeamMembers
This commit is contained in:
parent
59b3bfd342
commit
d494ebc730
79
public/app/features/teams/TeamMembers.test.tsx
Normal file
79
public/app/features/teams/TeamMembers.test.tsx
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { shallow } from 'enzyme';
|
||||||
|
import { TeamMembers, Props } from './TeamMembers';
|
||||||
|
import { TeamMember } from '../../types';
|
||||||
|
import { getMockTeamMember, getMockTeamMembers } from './__mocks__/teamMocks';
|
||||||
|
|
||||||
|
const setup = (propOverrides?: object) => {
|
||||||
|
const props: Props = {
|
||||||
|
members: [] as TeamMember[],
|
||||||
|
searchMemberQuery: '',
|
||||||
|
setSearchMemberQuery: jest.fn(),
|
||||||
|
loadTeamMembers: jest.fn(),
|
||||||
|
addTeamMember: jest.fn(),
|
||||||
|
removeTeamMember: jest.fn(),
|
||||||
|
};
|
||||||
|
|
||||||
|
Object.assign(props, propOverrides);
|
||||||
|
|
||||||
|
const wrapper = shallow(<TeamMembers {...props} />);
|
||||||
|
const instance = wrapper.instance() as TeamMembers;
|
||||||
|
|
||||||
|
return {
|
||||||
|
wrapper,
|
||||||
|
instance,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
describe('Render', () => {
|
||||||
|
it('should render component', () => {
|
||||||
|
const { wrapper } = setup();
|
||||||
|
|
||||||
|
expect(wrapper).toMatchSnapshot();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should render team members', () => {
|
||||||
|
const { wrapper } = setup({
|
||||||
|
members: getMockTeamMembers(5),
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(wrapper).toMatchSnapshot();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('Functions', () => {
|
||||||
|
describe('on search member query change', () => {
|
||||||
|
it('it should call setSearchMemberQuery', () => {
|
||||||
|
const { instance } = setup();
|
||||||
|
const mockEvent = { target: { value: 'member' } };
|
||||||
|
|
||||||
|
instance.onSearchQueryChange(mockEvent);
|
||||||
|
|
||||||
|
expect(instance.props.setSearchMemberQuery).toHaveBeenCalledWith('member');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('on remove member', () => {
|
||||||
|
const { instance } = setup();
|
||||||
|
const mockTeamMember = getMockTeamMember();
|
||||||
|
|
||||||
|
instance.onRemoveMember(mockTeamMember);
|
||||||
|
|
||||||
|
expect(instance.props.removeTeamMember).toHaveBeenCalledWith(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('on add user to team', () => {
|
||||||
|
const { wrapper, instance } = setup();
|
||||||
|
|
||||||
|
wrapper.state().newTeamMember = {
|
||||||
|
id: 1,
|
||||||
|
label: '',
|
||||||
|
avatarUrl: '',
|
||||||
|
login: '',
|
||||||
|
};
|
||||||
|
|
||||||
|
instance.onAddUserToTeam();
|
||||||
|
|
||||||
|
expect(instance.props.addTeamMember).toHaveBeenCalledWith(1);
|
||||||
|
});
|
||||||
|
});
|
@ -1,16 +1,14 @@
|
|||||||
import React, { PureComponent } from 'react';
|
import React, { PureComponent } from 'react';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { hot } from 'react-hot-loader';
|
|
||||||
import SlideDown from 'app/core/components/Animations/SlideDown';
|
import SlideDown from 'app/core/components/Animations/SlideDown';
|
||||||
import { UserPicker, User } from 'app/core/components/Picker/UserPicker';
|
import { UserPicker, User } from 'app/core/components/Picker/UserPicker';
|
||||||
import DeleteButton from 'app/core/components/DeleteButton/DeleteButton';
|
import DeleteButton from 'app/core/components/DeleteButton/DeleteButton';
|
||||||
import { Team, TeamMember } from '../../types';
|
import { TeamMember } from '../../types';
|
||||||
import { loadTeamMembers, addTeamMember, removeTeamMember, setSearchMemberQuery } from './state/actions';
|
import { loadTeamMembers, addTeamMember, removeTeamMember, setSearchMemberQuery } from './state/actions';
|
||||||
import { getSearchMemberQuery, getTeam } from './state/selectors';
|
import { getSearchMemberQuery, getTeamMembers } from './state/selectors';
|
||||||
import { getRouteParamsId } from '../../core/selectors/location';
|
|
||||||
|
|
||||||
interface Props {
|
export interface Props {
|
||||||
team: Team;
|
members: TeamMember[];
|
||||||
searchMemberQuery: string;
|
searchMemberQuery: string;
|
||||||
loadTeamMembers: typeof loadTeamMembers;
|
loadTeamMembers: typeof loadTeamMembers;
|
||||||
addTeamMember: typeof addTeamMember;
|
addTeamMember: typeof addTeamMember;
|
||||||
@ -37,7 +35,7 @@ export class TeamMembers extends PureComponent<Props, State> {
|
|||||||
this.props.setSearchMemberQuery(event.target.value);
|
this.props.setSearchMemberQuery(event.target.value);
|
||||||
};
|
};
|
||||||
|
|
||||||
removeMember(member: TeamMember) {
|
onRemoveMember(member: TeamMember) {
|
||||||
this.props.removeTeamMember(member.userId);
|
this.props.removeTeamMember(member.userId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -63,7 +61,7 @@ export class TeamMembers extends PureComponent<Props, State> {
|
|||||||
<td>{member.login}</td>
|
<td>{member.login}</td>
|
||||||
<td>{member.email}</td>
|
<td>{member.email}</td>
|
||||||
<td className="text-right">
|
<td className="text-right">
|
||||||
<DeleteButton onConfirmDelete={() => this.removeMember(member)} />
|
<DeleteButton onConfirmDelete={() => this.onRemoveMember(member)} />
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
);
|
);
|
||||||
@ -71,7 +69,7 @@ export class TeamMembers extends PureComponent<Props, State> {
|
|||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { newTeamMember, isAdding } = this.state;
|
const { newTeamMember, isAdding } = this.state;
|
||||||
const { team, searchMemberQuery } = this.props;
|
const { searchMemberQuery, members } = this.props;
|
||||||
const newTeamMemberValue = newTeamMember && newTeamMember.id.toString();
|
const newTeamMemberValue = newTeamMember && newTeamMember.id.toString();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -125,7 +123,7 @@ export class TeamMembers extends PureComponent<Props, State> {
|
|||||||
<th style={{ width: '1%' }} />
|
<th style={{ width: '1%' }} />
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>{team.members && team.members.map(member => this.renderMember(member))}</tbody>
|
<tbody>{members && members.map(member => this.renderMember(member))}</tbody>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -134,10 +132,8 @@ export class TeamMembers extends PureComponent<Props, State> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function mapStateToProps(state) {
|
function mapStateToProps(state) {
|
||||||
const teamId = getRouteParamsId(state.location);
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
team: getTeam(state.team, teamId),
|
members: getTeamMembers(state.team),
|
||||||
searchMemberQuery: getSearchMemberQuery(state.team),
|
searchMemberQuery: getSearchMemberQuery(state.team),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -149,4 +145,4 @@ const mapDispatchToProps = {
|
|||||||
setSearchMemberQuery,
|
setSearchMemberQuery,
|
||||||
};
|
};
|
||||||
|
|
||||||
export default hot(module)(connect(mapStateToProps, mapDispatchToProps)(TeamMembers));
|
export default connect(mapStateToProps, mapDispatchToProps)(TeamMembers);
|
||||||
|
@ -41,10 +41,10 @@ export class TeamPages extends PureComponent<Props, State> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
this.loadTeam();
|
this.fetchTeam();
|
||||||
}
|
}
|
||||||
|
|
||||||
async loadTeam() {
|
async fetchTeam() {
|
||||||
const { loadTeam, teamId } = this.props;
|
const { loadTeam, teamId } = this.props;
|
||||||
|
|
||||||
await loadTeam(teamId);
|
await loadTeam(teamId);
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { Team } from '../../../types';
|
import { Team, TeamMember } from '../../../types';
|
||||||
|
|
||||||
export const getMultipleMockTeams = (numberOfTeams: number): Team[] => {
|
export const getMultipleMockTeams = (numberOfTeams: number): Team[] => {
|
||||||
let teams: Team[] = [];
|
let teams: Team[] = [];
|
||||||
@ -9,9 +9,6 @@ export const getMultipleMockTeams = (numberOfTeams: number): Team[] => {
|
|||||||
avatarUrl: 'some/url/',
|
avatarUrl: 'some/url/',
|
||||||
email: `test-${i}@test.com`,
|
email: `test-${i}@test.com`,
|
||||||
memberCount: i,
|
memberCount: i,
|
||||||
search: '',
|
|
||||||
members: [],
|
|
||||||
groups: [],
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -25,13 +22,26 @@ export const getMockTeam = (): Team => {
|
|||||||
avatarUrl: 'some/url/',
|
avatarUrl: 'some/url/',
|
||||||
email: 'test@test.com',
|
email: 'test@test.com',
|
||||||
memberCount: 1,
|
memberCount: 1,
|
||||||
search: '',
|
|
||||||
members: [],
|
|
||||||
groups: [],
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getMockTeamMember = () => {
|
export const getMockTeamMembers = (amount: number): TeamMember[] => {
|
||||||
|
let teamMembers: TeamMember[] = [];
|
||||||
|
|
||||||
|
for (let i = 1; i <= amount; i++) {
|
||||||
|
teamMembers.push({
|
||||||
|
userId: i,
|
||||||
|
teamId: 1,
|
||||||
|
avatarUrl: 'some/url/',
|
||||||
|
email: 'test@test.com',
|
||||||
|
login: `testUser-${i}`,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return teamMembers;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getMockTeamMember = (): TeamMember => {
|
||||||
return {
|
return {
|
||||||
userId: 1,
|
userId: 1,
|
||||||
teamId: 1,
|
teamId: 1,
|
||||||
|
@ -0,0 +1,317 @@
|
|||||||
|
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||||
|
|
||||||
|
exports[`Render should render component 1`] = `
|
||||||
|
<div>
|
||||||
|
<div
|
||||||
|
className="page-action-bar"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
className="gf-form gf-form--grow"
|
||||||
|
>
|
||||||
|
<label
|
||||||
|
className="gf-form--has-input-icon gf-form--grow"
|
||||||
|
>
|
||||||
|
<input
|
||||||
|
className="gf-form-input"
|
||||||
|
onChange={[Function]}
|
||||||
|
placeholder="Search members"
|
||||||
|
type="text"
|
||||||
|
value=""
|
||||||
|
/>
|
||||||
|
<i
|
||||||
|
className="gf-form-input-icon fa fa-search"
|
||||||
|
/>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
className="page-action-bar__spacer"
|
||||||
|
/>
|
||||||
|
<button
|
||||||
|
className="btn btn-success pull-right"
|
||||||
|
disabled={false}
|
||||||
|
onClick={[Function]}
|
||||||
|
>
|
||||||
|
<i
|
||||||
|
className="fa fa-plus"
|
||||||
|
/>
|
||||||
|
Add a member
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<Component
|
||||||
|
in={false}
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
className="cta-form"
|
||||||
|
>
|
||||||
|
<button
|
||||||
|
className="cta-form__close btn btn-transparent"
|
||||||
|
onClick={[Function]}
|
||||||
|
>
|
||||||
|
<i
|
||||||
|
className="fa fa-close"
|
||||||
|
/>
|
||||||
|
</button>
|
||||||
|
<h5>
|
||||||
|
Add Team Member
|
||||||
|
</h5>
|
||||||
|
<div
|
||||||
|
className="gf-form-inline"
|
||||||
|
>
|
||||||
|
<UserPicker
|
||||||
|
className="width-30"
|
||||||
|
onSelected={[Function]}
|
||||||
|
value={null}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Component>
|
||||||
|
<div
|
||||||
|
className="admin-list-table"
|
||||||
|
>
|
||||||
|
<table
|
||||||
|
className="filter-table filter-table--hover form-inline"
|
||||||
|
>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th />
|
||||||
|
<th>
|
||||||
|
Name
|
||||||
|
</th>
|
||||||
|
<th>
|
||||||
|
Email
|
||||||
|
</th>
|
||||||
|
<th
|
||||||
|
style={
|
||||||
|
Object {
|
||||||
|
"width": "1%",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody />
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`Render should render team members 1`] = `
|
||||||
|
<div>
|
||||||
|
<div
|
||||||
|
className="page-action-bar"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
className="gf-form gf-form--grow"
|
||||||
|
>
|
||||||
|
<label
|
||||||
|
className="gf-form--has-input-icon gf-form--grow"
|
||||||
|
>
|
||||||
|
<input
|
||||||
|
className="gf-form-input"
|
||||||
|
onChange={[Function]}
|
||||||
|
placeholder="Search members"
|
||||||
|
type="text"
|
||||||
|
value=""
|
||||||
|
/>
|
||||||
|
<i
|
||||||
|
className="gf-form-input-icon fa fa-search"
|
||||||
|
/>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
className="page-action-bar__spacer"
|
||||||
|
/>
|
||||||
|
<button
|
||||||
|
className="btn btn-success pull-right"
|
||||||
|
disabled={false}
|
||||||
|
onClick={[Function]}
|
||||||
|
>
|
||||||
|
<i
|
||||||
|
className="fa fa-plus"
|
||||||
|
/>
|
||||||
|
Add a member
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<Component
|
||||||
|
in={false}
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
className="cta-form"
|
||||||
|
>
|
||||||
|
<button
|
||||||
|
className="cta-form__close btn btn-transparent"
|
||||||
|
onClick={[Function]}
|
||||||
|
>
|
||||||
|
<i
|
||||||
|
className="fa fa-close"
|
||||||
|
/>
|
||||||
|
</button>
|
||||||
|
<h5>
|
||||||
|
Add Team Member
|
||||||
|
</h5>
|
||||||
|
<div
|
||||||
|
className="gf-form-inline"
|
||||||
|
>
|
||||||
|
<UserPicker
|
||||||
|
className="width-30"
|
||||||
|
onSelected={[Function]}
|
||||||
|
value={null}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Component>
|
||||||
|
<div
|
||||||
|
className="admin-list-table"
|
||||||
|
>
|
||||||
|
<table
|
||||||
|
className="filter-table filter-table--hover form-inline"
|
||||||
|
>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th />
|
||||||
|
<th>
|
||||||
|
Name
|
||||||
|
</th>
|
||||||
|
<th>
|
||||||
|
Email
|
||||||
|
</th>
|
||||||
|
<th
|
||||||
|
style={
|
||||||
|
Object {
|
||||||
|
"width": "1%",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr
|
||||||
|
key="1"
|
||||||
|
>
|
||||||
|
<td
|
||||||
|
className="width-4 text-center"
|
||||||
|
>
|
||||||
|
<img
|
||||||
|
className="filter-table__avatar"
|
||||||
|
src="some/url/"
|
||||||
|
/>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
testUser-1
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
test@test.com
|
||||||
|
</td>
|
||||||
|
<td
|
||||||
|
className="text-right"
|
||||||
|
>
|
||||||
|
<DeleteButton
|
||||||
|
onConfirmDelete={[Function]}
|
||||||
|
/>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr
|
||||||
|
key="2"
|
||||||
|
>
|
||||||
|
<td
|
||||||
|
className="width-4 text-center"
|
||||||
|
>
|
||||||
|
<img
|
||||||
|
className="filter-table__avatar"
|
||||||
|
src="some/url/"
|
||||||
|
/>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
testUser-2
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
test@test.com
|
||||||
|
</td>
|
||||||
|
<td
|
||||||
|
className="text-right"
|
||||||
|
>
|
||||||
|
<DeleteButton
|
||||||
|
onConfirmDelete={[Function]}
|
||||||
|
/>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr
|
||||||
|
key="3"
|
||||||
|
>
|
||||||
|
<td
|
||||||
|
className="width-4 text-center"
|
||||||
|
>
|
||||||
|
<img
|
||||||
|
className="filter-table__avatar"
|
||||||
|
src="some/url/"
|
||||||
|
/>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
testUser-3
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
test@test.com
|
||||||
|
</td>
|
||||||
|
<td
|
||||||
|
className="text-right"
|
||||||
|
>
|
||||||
|
<DeleteButton
|
||||||
|
onConfirmDelete={[Function]}
|
||||||
|
/>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr
|
||||||
|
key="4"
|
||||||
|
>
|
||||||
|
<td
|
||||||
|
className="width-4 text-center"
|
||||||
|
>
|
||||||
|
<img
|
||||||
|
className="filter-table__avatar"
|
||||||
|
src="some/url/"
|
||||||
|
/>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
testUser-4
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
test@test.com
|
||||||
|
</td>
|
||||||
|
<td
|
||||||
|
className="text-right"
|
||||||
|
>
|
||||||
|
<DeleteButton
|
||||||
|
onConfirmDelete={[Function]}
|
||||||
|
/>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr
|
||||||
|
key="5"
|
||||||
|
>
|
||||||
|
<td
|
||||||
|
className="width-4 text-center"
|
||||||
|
>
|
||||||
|
<img
|
||||||
|
className="filter-table__avatar"
|
||||||
|
src="some/url/"
|
||||||
|
/>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
testUser-5
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
test@test.com
|
||||||
|
</td>
|
||||||
|
<td
|
||||||
|
className="text-right"
|
||||||
|
>
|
||||||
|
<DeleteButton
|
||||||
|
onConfirmDelete={[Function]}
|
||||||
|
/>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`;
|
@ -21,12 +21,9 @@ exports[`Render should render group sync page 1`] = `
|
|||||||
Object {
|
Object {
|
||||||
"avatarUrl": "some/url/",
|
"avatarUrl": "some/url/",
|
||||||
"email": "test@test.com",
|
"email": "test@test.com",
|
||||||
"groups": Array [],
|
|
||||||
"id": 1,
|
"id": 1,
|
||||||
"memberCount": 1,
|
"memberCount": 1,
|
||||||
"members": Array [],
|
|
||||||
"name": "test",
|
"name": "test",
|
||||||
"search": "",
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
@ -42,20 +39,7 @@ exports[`Render should render member page if team not empty 1`] = `
|
|||||||
<div
|
<div
|
||||||
className="page-container page-body"
|
className="page-container page-body"
|
||||||
>
|
>
|
||||||
<TeamMembers
|
<Connect(TeamMembers) />
|
||||||
team={
|
|
||||||
Object {
|
|
||||||
"avatarUrl": "some/url/",
|
|
||||||
"email": "test@test.com",
|
|
||||||
"groups": Array [],
|
|
||||||
"id": 1,
|
|
||||||
"memberCount": 1,
|
|
||||||
"members": Array [],
|
|
||||||
"name": "test",
|
|
||||||
"search": "",
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
@ -73,12 +57,9 @@ exports[`Render should render settings page 1`] = `
|
|||||||
Object {
|
Object {
|
||||||
"avatarUrl": "some/url/",
|
"avatarUrl": "some/url/",
|
||||||
"email": "test@test.com",
|
"email": "test@test.com",
|
||||||
"groups": Array [],
|
|
||||||
"id": 1,
|
"id": 1,
|
||||||
"memberCount": 1,
|
"memberCount": 1,
|
||||||
"members": Array [],
|
|
||||||
"name": "test",
|
"name": "test",
|
||||||
"search": "",
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
|
@ -117,6 +117,7 @@ export function loadTeam(id: number): ThunkResult<void> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function loadTeamMembers(): ThunkResult<void> {
|
export function loadTeamMembers(): ThunkResult<void> {
|
||||||
|
console.log('loading team members');
|
||||||
return async (dispatch, getStore) => {
|
return async (dispatch, getStore) => {
|
||||||
const team = getStore().team.team;
|
const team = getStore().team.team;
|
||||||
|
|
||||||
|
@ -31,22 +31,42 @@ describe('teams reducer', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
describe('team reducer', () => {
|
describe('team reducer', () => {
|
||||||
|
it('should set team', () => {
|
||||||
|
const payload = getMockTeam();
|
||||||
|
|
||||||
|
const action: Action = {
|
||||||
|
type: ActionTypes.LoadTeam,
|
||||||
|
payload,
|
||||||
|
};
|
||||||
|
|
||||||
|
const result = teamReducer(initialTeamState, action);
|
||||||
|
|
||||||
|
expect(result.team).toEqual(payload);
|
||||||
|
});
|
||||||
|
|
||||||
it('should set team members', () => {
|
it('should set team members', () => {
|
||||||
const mockTeamMember = getMockTeamMember();
|
const mockTeamMember = getMockTeamMember();
|
||||||
const mockTeam = getMockTeam();
|
|
||||||
const state = {
|
|
||||||
...initialTeamState,
|
|
||||||
team: mockTeam,
|
|
||||||
};
|
|
||||||
|
|
||||||
const action: Action = {
|
const action: Action = {
|
||||||
type: ActionTypes.LoadTeamMembers,
|
type: ActionTypes.LoadTeamMembers,
|
||||||
payload: [mockTeamMember],
|
payload: [mockTeamMember],
|
||||||
};
|
};
|
||||||
|
|
||||||
const result = teamReducer(state, action);
|
const result = teamReducer(initialTeamState, action);
|
||||||
const expectedState = { team: { ...mockTeam, members: [mockTeamMember] }, searchQuery: '' };
|
|
||||||
|
|
||||||
expect(result).toEqual(expectedState);
|
expect(result.members).toEqual([mockTeamMember]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should set member search query', () => {
|
||||||
|
const payload = 'member';
|
||||||
|
|
||||||
|
const action: Action = {
|
||||||
|
type: ActionTypes.SetSearchMemberQuery,
|
||||||
|
payload,
|
||||||
|
};
|
||||||
|
|
||||||
|
const result = teamReducer(initialTeamState, action);
|
||||||
|
|
||||||
|
expect(result.searchMemberQuery).toEqual('member');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -1,8 +1,13 @@
|
|||||||
import { Team, TeamsState, TeamState } from '../../../types';
|
import { Team, TeamGroup, TeamMember, TeamsState, TeamState } from '../../../types';
|
||||||
import { Action, ActionTypes } from './actions';
|
import { Action, ActionTypes } from './actions';
|
||||||
|
|
||||||
export const initialTeamsState: TeamsState = { teams: [], searchQuery: '' };
|
export const initialTeamsState: TeamsState = { teams: [], searchQuery: '' };
|
||||||
export const initialTeamState: TeamState = { team: {} as Team, searchMemberQuery: '' };
|
export const initialTeamState: TeamState = {
|
||||||
|
team: {} as Team,
|
||||||
|
members: [] as TeamMember[],
|
||||||
|
groups: [] as TeamGroup[],
|
||||||
|
searchMemberQuery: '',
|
||||||
|
};
|
||||||
|
|
||||||
export const teamsReducer = (state = initialTeamsState, action: Action): TeamsState => {
|
export const teamsReducer = (state = initialTeamsState, action: Action): TeamsState => {
|
||||||
switch (action.type) {
|
switch (action.type) {
|
||||||
@ -21,7 +26,7 @@ export const teamReducer = (state = initialTeamState, action: Action): TeamState
|
|||||||
return { ...state, team: action.payload };
|
return { ...state, team: action.payload };
|
||||||
|
|
||||||
case ActionTypes.LoadTeamMembers:
|
case ActionTypes.LoadTeamMembers:
|
||||||
return { ...state, team: { ...state.team, members: action.payload } };
|
return { ...state, members: action.payload };
|
||||||
|
|
||||||
case ActionTypes.SetSearchMemberQuery:
|
case ActionTypes.SetSearchMemberQuery:
|
||||||
return { ...state, searchMemberQuery: action.payload };
|
return { ...state, searchMemberQuery: action.payload };
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
import { getTeams } from './selectors';
|
import { getTeam, getTeams } from './selectors';
|
||||||
import { getMultipleMockTeams } from '../__mocks__/teamMocks';
|
import { getMockTeam, getMultipleMockTeams } from '../__mocks__/teamMocks';
|
||||||
import { TeamsState } from '../../../types';
|
import { TeamsState, TeamState } from '../../../types';
|
||||||
|
|
||||||
describe('Team selectors', () => {
|
describe('Teams selectors', () => {
|
||||||
describe('Get teams', () => {
|
describe('Get teams', () => {
|
||||||
const mockTeams = getMultipleMockTeams(5);
|
const mockTeams = getMultipleMockTeams(5);
|
||||||
|
|
||||||
@ -23,3 +23,17 @@ describe('Team selectors', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('Team selectors', () => {
|
||||||
|
describe('Get team', () => {
|
||||||
|
const mockTeam = getMockTeam();
|
||||||
|
|
||||||
|
it('should return team if matching with location team', () => {
|
||||||
|
const mockState: TeamState = { team: mockTeam, searchMemberQuery: '' };
|
||||||
|
|
||||||
|
const team = getTeam(mockState, '1');
|
||||||
|
|
||||||
|
expect(team).toEqual(mockTeam);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
@ -2,8 +2,7 @@ export const getSearchQuery = state => state.searchQuery;
|
|||||||
export const getSearchMemberQuery = state => state.searchMemberQuery;
|
export const getSearchMemberQuery = state => state.searchMemberQuery;
|
||||||
|
|
||||||
export const getTeam = (state, currentTeamId) => {
|
export const getTeam = (state, currentTeamId) => {
|
||||||
if (state.team.id === currentTeamId) {
|
if (state.team.id === parseInt(currentTeamId)) {
|
||||||
console.log('yes');
|
|
||||||
return state.team;
|
return state.team;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -15,3 +14,11 @@ export const getTeams = state => {
|
|||||||
return regex.test(team.name);
|
return regex.test(team.name);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const getTeamMembers = state => {
|
||||||
|
const regex = RegExp(state.searchMemberQuery, 'i');
|
||||||
|
|
||||||
|
return state.members.filter(member => {
|
||||||
|
return regex.test(member.login) || regex.test(member.email);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
@ -63,9 +63,6 @@ export interface Team {
|
|||||||
avatarUrl: string;
|
avatarUrl: string;
|
||||||
email: string;
|
email: string;
|
||||||
memberCount: number;
|
memberCount: number;
|
||||||
search?: string;
|
|
||||||
members?: TeamMember[];
|
|
||||||
groups?: TeamGroup[];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface TeamMember {
|
export interface TeamMember {
|
||||||
@ -124,6 +121,8 @@ export interface TeamsState {
|
|||||||
|
|
||||||
export interface TeamState {
|
export interface TeamState {
|
||||||
team: Team;
|
team: Team;
|
||||||
|
members: TeamMember[];
|
||||||
|
groups: TeamGroup[];
|
||||||
searchMemberQuery: string;
|
searchMemberQuery: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user