render() {
const { measure } = this.props;
+ const userName = measure.user.name || measure.user.login;
return (
<tr data-metric={measure.metric.key}>
<MeasureDate measure={measure} /> {translate('by_')}{' '}
<span className="js-custom-measure-user">
{isUserActive(measure.user)
- ? measure.user.name || measure.user.login
- : translateWithParameters('user.x_deleted', measure.user.login)}
+ ? userName
+ : translateWithParameters('user.x_deleted', userName)}
</span>
</td>
handleAssigneeSearch = (query: string) => {
return searchAssignees(query, this.state.organization).then(({ results }) =>
- results.map(r => ({
- avatar: r.avatar,
- label: isUserActive(r) ? r.name : translateWithParameters('user.x_deleted', r.login),
- value: r.login
- }))
+ results.map(r => {
+ const userInfo = r.name || r.login;
+
+ return {
+ avatar: r.avatar,
+ label: isUserActive(r) ? userInfo : translateWithParameters('user.x_deleted', userInfo),
+ value: r.login
+ };
+ })
);
};
return mock;
});
+jest.mock('../../utils', () => ({
+ searchAssignees: jest.fn().mockResolvedValue({
+ results: [
+ {
+ active: true,
+ avatar: '##toto',
+ login: 'toto@toto',
+ name: 'toto'
+ },
+ {
+ active: false,
+ avatar: '##toto',
+ login: 'login@login',
+ name: 'toto'
+ },
+ {
+ active: true,
+ avatar: '##toto',
+ login: 'login@login'
+ }
+ ]
+ })
+}));
+
it('should display error message when no issues available', async () => {
const wrapper = getWrapper([]);
await waitAndUpdate(wrapper);
expect(wrapper.find('Alert')).toMatchSnapshot();
});
+it('should properly handle the search for assignee', async () => {
+ const issues: T.Issue[] = [];
+ for (let i = MAX_PAGE_SIZE + 1; i > 0; i--) {
+ issues.push(mockIssue());
+ }
+
+ const wrapper = getWrapper(issues);
+ const result = await wrapper.instance().handleAssigneeSearch('toto');
+ expect(result).toMatchSnapshot();
+});
+
const getWrapper = (issues: T.Issue[]) => {
- return shallow(
+ return shallow<BulkChangeModal>(
<BulkChangeModal
component={undefined}
currentUser={{ isLoggedIn: true }}
/>
</Alert>
`;
+
+exports[`should properly handle the search for assignee 1`] = `
+Array [
+ Object {
+ "avatar": "##toto",
+ "label": "toto",
+ "value": "toto@toto",
+ },
+ Object {
+ "avatar": "##toto",
+ "label": "user.x_deleted.toto",
+ "value": "login@login",
+ },
+ Object {
+ "avatar": "##toto",
+ "label": "user.x_deleted.login@login",
+ "value": "login@login",
+ },
+]
+`;
const user = this.props.referencedUsers[assignee];
- return user ? (
+ if (!user) {
+ return assignee;
+ }
+
+ const userName = user.name || user.login;
+
+ return (
<>
- <Avatar
- className="little-spacer-right"
- hash={user.avatar}
- name={user.name || user.login}
- size={16}
- />
- {isUserActive(user) ? user.name : translateWithParameters('user.x_deleted', user.login)}
+ <Avatar className="little-spacer-right" hash={user.avatar} name={userName} size={16} />
+ {isUserActive(user) ? userName : translateWithParameters('user.x_deleted', userName)}
</>
- ) : (
- assignee
);
};
renderAssignee() {
const { issue } = this.props;
- const assignee =
- issue.assigneeActive !== false ? issue.assigneeName || issue.assignee : issue.assignee;
+ const assigneeName = issue.assigneeName || issue.assignee;
- if (assignee) {
+ if (assigneeName) {
return (
<>
<span className="text-top">
</span>
<span className="issue-meta-label">
{issue.assigneeActive === false
- ? translateWithParameters('user.x_deleted', assignee)
- : assignee}
+ ? translateWithParameters('user.x_deleted', assigneeName)
+ : assigneeName}
</span>
</>
);
expect(shallowRender()).toMatchSnapshot();
});
+it('should render a fallback assignee display if assignee info are not available', () => {
+ expect(shallowRender({ issue: { projectOrganization: 'org' } })).toMatchSnapshot();
+});
+
it('should open the popup when the button is clicked', () => {
const togglePopup = jest.fn();
const element = shallowRender({ togglePopup });
});
function shallowRender(props: Partial<IssueAssign['props']> = {}) {
- return shallow(
+ return shallow<IssueAssign>(
<IssueAssign
canAssign={true}
isOpen={false}
</div>
`;
+exports[`should render a fallback assignee display if assignee info are not available 1`] = `
+<div
+ className="dropdown"
+>
+ <Toggler
+ closeOnEscape={true}
+ onRequestClose={[Function]}
+ open={false}
+ overlay={
+ <Connect(withCurrentUser(SetAssigneePopup))
+ issue={
+ Object {
+ "projectOrganization": "org",
+ }
+ }
+ onSelect={[MockFunction]}
+ />
+ }
+ >
+ <ButtonLink
+ className="issue-action issue-action-with-options js-issue-assign"
+ onClick={[Function]}
+ >
+ <span
+ className="issue-meta-label"
+ >
+ unassigned
+ </span>
+ <DropdownIcon
+ className="little-spacer-left"
+ />
+ </ButtonLink>
+ </Toggler>
+</div>
+`;
+
exports[`should render with the action 1`] = `
<div
className="dropdown"
</td>
</tr>
- {this.state.changelog.map((item, idx) => (
- <tr key={idx}>
- <td className="thin text-left text-top nowrap">
- <DateTimeFormatter date={item.creationDate} />
- </td>
- <td className="text-left text-top">
- <p>
- <Avatar
- className="little-spacer-right"
- hash={item.avatar}
- name={(item.isUserActive && item.userName) || item.user}
- size={16}
- />
- {item.isUserActive
- ? item.userName || item.user
- : translateWithParameters('user.x_deleted', item.user)}
- </p>
- {item.diffs.map(diff => (
- <IssueChangelogDiff diff={diff} key={diff.key} />
- ))}
- </td>
- </tr>
- ))}
+ {this.state.changelog.map((item, idx) => {
+ const userName = item.userName || item.user;
+
+ return (
+ <tr key={idx}>
+ <td className="thin text-left text-top nowrap">
+ <DateTimeFormatter date={item.creationDate} />
+ </td>
+ <td className="text-left text-top">
+ {userName && (
+ <p>
+ <Avatar
+ className="little-spacer-right"
+ hash={item.avatar}
+ name={userName}
+ size={16}
+ />
+ {item.isUserActive
+ ? userName
+ : translateWithParameters('user.x_deleted', userName)}
+ </p>
+ )}
+ {item.diffs.map(diff => (
+ <IssueChangelogDiff diff={diff} key={diff.key} />
+ ))}
+ </td>
+ </tr>
+ );
+ })}
</tbody>
</table>
</div>