]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-21381 Show author in Issue activity
authorViktor Vorona <viktor.vorona@sonarsource.com>
Fri, 5 Jan 2024 13:03:26 +0000 (14:03 +0100)
committersonartech <sonartech@sonarsource.com>
Wed, 17 Jan 2024 20:02:45 +0000 (20:02 +0000)
16 files changed:
server/sonar-web/src/main/js/api/mocks/IssuesServiceMock.ts
server/sonar-web/src/main/js/api/mocks/UsersServiceMock.ts
server/sonar-web/src/main/js/api/mocks/data/issues.ts
server/sonar-web/src/main/js/apps/issues/__tests__/IssueApp-it.tsx
server/sonar-web/src/main/js/apps/issues/__tests__/IssuesApp-Filtering-it.tsx
server/sonar-web/src/main/js/apps/issues/__tests__/IssuesApp-it.tsx
server/sonar-web/src/main/js/apps/issues/__tests__/IssuesAppActivity-it.tsx
server/sonar-web/src/main/js/apps/issues/__tests__/IssuesAppGuide-it.tsx
server/sonar-web/src/main/js/apps/issues/__tests__/IssuesNewStatusAndTransitionGuide-it.tsx
server/sonar-web/src/main/js/apps/issues/__tests__/IssuesSourceViewer-it.tsx
server/sonar-web/src/main/js/apps/issues/components/IssueReviewHistory.tsx
server/sonar-web/src/main/js/apps/issues/crossComponentSourceViewer/utils.ts
server/sonar-web/src/main/js/apps/issues/test-utils.tsx
server/sonar-web/src/main/js/components/SourceViewer/__tests__/SourceViewer-it.tsx
server/sonar-web/src/main/js/components/issue/__tests__/Issue-it.tsx
server/sonar-web/src/main/js/queries/users.ts

