Skip to content

Commit c01601a

Browse files
authored
Merge of #4176
2 parents d8ec9c7 + 91719c1 commit c01601a

File tree

2 files changed

+136
-36
lines changed

2 files changed

+136
-36
lines changed

src/elements/content-sidebar/AddTaskButton.js

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,15 @@ import { TASK_TYPE_APPROVAL } from '../../constants';
88
import type { TaskFormProps } from './activity-feed/task-form/TaskForm';
99
import type { TaskType } from '../../common/types/tasks';
1010
import type { ElementsXhrError } from '../../common/types/api';
11+
import type { InternalSidebarNavigation, InternalSidebarNavigationHandler } from '../common/types/SidebarNavigation';
1112

1213
type Props = {|
1314
history: RouterHistory,
15+
internalSidebarNavigation?: InternalSidebarNavigation,
16+
internalSidebarNavigationHandler?: InternalSidebarNavigationHandler,
1417
isDisabled: boolean,
1518
onTaskModalClose: () => void,
19+
routerDisabled?: boolean,
1620
taskFormProps: TaskFormProps,
1721
|};
1822

@@ -40,7 +44,20 @@ class AddTaskButton extends React.Component<Props, State> {
4044
2. Preventing the sidebar from closing keeps the task modal open upon edit and resize
4145
*/
4246
handleClickMenuItem = (taskType: TaskType) => {
43-
this.props.history.replace({ state: { open: true } });
47+
const { history, internalSidebarNavigation, internalSidebarNavigationHandler, routerDisabled } = this.props;
48+
49+
if (routerDisabled && internalSidebarNavigationHandler) {
50+
internalSidebarNavigationHandler(
51+
{
52+
...internalSidebarNavigation,
53+
open: true,
54+
},
55+
true,
56+
);
57+
} else {
58+
history.replace({ state: { open: true } });
59+
}
60+
4461
this.setState({ isTaskFormOpen: true, taskType });
4562
};
4663

Lines changed: 118 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,56 +1,139 @@
11
import * as React from 'react';
2-
import { mount } from 'enzyme';
2+
import { render, screen, userEvent } from '../../../test-utils/testing-library';
33
import { AddTaskButtonComponent as AddTaskButton } from '../AddTaskButton';
44

5-
jest.mock('../../../components/date-picker/DatePicker', () => props => {
6-
// only spread `input` attritutes to the input field
7-
const { name, value = '', className, onChange, placeholder } = props;
8-
const localInputProps = {
9-
name,
10-
value,
11-
className,
12-
onChange,
13-
placeholder,
14-
};
15-
return (
16-
<input type="date" {...localInputProps} {...props.inputProps} /> // eslint-disable-line react/prop-types
17-
);
18-
});
5+
jest.mock('../AddTaskMenu', () => ({ onMenuItemClick, isDisabled, setAddTaskButtonRef }) => (
6+
<div data-testid="add-task-menu">
7+
<button
8+
type="button"
9+
onClick={() => onMenuItemClick('GENERAL')}
10+
disabled={isDisabled}
11+
ref={setAddTaskButtonRef}
12+
data-testid="menu-item-general"
13+
>
14+
Add General Task
15+
</button>
16+
</div>
17+
));
18+
19+
jest.mock('../TaskModal', () => ({ isTaskFormOpen, onModalClose, taskType }) => (
20+
<div data-testid="task-modal" data-open={isTaskFormOpen} data-task-type={taskType}>
21+
<button type="button" onClick={onModalClose} data-testid="modal-close">
22+
Close Modal
23+
</button>
24+
</div>
25+
));
1926

2027
describe('elements/content-sidebar/AddTaskButton', () => {
2128
/*
2229
1. Pushing the open state into history keeps the sidebar open upon resize and refresh
2330
2. Preventing the sidebar from closing keeps the task modal open upon edit and resize
2431
*/
2532

26-
test('should call history.replace state with force open state when task menu items are clicked', () => {
33+
const defaultProps = {
34+
history: { replace: jest.fn() },
35+
isDisabled: false,
36+
onTaskModalClose: jest.fn(),
37+
taskFormProps: {
38+
approvers: [],
39+
approverSelectorContacts: [],
40+
completionRule: 'ALL',
41+
createTask: jest.fn(),
42+
getApproverWithQuery: jest.fn(),
43+
getAvatarUrl: jest.fn(),
44+
id: '',
45+
message: '',
46+
},
47+
};
48+
49+
const renderComponent = (props = {}) => {
50+
return render(<AddTaskButton {...defaultProps} {...props} />);
51+
};
52+
53+
beforeEach(() => {
54+
jest.clearAllMocks();
55+
});
56+
57+
test('should call history.replace state with force open state when task menu items are clicked', async () => {
2758
const historyMock = { replace: jest.fn() };
28-
const wrapper = mount(<AddTaskButton history={historyMock} />);
59+
const user = userEvent();
2960

30-
const button = wrapper.find('Button');
31-
button.simulate('click');
61+
renderComponent({ history: historyMock });
3262

33-
const menuItem = wrapper.find('MenuItem').first();
34-
menuItem.simulate('click');
63+
const menuItem = screen.getByTestId('menu-item-general');
64+
await user.click(menuItem);
3565

3666
expect(historyMock.replace).toHaveBeenCalledWith({ state: { open: true } });
3767
});
3868

39-
test('should set state.isTaskFormOpen to false and call onTaskModalClose when task modal is closed', () => {
69+
test('should set state.isTaskFormOpen to false and call onTaskModalClose when task modal is closed', async () => {
4070
const onTaskModalCloseMock = jest.fn();
41-
const mockButtonRef = {
42-
current: {
43-
focus: jest.fn(),
44-
},
45-
};
46-
const wrapper = shallow(<AddTaskButton onTaskModalClose={onTaskModalCloseMock} />);
47-
wrapper.instance().buttonRef = mockButtonRef;
48-
wrapper.setState({ isTaskFormOpen: true });
49-
50-
wrapper.instance().handleModalClose();
51-
52-
expect(wrapper.state('isTaskFormOpen')).toBe(false);
53-
expect(mockButtonRef.current.focus).toHaveBeenCalledTimes(1);
71+
const user = userEvent();
72+
73+
renderComponent({ onTaskModalClose: onTaskModalCloseMock });
74+
75+
// First click a menu item to open the modal
76+
const menuItem = screen.getByTestId('menu-item-general');
77+
await user.click(menuItem);
78+
79+
// Verify modal is open
80+
const modal = screen.getByTestId('task-modal');
81+
expect(modal).toHaveAttribute('data-open', 'true');
82+
83+
// Close the modal
84+
const closeButton = screen.getByTestId('modal-close');
85+
await user.click(closeButton);
86+
87+
// Verify modal is closed and callback was called
88+
expect(modal).toHaveAttribute('data-open', 'false');
5489
expect(onTaskModalCloseMock).toHaveBeenCalledTimes(1);
5590
});
91+
92+
describe('when routerDisabled is true', () => {
93+
test('should use internalSidebarNavigationHandler when task menu items are clicked', async () => {
94+
const mockNavigationHandler = jest.fn();
95+
const user = userEvent();
96+
97+
renderComponent({
98+
routerDisabled: true,
99+
internalSidebarNavigationHandler: mockNavigationHandler,
100+
});
101+
102+
const menuItem = screen.getByTestId('menu-item-general');
103+
await user.click(menuItem);
104+
105+
expect(mockNavigationHandler).toHaveBeenCalledTimes(1);
106+
expect(mockNavigationHandler).toHaveBeenCalledWith({ open: true }, true);
107+
});
108+
109+
test('should preserve internalSidebarNavigation state when using navigation handler', async () => {
110+
const mockNavigationHandler = jest.fn();
111+
const mockInternalSidebarNavigation = {
112+
sidebar: 'activity',
113+
activeFeedEntryType: 'comments',
114+
activeFeedEntryId: '123',
115+
};
116+
const user = userEvent();
117+
118+
renderComponent({
119+
routerDisabled: true,
120+
internalSidebarNavigationHandler: mockNavigationHandler,
121+
internalSidebarNavigation: mockInternalSidebarNavigation,
122+
});
123+
124+
const menuItem = screen.getByTestId('menu-item-general');
125+
await user.click(menuItem);
126+
127+
expect(mockNavigationHandler).toHaveBeenCalledTimes(1);
128+
expect(mockNavigationHandler).toHaveBeenCalledWith(
129+
{
130+
sidebar: 'activity',
131+
activeFeedEntryType: 'comments',
132+
activeFeedEntryId: '123',
133+
open: true,
134+
},
135+
true,
136+
);
137+
});
138+
});
56139
});

0 commit comments

Comments
 (0)