@@ -53,6 +53,7 @@ import { NoticeType } from '../../types/users'; | |||
import { getComponentForSourceViewer, getSources } from '../components'; | |||
import { | |||
addIssueComment, | |||
bulkChangeIssues, | |||
deleteIssueComment, | |||
editIssueComment, | |||
getIssueFlowSnippets, | |||
@@ -252,6 +253,7 @@ export default class IssuesServiceMock { | |||
(getComponentForSourceViewer as jest.Mock).mockImplementation( | |||
this.handleGetComponentForSourceViewer | |||
); | |||
(bulkChangeIssues as jest.Mock).mockImplementation(this.handleBulkChangeIssues); | |||
(getCurrentUser as jest.Mock).mockImplementation(this.handleGetCurrentUser); | |||
(dismissNotice as jest.Mock).mockImplementation(this.handleDismissNotification); | |||
(setIssueType as jest.Mock).mockImplementation(this.handleSetIssueType); | |||
@@ -285,6 +287,16 @@ export default class IssuesServiceMock { | |||
this.isAdmin = isAdmin; | |||
} | |||
handleBulkChangeIssues = (issueKeys: string[], query: RequestData) => { | |||
//For now we only check for issue type change. | |||
this.list | |||
.filter(i => issueKeys.includes(i.issue.key)) | |||
.forEach(data => { | |||
data.issue.type = query.set_type; | |||
}); | |||
return this.reply({}); | |||
}; | |||
handleGetSources = (data: { key: string; from?: number; to?: number } & BranchParameters) => { | |||
return this.reply(range(data.from || 1, data.to || 10).map(line => mockSourceLine({ line }))); | |||
}; |
@@ -17,9 +17,10 @@ | |||
* along with this program; if not, write to the Free Software Foundation, | |||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |||
*/ | |||
import { screen } from '@testing-library/react'; | |||
import { screen, within } from '@testing-library/react'; | |||
import userEvent from '@testing-library/user-event'; | |||
import React from 'react'; | |||
import selectEvent from 'react-select-event'; | |||
import IssuesServiceMock from '../../../api/mocks/IssuesServiceMock'; | |||
import { renderOwaspTop102021Category } from '../../../helpers/security-standard'; | |||
import { mockCurrentUser } from '../../../helpers/testMocks'; | |||
@@ -42,6 +43,52 @@ beforeEach(() => { | |||
window.HTMLElement.prototype.scrollIntoView = jest.fn(); | |||
}); | |||
//Improve this to include all the bulk change fonctionality | |||
it('should be able to bulk change', async () => { | |||
const user = userEvent.setup(); | |||
handler.setIsAdmin(true); | |||
renderIssueApp(mockCurrentUser({ isLoggedIn: true })); | |||
// Check that the bulk button has correct behavior | |||
expect(await screen.findByRole('button', { name: 'bulk_change' })).toHaveAttribute('disabled'); | |||
await user.click(screen.getByRole('checkbox', { name: 'issues.select_all_issues' })); | |||
expect( | |||
screen.getByRole('button', { name: 'issues.bulk_change_X_issues.500' }) | |||
).toBeInTheDocument(); | |||
await user.click(screen.getByRole('button', { name: 'issues.bulk_change_X_issues.500' })); | |||
await user.click(screen.getByRole('button', { name: 'cancel' })); | |||
expect(screen.getByRole('button', { name: 'issues.bulk_change_X_issues.500' })).toHaveFocus(); | |||
await user.click(screen.getByRole('checkbox', { name: 'issues.select_all_issues' })); | |||
// Check that we bulk change the selected issue | |||
const issueBoxFixThat = within(await screen.findByRole('region', { name: 'Fix that' })); | |||
expect( | |||
issueBoxFixThat.getByRole('button', { | |||
name: 'issue.type.type_x_click_to_change.issue.type.CODE_SMELL' | |||
}) | |||
).toBeInTheDocument(); | |||
await user.click(screen.getByRole('checkbox', { name: 'issues.action_select.label.Fix that' })); | |||
expect(screen.getByRole('button', { name: 'issues.bulk_change_X_issues.1' })).toBeInTheDocument(); | |||
await user.click(screen.getByRole('button', { name: 'issues.bulk_change_X_issues.1' })); | |||
await user.click(screen.getByRole('textbox', { name: 'issue.comment.formlink' })); | |||
await user.keyboard('New Comment'); | |||
expect(screen.getByRole('button', { name: 'apply' })).toHaveAttribute('disabled'); | |||
await selectEvent.select(screen.getByRole('textbox', { name: 'issue.set_type' }), [ | |||
'issue.type.BUG' | |||
]); | |||
await user.click(screen.getByRole('button', { name: 'apply' })); | |||
expect( | |||
issueBoxFixThat.getByRole('button', { | |||
name: 'issue.type.type_x_click_to_change.issue.type.BUG' | |||
}) | |||
).toBeInTheDocument(); | |||
}); | |||
it('should show education principles', async () => { | |||
const user = userEvent.setup(); | |||
renderProjectIssuesApp('project/issues?issues=issue2&open=issue2&id=myproject'); | |||
@@ -480,7 +527,7 @@ describe('redirects', () => { | |||
}); | |||
function renderIssueApp(currentUser?: CurrentUser) { | |||
renderApp('project/issues', <IssuesApp />, { currentUser: mockCurrentUser(), ...currentUser }); | |||
renderApp('project/issues', <IssuesApp />, { currentUser: mockCurrentUser(currentUser) }); | |||
} | |||
function renderProjectIssuesApp(navigateTo?: string) { |
@@ -113,7 +113,6 @@ beforeEach(() => { | |||
}); | |||
afterEach(() => { | |||
// jest.clearAllMocks(); | |||
(searchIssues as jest.Mock).mockReset(); | |||
}); | |||
@@ -274,74 +273,6 @@ it('should be able to bulk change specific issues', async () => { | |||
expect(issues).toHaveLength(2); | |||
}); | |||
it('should be able to uncheck all issue with global checkbox', async () => { | |||
const wrapper = shallowRender(); | |||
await waitAndUpdate(wrapper); | |||
expect(wrapper.state().issues.length).toBe(4); | |||
const instance = wrapper.instance(); | |||
instance.handleIssueCheck('foo'); | |||
instance.handleIssueCheck('bar'); | |||
expect(wrapper.state().checked.length).toBe(2); | |||
instance.handleCheckAll(false); | |||
expect(wrapper.state().checked.length).toBe(0); | |||
}); | |||
it('should be able to check all issue with global checkbox', async () => { | |||
const wrapper = shallowRender(); | |||
await waitAndUpdate(wrapper); | |||
const instance = wrapper.instance(); | |||
expect(wrapper.state().checked.length).toBe(0); | |||
instance.handleCheckAll(true); | |||
expect(wrapper.state().checked.length).toBe(wrapper.state().issues.length); | |||
}); | |||
it('should check all issues, even the ones that are not visible', async () => { | |||
(searchIssues as jest.Mock).mockResolvedValueOnce({ | |||
components: [referencedComponent], | |||
effortTotal: 1, | |||
facets: FACETS, | |||
issues: ISSUES, | |||
languages: [], | |||
paging: { pageIndex: 1, pageSize: 100, total: 250 }, | |||
rules: [], | |||
users: [] | |||
}); | |||
const wrapper = shallowRender(); | |||
const instance = wrapper.instance(); | |||
await waitAndUpdate(wrapper); | |||
// Checking all issues should show the correct count in the Bulk Change button. | |||
instance.handleCheckAll(true); | |||
waitAndUpdate(wrapper); | |||
expect(wrapper.find('#issues-bulk-change')).toMatchSnapshot(); | |||
}); | |||
it('should check max 500 issues', async () => { | |||
(searchIssues as jest.Mock).mockResolvedValue({ | |||
components: [referencedComponent], | |||
effortTotal: 1, | |||
facets: FACETS, | |||
issues: ISSUES, | |||
languages: [], | |||
paging: { pageIndex: 1, pageSize: 100, total: 1000 }, | |||
rules: [], | |||
users: [] | |||
}); | |||
const wrapper = shallowRender(); | |||
const instance = wrapper.instance(); | |||
await waitAndUpdate(wrapper); | |||
// Checking all issues should show 500 in the Bulk Change button, and display | |||
// a warning. | |||
instance.handleCheckAll(true); | |||
waitAndUpdate(wrapper); | |||
expect(wrapper.find('#issues-bulk-change')).toMatchSnapshot(); | |||
}); | |||
it('should display the right facets open', () => { | |||
expect( | |||
shallowRender({ |
@@ -1,35 +1,5 @@ | |||
// Jest Snapshot v1, https://goo.gl/fbAQLP | |||
exports[`should check all issues, even the ones that are not visible 1`] = ` | |||
<Button | |||
disabled={false} | |||
id="issues-bulk-change" | |||
innerRef={ | |||
Object { | |||
"current": null, | |||
} | |||
} | |||
onClick={[Function]} | |||
> | |||
issues.bulk_change_X_issues.250 | |||
</Button> | |||
`; | |||
exports[`should check max 500 issues 1`] = ` | |||
<Button | |||
disabled={false} | |||
id="issues-bulk-change" | |||
innerRef={ | |||
Object { | |||
"current": null, | |||
} | |||
} | |||
onClick={[Function]} | |||
> | |||
issues.bulk_change_X_issues.500 | |||
</Button> | |||
`; | |||
exports[`should show warnning when not all projects are accessible 1`] = ` | |||
<div | |||
className="layout-page-side-outer" |
@@ -288,10 +288,9 @@ export class TooltipInner extends React.Component<TooltipProps, State> { | |||
handleBlur = () => { | |||
if (this.mounted) { | |||
this.setState({ visible: false }); | |||
} | |||
if (this.props.onHide) { | |||
this.props.onHide(); | |||
if (this.props.onHide) { | |||
this.props.onHide(); | |||
} | |||
} | |||
}; | |||