index 4400f4a3e8a9fba762f0bc3633b9ed4e332de389..a451cf43a1f657140d5ccb63e759f5e3aa8a4dfe 100644 (file)
@@ -47,7 +47,6 @@ import {
 import { SearchRulesQuery } from '../../types/rules';
 import { Standards } from '../../types/security';
 import { Dict, Rule, RuleActivation, RuleDetails, SnippetsByComponent } from '../../types/types';
-import { LoggedInUser, NoticeType, RestUser } from '../../types/users';
 import {
   addIssueComment,
   bulkChangeIssues,
@@ -57,8 +56,8 @@ import {
   getIssueFlowSnippets,
   listIssues,
   searchIssueAuthors,
-  searchIssueTags,
   searchIssues,
+  searchIssueTags,
   setIssueAssignee,
   setIssueSeverity,
   setIssueTags,
@@ -66,15 +65,14 @@ import {
   setIssueType,
 } from '../issues';
 import { getRuleDetails, searchRules } from '../rules';
-import { dismissNotice, getCurrentUser, getUsers } from '../users';
 import { IssueData, mockIssuesList } from './data/issues';
 import { mockRuleList } from './data/rules';
+import UsersServiceMock from './UsersServiceMock';
 
 jest.mock('../../api/issues');
 // The following 2 mocks are needed, because IssuesServiceMock mocks more than it should.
 // This should be removed once IssuesServiceMock is cleaned up.
 jest.mock('../../api/rules');
-jest.mock('../../api/users');
 
 function mockReferenceComponent(override?: Partial<ReferencedComponent>) {
   return {
@@ -101,14 +99,14 @@ function generateReferenceComponentsForIssues(issueData: IssueData[]) {
 
 export default class IssuesServiceMock {
   isAdmin = false;
-  currentUser: LoggedInUser;
   standards?: Standards;
+  usersServiceMock?: UsersServiceMock;
   defaultList: IssueData[];
   rulesList: Rule[];
   list: IssueData[];
 
-  constructor() {
-    this.currentUser = mockLoggedInUser();
+  constructor(usersServiceMock?: UsersServiceMock) {
+    this.usersServiceMock = usersServiceMock;
     this.defaultList = mockIssuesList();
     this.rulesList = mockRuleList();
 
@@ -117,9 +115,7 @@ export default class IssuesServiceMock {
     jest.mocked(addIssueComment).mockImplementation(this.handleAddComment);
     jest.mocked(bulkChangeIssues).mockImplementation(this.handleBulkChangeIssues);
     jest.mocked(deleteIssueComment).mockImplementation(this.handleDeleteComment);
-    jest.mocked(dismissNotice).mockImplementation(this.handleDismissNotification);
     jest.mocked(editIssueComment).mockImplementation(this.handleEditComment);
-    jest.mocked(getCurrentUser).mockImplementation(this.handleGetCurrentUser);
     jest.mocked(getIssueChangelog).mockImplementation(this.handleGetIssueChangelog);
     jest.mocked(getIssueFlowSnippets).mockImplementation(this.handleGetIssueFlowSnippets);
     jest.mocked(getRuleDetails).mockImplementation(this.handleGetRuleDetails);
@@ -128,7 +124,6 @@ export default class IssuesServiceMock {
     jest.mocked(searchIssues).mockImplementation(this.handleSearchIssues);
     jest.mocked(searchIssueTags).mockImplementation(this.handleSearchIssueTags);
     jest.mocked(searchRules).mockImplementation(this.handleSearchRules);
-    jest.mocked(getUsers).mockImplementation(this.handleGetUsers);
     jest.mocked(setIssueAssignee).mockImplementation(this.handleSetIssueAssignee);
     jest.mocked(setIssueSeverity).mockImplementation(this.handleSetIssueSeverity);
     jest.mocked(setIssueTags).mockImplementation(this.handleSetIssueTags);
@@ -138,11 +133,6 @@ export default class IssuesServiceMock {
 
   reset = () => {
     this.list = cloneDeep(this.defaultList);
-    this.currentUser = mockLoggedInUser();
-  };
-
-  setCurrentUser = (user: LoggedInUser) => {
-    this.currentUser = user;
   };
 
   setIssueList = (list: IssueData[]) => {
@@ -496,24 +486,6 @@ export default class IssuesServiceMock {
     });
   };
 
-  handleGetCurrentUser = () => {
-    return this.reply(this.currentUser);
-  };
-
-  handleDismissNotification = (noticeType: NoticeType) => {
-    if (
-      [
-        NoticeType.EDUCATION_PRINCIPLES,
-        NoticeType.ISSUE_GUIDE,
-        NoticeType.ISSUE_NEW_STATUS_AND_TRANSITION_GUIDE,
-      ].includes(noticeType)
-    ) {
-      return this.reply(true);
-    }
-
-    return Promise.reject();
-  };
-
   handleSetIssueType = (data: { issue: string; type: IssueType }) => {
     return this.getActionsResponse({ type: data.type }, data.issue);
   };
@@ -524,7 +496,10 @@ export default class IssuesServiceMock {
 
   handleSetIssueAssignee = (data: { issue: string; assignee?: string }) => {
     return this.getActionsResponse(
-      { assignee: data.assignee === '_me' ? this.currentUser.login : data.assignee },
+      {
+        assignee:
+          data.assignee === '_me' ? this.usersServiceMock?.currentUser.login : data.assignee,
+      },
       data.issue,
     );
   };
@@ -628,13 +603,6 @@ export default class IssuesServiceMock {
     );
   };
 
-  handleGetUsers = () => {
-    return this.reply({
-      page: mockPaging(),
-      users: [mockLoggedInUser() as unknown as RestUser],
-    });
-  };
-
   handleSearchIssueAuthors = () => {
     return this.reply(mockIssueAuthors());
   };
index 77dc8e6217175fd62db577b019038a2d0c63cf6c..1d0e13dac7c9c8d05b2044ebed1978dcb8bb2e2c 100644 (file)
 import { isAfter, isBefore } from 'date-fns';
 import { cloneDeep, isEmpty, isUndefined, omitBy } from 'lodash';
 import { HttpStatus } from '../../helpers/request';
-import { mockIdentityProvider, mockRestUser } from '../../helpers/testMocks';
+import { mockIdentityProvider, mockLoggedInUser, mockRestUser } from '../../helpers/testMocks';
 import { IdentityProvider } from '../../types/types';
-import { ChangePasswordResults, RestUserDetailed } from '../../types/users';
+import {
+  ChangePasswordResults,
+  LoggedInUser,
+  NoticeType,
+  RestUserDetailed,
+} from '../../types/users';
 import { addUserToGroup, removeUserFromGroup } from '../legacy-group-membership';
 import {
   UserGroup,
   changePassword,
   deleteUser,
   dismissNotice,
+  getCurrentUser,
   getIdentityProviders,
   getUserGroups,
   getUsers,
@@ -131,6 +137,7 @@ const DEFAULT_PASSWORD = 'test';
 export default class UsersServiceMock {
   isManaged = true;
   users = cloneDeep(DEFAULT_USERS);
+  currentUser = mockLoggedInUser();
   groups = cloneDeep(DEFAULT_GROUPS);
   password = DEFAULT_PASSWORD;
   groupMembershipsServiceMock?: GroupMembershipsServiceMock = undefined;
@@ -145,7 +152,8 @@ export default class UsersServiceMock {
     jest.mocked(removeUserFromGroup).mockImplementation(this.handleRemoveUserFromGroup);
     jest.mocked(changePassword).mockImplementation(this.handleChangePassword);
     jest.mocked(deleteUser).mockImplementation(this.handleDeactivateUser);
-    jest.mocked(dismissNotice).mockResolvedValue({});
+    jest.mocked(dismissNotice).mockImplementation(this.handleDismissNotification);
+    jest.mocked(getCurrentUser).mockImplementation(this.handleGetCurrentUser);
   }
 
   getFilteredRestUsers = (filterParams: Parameters<typeof getUsers>[0]) => {
@@ -178,7 +186,7 @@ export default class UsersServiceMock {
         return false;
       }
 
-      if (q && (!user.login.includes(q) || (user.name && !user.name.includes(q)))) {
+      if (q && !user.login.includes(q) && !user.name?.includes(q) && !user.email?.includes(q)) {
         return false;
       }
 
@@ -354,11 +362,28 @@ export default class UsersServiceMock {
     return this.reply(undefined);
   };
 
+  handleDismissNotification: typeof dismissNotice = (noticeType: NoticeType) => {
+    if (Object.values(NoticeType).includes(noticeType)) {
+      return this.reply(true);
+    }
+
+    return Promise.reject();
+  };
+
+  setCurrentUser = (user: LoggedInUser) => {
+    this.currentUser = user;
+  };
+
+  handleGetCurrentUser: typeof getCurrentUser = () => {
+    return this.reply(this.currentUser);
+  };
+
   reset = () => {
     this.isManaged = true;
     this.users = cloneDeep(DEFAULT_USERS);
     this.groups = cloneDeep(DEFAULT_GROUPS);
     this.password = DEFAULT_PASSWORD;
+    this.currentUser = mockLoggedInUser();
   };
 
   reply<T>(response: T): Promise<T> {
index 129806d01f59a8e478e4b8a021172818a39be406..3efa63ae18dc3b467f7d5bd2dda900ec9c7991d2 100644 (file)
@@ -320,6 +320,7 @@ export function mockIssuesList(baseComponentKey = PARENT_COMPONENT_KEY): IssueDa
         status: IssueDeprecatedStatus.Open,
         issueStatus: IssueStatus.Open,
         ruleDescriptionContextKey: 'spring',
+        author: 'bob.marley@test.com',
       }),
       snippets: keyBy(
         [
@@ -347,6 +348,7 @@ export function mockIssuesList(baseComponentKey = PARENT_COMPONENT_KEY): IssueDa
         resolution: IssueResolution.Fixed,
         status: IssueDeprecatedStatus.Confirmed,
         issueStatus: IssueStatus.Confirmed,
+        author: 'unknownemail@test.com',
       }),
       snippets: keyBy(
         [
index 0ec30c428fb5e654118a3f6d09eb39bbfd6c1092..ad7246fa8b24faddbc7bbc96b088cae85271e969 100644 (file)
@@ -21,7 +21,9 @@ import { screen, within } from '@testing-library/react';
 import userEvent from '@testing-library/user-event';
 import React from 'react';
 import { TabKeys } from '../../../components/rules/RuleTabViewer';
+import { mockLoggedInUser } from '../../../helpers/testMocks';
 import { byRole } from '../../../helpers/testSelector';
+import { RestUserDetailed } from '../../../types/users';
 import {
   branchHandler,
   componentsHandler,
@@ -29,6 +31,7 @@ import {
   renderIssueApp,
   renderProjectIssuesApp,
   ui,
+  usersHandler,
 } from '../test-utils';
 
 jest.mock('../sidebar/Sidebar', () => {
@@ -58,6 +61,8 @@ beforeEach(() => {
   issuesHandler.reset();
   componentsHandler.reset();
   branchHandler.reset();
+  usersHandler.reset();
+  usersHandler.users = [mockLoggedInUser() as unknown as RestUserDetailed];
   window.scrollTo = jest.fn();
   window.HTMLElement.prototype.scrollTo = jest.fn();
 });
index 1a62b0f35f393bb3a14e8cf9331f79479cc47424..66670341b52c9406189c8c46c6cb00caf23b0196 100644 (file)
@@ -31,6 +31,7 @@ import {
   renderIssueApp,
   renderProjectIssuesApp,
   ui,
+  usersHandler,
   waitOnDataLoaded,
 } from '../test-utils';
 
@@ -56,6 +57,7 @@ beforeEach(() => {
   issuesHandler.reset();
   componentsHandler.reset();
   branchHandler.reset();
+  usersHandler.reset();
   window.scrollTo = jest.fn();
   window.HTMLElement.prototype.scrollTo = jest.fn();
 });
@@ -192,7 +194,7 @@ describe('issues app filtering', () => {
   it('should allow to set creation date', async () => {
     const user = userEvent.setup();
     const currentUser = mockLoggedInUser({ dismissedNotices: { [NoticeType.ISSUE_GUIDE]: true } });
-    issuesHandler.setCurrentUser(currentUser);
+    usersHandler.setCurrentUser(currentUser);
 
     renderIssueApp(currentUser);
 
@@ -229,7 +231,7 @@ describe('issues app filtering', () => {
   it('should allow to only show my issues', async () => {
     const user = userEvent.setup();
     const currentUser = mockLoggedInUser({ dismissedNotices: { [NoticeType.ISSUE_GUIDE]: true } });
-    issuesHandler.setCurrentUser(currentUser);
+    usersHandler.setCurrentUser(currentUser);
     renderIssueApp(currentUser);
     await waitOnDataLoaded();
 
index 5ebcbd4d4e6143bc4ead0f1b6c8630be5749b534..49633d8a9bf688a3d418a866882f4472b79c7a96 100644 (file)
@@ -31,6 +31,7 @@ import {
   renderIssueApp,
   renderProjectIssuesApp,
   ui,
+  usersHandler,
 } from '../test-utils';
 
 jest.mock('../sidebar/Sidebar', () => {
@@ -48,6 +49,7 @@ beforeEach(() => {
   issuesHandler.reset();
   componentsHandler.reset();
   branchHandler.reset();
+  usersHandler.reset();
   window.scrollTo = jest.fn();
   window.HTMLElement.prototype.scrollTo = jest.fn();
 });
@@ -221,7 +223,7 @@ describe('issues app', () => {
         dismissedNotices: { [NoticeType.ISSUE_GUIDE]: true },
       });
       issuesHandler.setIsAdmin(true);
-      issuesHandler.setCurrentUser(currentUser);
+      usersHandler.setCurrentUser(currentUser);
       renderIssueApp(currentUser);
 
       // Check that the bulk button has correct behavior
@@ -250,7 +252,7 @@ describe('issues app', () => {
         dismissedNotices: { [NoticeType.ISSUE_GUIDE]: true },
       });
       issuesHandler.setIsAdmin(true);
-      issuesHandler.setCurrentUser(currentUser);
+      usersHandler.setCurrentUser(currentUser);
       renderIssueApp(currentUser);
 
       // Check that we bulk change the selected issue
index 7d679a4a39c60bef82983ed9f3c554ad8a192293..5c6fec5e12189e0ece5c7738403bdcc4a0dcd20d 100644 (file)
 import { screen } from '@testing-library/react';
 import userEvent from '@testing-library/user-event';
 import React from 'react';
-import { branchHandler, componentsHandler, issuesHandler, renderIssueApp, ui } from '../test-utils';
+import { mockRestUser } from '../../../helpers/testMocks';
+import {
+  branchHandler,
+  componentsHandler,
+  issuesHandler,
+  renderIssueApp,
+  ui,
+  usersHandler,
+} from '../test-utils';
 
 jest.mock('../sidebar/Sidebar', () => {
   const fakeSidebar = () => {
@@ -49,6 +57,14 @@ beforeEach(() => {
   issuesHandler.reset();
   componentsHandler.reset();
   branchHandler.reset();
+  usersHandler.reset();
+  usersHandler.users = [
+    mockRestUser({
+      login: 'bob.marley',
+      email: 'bob.marley@test.com',
+      name: 'Bob Marley',
+    }),
+  ];
   window.scrollTo = jest.fn();
   window.HTMLElement.prototype.scrollTo = jest.fn();
 });
@@ -103,7 +119,7 @@ it('should be able to show changelog', async () => {
 
   await user.click(ui.issueActivityTab.get());
 
-  expect(screen.getByText('issue.activity.review_history.created')).toBeInTheDocument();
+  expect(screen.getByText(/issue.activity.review_history.created/)).toHaveTextContent('Bob Marley');
   expect(
     screen.getByText(
       'issue.changelog.changed_to.issue.changelog.field.assign.darth.vader (issue.changelog.was.luke.skywalker)',
@@ -125,3 +141,17 @@ it('should be able to show changelog', async () => {
     ),
   ).not.toBeInTheDocument();
 });
+
+it('should show author email if there is no user with that email', async () => {
+  const user = userEvent.setup();
+  issuesHandler.setIsAdmin(true);
+  renderIssueApp();
+
+  await user.click(await ui.issueItemAction6.find());
+
+  await user.click(ui.issueActivityTab.get());
+
+  expect(screen.getByText(/issue.activity.review_history.created/)).toHaveTextContent(
+    'unknownemail@test.com',
+  );
+});
index 9e794a924b8c27be4c980010e34c1e6300f30a0c..636b22240eeff896d04683dda0c46b5d4c3d786f 100644 (file)
@@ -28,6 +28,7 @@ import {
   renderIssueApp,
   renderProjectIssuesApp,
   ui,
+  usersHandler,
 } from '../test-utils';
 
 jest.mock('../sidebar/Sidebar', () => {
@@ -57,6 +58,7 @@ beforeEach(() => {
   issuesHandler.reset();
   componentsHandler.reset();
   branchHandler.reset();
+  usersHandler.reset();
   window.scrollTo = jest.fn();
   window.HTMLElement.prototype.scrollTo = jest.fn();
 });
index 3700e006c8ea936dabfbe82d51b7d93df23aabaf..0a95a39f2ccb2f57eb954bc8c041a3bc7e747ad9 100644 (file)
@@ -20,7 +20,6 @@
 import { act } from '@testing-library/react';
 import userEvent from '@testing-library/user-event';
 import React from 'react';
-import IssuesServiceMock from '../../../api/mocks/IssuesServiceMock';
 import CurrentUserContextProvider from '../../../app/components/current-user/CurrentUserContextProvider';
 import IssueTransitionComponent from '../../../components/issue/components/IssueTransition';
 import { mockCurrentUser, mockIssue } from '../../../helpers/testMocks';
@@ -29,9 +28,7 @@ import { IssueTransition } from '../../../types/issues';
 import { Issue } from '../../../types/types';
 import { NoticeType } from '../../../types/users';
 import IssueNewStatusAndTransitionGuide from '../components/IssueNewStatusAndTransitionGuide';
-import { ui } from '../test-utils';
-
-const issuesHandler = new IssuesServiceMock();
+import { issuesHandler, ui } from '../test-utils';
 
 beforeEach(() => {
   issuesHandler.reset();
index 1facb45f6f39b221d0d3e595bb989a7f7bf8e6e7..59e2a997b660e5a9fc11d3bd1919106a556aab9e 100644 (file)
@@ -24,12 +24,14 @@ import {
   componentsHandler,
   issuesHandler,
   renderProjectIssuesApp,
+  usersHandler,
   waitOnDataLoaded,
 } from '../test-utils';
 
 beforeEach(() => {
   issuesHandler.reset();
   componentsHandler.reset();
+  usersHandler.reset();
   window.scrollTo = jest.fn();
   window.HTMLElement.prototype.scrollTo = jest.fn();
 });
index 400e3fe27e2a29ff1d42c88791696f719dc07954..9bdc3e17d9bec5f71b3186e8a5ab97db2b332958 100644 (file)
@@ -39,7 +39,7 @@ import { sanitizeUserInput } from '../../../helpers/sanitize';
 import { ReviewHistoryType } from '../../../types/security-hotspots';
 import { Issue, IssueChangelog } from '../../../types/types';
 import HotspotCommentModal from '../../security-hotspots/components/HotspotCommentModal';
-import { getIssueReviewHistory } from '../crossComponentSourceViewer/utils';
+import { useGetIssueReviewHistory } from '../crossComponentSourceViewer/utils';
 
 export interface HotspotReviewHistoryProps {
   issue: Issue;
@@ -50,7 +50,7 @@ export interface HotspotReviewHistoryProps {
 export default function IssueReviewHistory(props: HotspotReviewHistoryProps) {
   const { issue } = props;
   const [changeLog, setChangeLog] = React.useState<IssueChangelog[]>([]);
-  const history = getIssueReviewHistory(issue, changeLog);
+  const history = useGetIssueReviewHistory(issue, changeLog);
   const [editCommentKey, setEditCommentKey] = React.useState('');
   const [deleteCommentKey, setDeleteCommentKey] = React.useState('');
 
index 135d51c4aa9daf1af9836933a32f071ea21b5ff2..7b9d057d675754fc9092ca5d7e4f181d8b3ab07a 100644 (file)
@@ -20,6 +20,7 @@
 import { sortBy } from 'lodash';
 import { decorateWithUnderlineFlags } from '../../../helpers/code-viewer';
 import { isDefined } from '../../../helpers/types';
+import { useUsersQueries } from '../../../queries/users';
 import { ComponentQualifier } from '../../../types/component';
 import { ReviewHistoryElement, ReviewHistoryType } from '../../../types/security-hotspots';
 import {
@@ -33,6 +34,7 @@ import {
   SnippetsByComponent,
   SourceLine,
 } from '../../../types/types';
+import { RestUser } from '../../../types/users';
 
 const LINES_ABOVE = 5;
 const LINES_BELOW = 5;
@@ -235,20 +237,23 @@ export function inSnippet(line: number, snippet: SourceLine[]) {
   return line >= snippet[0].line && line <= snippet[snippet.length - 1].line;
 }
 
-export function getIssueReviewHistory(
+export function useGetIssueReviewHistory(
   issue: Issue,
   changelog: IssueChangelog[],
 ): ReviewHistoryElement[] {
   const history: ReviewHistoryElement[] = [];
 
+  const { data } = useUsersQueries<RestUser>({ q: issue.author ?? '' }, !!issue.author);
+  const author = data?.pages[0]?.users[0] ?? null;
+
   if (issue.creationDate) {
     history.push({
       type: ReviewHistoryType.Creation,
       date: issue.creationDate,
       user: {
-        active: issue.assigneeActive,
-        avatar: issue.assigneeAvatar,
-        name: issue.assigneeName || issue.assigneeLogin,
+        active: true,
+        avatar: author?.avatar,
+        name: author?.name ?? author?.login ?? issue.author,
       },
     });
   }
index 0c3ed20a5952593ab3555e9ee6a245a17064372d..1b5d7cd3a51b66710caa3788a59f8e7bc2b913dd 100644 (file)
@@ -23,6 +23,7 @@ import { Outlet, Route } from 'react-router-dom';
 import BranchesServiceMock from '../../api/mocks/BranchesServiceMock';
 import ComponentsServiceMock from '../../api/mocks/ComponentsServiceMock';
 import IssuesServiceMock from '../../api/mocks/IssuesServiceMock';
+import UsersServiceMock from '../../api/mocks/UsersServiceMock';
 import { mockComponent } from '../../helpers/mocks/component';
 import { mockCurrentUser } from '../../helpers/testMocks';
 import { renderApp, renderAppWithComponentContext } from '../../helpers/testReactTestingUtils';
@@ -38,7 +39,8 @@ import { NoticeType } from '../../types/users';
 import IssuesApp from './components/IssuesApp';
 import { projectIssuesRoutes } from './routes';
 
-export const issuesHandler = new IssuesServiceMock();
+export const usersHandler = new UsersServiceMock();
+export const issuesHandler = new IssuesServiceMock(usersHandler);
 export const componentsHandler = new ComponentsServiceMock();
 export const branchHandler = new BranchesServiceMock();
 
index 9e76f47e07f6965825db22552553d3ee974f288b..f29f2d820787b5812d78bf95bdb33b27df8cccff 100644 (file)
@@ -22,9 +22,11 @@ import userEvent from '@testing-library/user-event';
 import * as React from 'react';
 import ComponentsServiceMock from '../../../api/mocks/ComponentsServiceMock';
 import IssuesServiceMock from '../../../api/mocks/IssuesServiceMock';
+import UsersServiceMock from '../../../api/mocks/UsersServiceMock';
 import { HttpStatus } from '../../../helpers/request';
-import { mockIssue } from '../../../helpers/testMocks';
+import { mockIssue, mockLoggedInUser } from '../../../helpers/testMocks';
 import { renderComponent } from '../../../helpers/testReactTestingUtils';
+import { RestUserDetailed } from '../../../types/users';
 import SourceViewer, { Props } from '../SourceViewer';
 import loadIssues from '../helpers/loadIssues';
 
@@ -33,7 +35,6 @@ jest.mock('../../../api/issues');
 // The following 2 mocks are needed, because IssuesServiceMock mocks more than it should.
 // This should be removed once IssuesServiceMock is cleaned up.
 jest.mock('../../../api/rules');
-jest.mock('../../../api/users');
 
 jest.mock('../helpers/loadIssues', () => ({
   __esModule: true,
@@ -50,11 +51,14 @@ jest.mock('../helpers/lines', () => {
 
 const componentsHandler = new ComponentsServiceMock();
 const issuesHandler = new IssuesServiceMock();
+const usersHandler = new UsersServiceMock();
 const message = 'First Issue';
 
 beforeEach(() => {
   issuesHandler.reset();
   componentsHandler.reset();
+  usersHandler.reset();
+  usersHandler.users = [mockLoggedInUser() as unknown as RestUserDetailed];
 });
 
 it('should show a permalink on line number', async () => {
index 89638fad59646bdbdfa39a7afa687ff2318cded0..eb03a1dc21e84ae38ebc76dd52e7a35e0f119583 100644 (file)
@@ -23,6 +23,7 @@ import { omit, pick } from 'lodash';
 import * as React from 'react';
 import { Route } from 'react-router-dom';
 import IssuesServiceMock from '../../../api/mocks/IssuesServiceMock';
+import UsersServiceMock from '../../../api/mocks/UsersServiceMock';
 import { KeyboardKeys } from '../../../helpers/keycodes';
 import { mockIssue, mockLoggedInUser, mockRawIssue } from '../../../helpers/testMocks';
 import { renderAppRoutes } from '../../../helpers/testReactTestingUtils';
@@ -35,16 +36,20 @@ import {
   IssueTransition,
   IssueType,
 } from '../../../types/issues';
+import { RestUserDetailed } from '../../../types/users';
 import Issue from '../Issue';
 
 jest.mock('../../../helpers/preferences', () => ({
   getKeyboardShortcutEnabled: jest.fn(() => true),
 }));
 
-const issuesHandler = new IssuesServiceMock();
+const usersHandler = new UsersServiceMock();
+const issuesHandler = new IssuesServiceMock(usersHandler);
 
 beforeEach(() => {
   issuesHandler.reset();
+  usersHandler.reset();
+  usersHandler.users = [mockLoggedInUser() as unknown as RestUserDetailed];
 });
 
 describe('rendering', () => {
@@ -147,7 +152,7 @@ it('should correctly handle keyboard shortcuts', async () => {
     transitions: [IssueTransition.Confirm, IssueTransition.UnConfirm],
   });
   issuesHandler.setIssueList([{ issue, snippets: {} }]);
-  issuesHandler.setCurrentUser(mockLoggedInUser({ login: 'leia', name: 'Organa' }));
+  usersHandler.setCurrentUser(mockLoggedInUser({ login: 'leia', name: 'Organa' }));
   renderIssue({
     onCheck,
     selected: true,
index 0ba1e2737cd3c69f30c52e1a54c3ff25d2315bb6..1a97eaeb45efa8f7a7a01dc07f7c68549b485529 100644 (file)
@@ -37,12 +37,14 @@ const STALE_TIME = 4 * 60 * 1000;
 
 export function useUsersQueries<U extends RestUserBase>(
   getParams: Omit<Parameters<typeof getUsers>[0], 'pageSize' | 'pageIndex'>,
+  enabled = true,
 ) {
   return useInfiniteQuery({
     queryKey: ['user', 'list', getParams],
     queryFn: ({ pageParam = 1 }) => getUsers<U>({ ...getParams, pageIndex: pageParam }),
     getNextPageParam,
     getPreviousPageParam,
+    enabled,
   });
 }