]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-18553 Migrate concise issues list components tests to RTL
author7PH <benjamin.raymond@sonarsource.com>
Thu, 2 Mar 2023 10:21:09 +0000 (11:21 +0100)
committersonartech <sonartech@sonarsource.com>
Mon, 6 Mar 2023 20:03:37 +0000 (20:03 +0000)
18 files changed:
server/sonar-web/src/main/js/apps/issues/conciseIssuesList/ConciseIssueBox.tsx
server/sonar-web/src/main/js/apps/issues/conciseIssuesList/ConciseIssueLocations.tsx
server/sonar-web/src/main/js/apps/issues/conciseIssuesList/__tests__/ConciseIssue-test.tsx [deleted file]
server/sonar-web/src/main/js/apps/issues/conciseIssuesList/__tests__/ConciseIssueBox-test.tsx [deleted file]
server/sonar-web/src/main/js/apps/issues/conciseIssuesList/__tests__/ConciseIssueComponent-test.tsx [deleted file]
server/sonar-web/src/main/js/apps/issues/conciseIssuesList/__tests__/ConciseIssueLocationBadge-test.tsx [deleted file]
server/sonar-web/src/main/js/apps/issues/conciseIssuesList/__tests__/ConciseIssueLocations-test.tsx [deleted file]
server/sonar-web/src/main/js/apps/issues/conciseIssuesList/__tests__/ConciseIssues-it.tsx [new file with mode: 0644]
server/sonar-web/src/main/js/apps/issues/conciseIssuesList/__tests__/ConciseIssuesList-test.tsx [deleted file]
server/sonar-web/src/main/js/apps/issues/conciseIssuesList/__tests__/ConciseIssuesListHeader-test.tsx [deleted file]
server/sonar-web/src/main/js/apps/issues/conciseIssuesList/__tests__/__snapshots__/ConciseIssue-test.tsx.snap [deleted file]
server/sonar-web/src/main/js/apps/issues/conciseIssuesList/__tests__/__snapshots__/ConciseIssueBox-test.tsx.snap [deleted file]
server/sonar-web/src/main/js/apps/issues/conciseIssuesList/__tests__/__snapshots__/ConciseIssueComponent-test.tsx.snap [deleted file]
server/sonar-web/src/main/js/apps/issues/conciseIssuesList/__tests__/__snapshots__/ConciseIssueLocationBadge-test.tsx.snap [deleted file]
server/sonar-web/src/main/js/apps/issues/conciseIssuesList/__tests__/__snapshots__/ConciseIssueLocations-test.tsx.snap [deleted file]
server/sonar-web/src/main/js/apps/issues/conciseIssuesList/__tests__/__snapshots__/ConciseIssuesList-test.tsx.snap [deleted file]
server/sonar-web/src/main/js/apps/issues/conciseIssuesList/__tests__/__snapshots__/ConciseIssuesListHeader-test.tsx.snap [deleted file]
server/sonar-web/src/main/js/helpers/testMocks.ts

index 12568435f02200c9f411ffc775ff5a2560a67b14..e41bef46e560a62be305860841da0016cbfb6943 100644 (file)
@@ -79,7 +79,6 @@ export default class ConciseIssueBox extends React.PureComponent<Props> {
           className="concise-issue-box-message"
           aria-current={selected}
           innerRef={(node) => (this.messageElement = node)}
-          onClick={this.handleClick}
         >
           <IssueMessageHighlighting
             message={issue.message}
index 9182e2728f514e63aa76c6c1d18d648d82defee6..e99e0beaa2e3fd87de3db5e4466846153f3ac0e1 100644 (file)
@@ -32,10 +32,10 @@ interface State {
   collapsed: boolean;
 }
 
-const LIMIT = 8;
+export const COLLAPSE_LIMIT = 8;
 
 export default class ConciseIssueLocations extends React.PureComponent<Props, State> {
-  state: State = { collapsed: true };
+  state = { collapsed: true };
 
   handleExpandClick = () => {
     this.setState({ collapsed: false });
@@ -78,13 +78,13 @@ export default class ConciseIssueLocations extends React.PureComponent<Props, St
       );
     });
 
-    if (!this.state.collapsed || badges.length <= LIMIT) {
+    if (!this.state.collapsed || badges.length <= COLLAPSE_LIMIT) {
       return badges;
     }
 
     return (
       <>
-        {badges.slice(0, LIMIT - 1)}
+        {badges.slice(0, COLLAPSE_LIMIT - 1)}
         {this.renderExpandButton()}
       </>
     );
diff --git a/server/sonar-web/src/main/js/apps/issues/conciseIssuesList/__tests__/ConciseIssue-test.tsx b/server/sonar-web/src/main/js/apps/issues/conciseIssuesList/__tests__/ConciseIssue-test.tsx
deleted file mode 100644 (file)
index 954e447..0000000
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2023 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-import { shallow } from 'enzyme';
-import * as React from 'react';
-import { Issue } from '../../../../types/types';
-import ConciseIssue from '../ConciseIssue';
-
-const issue: Issue = {
-  actions: [],
-  component: '',
-  componentLongName: 'src/file.js',
-  componentQualifier: '',
-  componentUuid: '',
-  creationDate: '',
-  flows: [],
-  flowsWithType: [],
-  key: '',
-  message: '',
-  project: '',
-  projectKey: '',
-  projectName: '',
-  rule: '',
-  ruleName: '',
-  secondaryLocations: [],
-  severity: '',
-  status: '',
-  transitions: [],
-  type: 'BUG',
-};
-
-it('should render', () => {
-  expect(
-    shallow(
-      <ConciseIssue
-        issue={issue}
-        onFlowSelect={jest.fn()}
-        onLocationSelect={jest.fn()}
-        onSelect={jest.fn()}
-        previousIssue={undefined}
-        scroll={jest.fn()}
-        selected={false}
-        selectedFlowIndex={undefined}
-        selectedLocationIndex={undefined}
-      />
-    )
-  ).toMatchSnapshot();
-});
-
-it('should not render component', () => {
-  expect(
-    shallow(
-      <ConciseIssue
-        issue={{ ...issue, component: 'foo' }}
-        onFlowSelect={jest.fn()}
-        onLocationSelect={jest.fn()}
-        onSelect={jest.fn()}
-        previousIssue={{ ...issue, component: 'foo' }}
-        scroll={jest.fn()}
-        selected={false}
-        selectedFlowIndex={undefined}
-        selectedLocationIndex={undefined}
-      />
-    ).find('ConciseIssueComponent')
-  ).toHaveLength(0);
-});
diff --git a/server/sonar-web/src/main/js/apps/issues/conciseIssuesList/__tests__/ConciseIssueBox-test.tsx b/server/sonar-web/src/main/js/apps/issues/conciseIssuesList/__tests__/ConciseIssueBox-test.tsx
deleted file mode 100644 (file)
index bbea7fd..0000000
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2023 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-import { shallow } from 'enzyme';
-import * as React from 'react';
-import { mockIssue } from '../../../../helpers/testMocks';
-import { click, waitAndUpdate } from '../../../../helpers/testUtils';
-import ConciseIssueBox from '../ConciseIssueBox';
-
-it('should render correctly', async () => {
-  const onClick = jest.fn();
-  const issue = mockIssue();
-  const wrapper = shallowRender({ onClick, issue });
-  await waitAndUpdate(wrapper);
-  expect(wrapper).toMatchSnapshot();
-
-  click(wrapper.find('.concise-issue-box'));
-  expect(onClick).toHaveBeenCalledWith(issue.key);
-
-  expect(shallowRender({ issue: mockIssue(true), selected: true })).toMatchSnapshot();
-});
-
-const shallowRender = (props: Partial<ConciseIssueBox['props']> = {}) => {
-  return shallow(
-    <ConciseIssueBox
-      issue={mockIssue()}
-      onClick={jest.fn()}
-      onFlowSelect={jest.fn()}
-      onLocationSelect={jest.fn()}
-      scroll={jest.fn()}
-      selected={false}
-      selectedFlowIndex={0}
-      selectedLocationIndex={0}
-      {...props}
-    />
-  );
-};
diff --git a/server/sonar-web/src/main/js/apps/issues/conciseIssuesList/__tests__/ConciseIssueComponent-test.tsx b/server/sonar-web/src/main/js/apps/issues/conciseIssuesList/__tests__/ConciseIssueComponent-test.tsx
deleted file mode 100644 (file)
index 7db8fa1..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2023 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-import { shallow } from 'enzyme';
-import * as React from 'react';
-import ConciseIssueComponent from '../ConciseIssueComponent';
-
-it('should render', () => {
-  expect(
-    shallow(<ConciseIssueComponent path="src/app/folder/sub-folder/long-folder/name/app.js" />)
-  ).toMatchSnapshot();
-});
diff --git a/server/sonar-web/src/main/js/apps/issues/conciseIssuesList/__tests__/ConciseIssueLocationBadge-test.tsx b/server/sonar-web/src/main/js/apps/issues/conciseIssuesList/__tests__/ConciseIssueLocationBadge-test.tsx
deleted file mode 100644 (file)
index ed45c99..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2023 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-import { shallow } from 'enzyme';
-import * as React from 'react';
-import ConciseIssueLocationBadge from '../ConciseIssueLocationBadge';
-
-it('should render', () => {
-  expect(shallow(<ConciseIssueLocationBadge count={7} selected={false} />)).toMatchSnapshot();
-});
diff --git a/server/sonar-web/src/main/js/apps/issues/conciseIssuesList/__tests__/ConciseIssueLocations-test.tsx b/server/sonar-web/src/main/js/apps/issues/conciseIssuesList/__tests__/ConciseIssueLocations-test.tsx
deleted file mode 100644 (file)
index 5e09d67..0000000
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2023 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-import { shallow } from 'enzyme';
-import * as React from 'react';
-import ConciseIssueLocations from '../ConciseIssueLocations';
-
-const textRange = { startLine: 1, startOffset: 1, endLine: 1, endOffset: 1 };
-
-const loc = { component: '', msg: '', textRange };
-
-it('should render secondary locations', () => {
-  const issue = {
-    flows: [],
-    secondaryLocations: [loc, loc, loc],
-  };
-  expect(
-    shallow(
-      <ConciseIssueLocations issue={issue} onFlowSelect={jest.fn()} selectedFlowIndex={undefined} />
-    )
-  ).toMatchSnapshot();
-});
-
-it('should render one flow', () => {
-  const issue = {
-    flows: [[loc, loc, loc]],
-    secondaryLocations: [],
-  };
-  expect(
-    shallow(
-      <ConciseIssueLocations issue={issue} onFlowSelect={jest.fn()} selectedFlowIndex={undefined} />
-    )
-  ).toMatchSnapshot();
-});
-
-it('should render several flows', () => {
-  const issue = {
-    flows: [
-      [loc, loc, loc],
-      [loc, loc],
-      [loc, loc, loc],
-    ],
-    secondaryLocations: [],
-  };
-  expect(
-    shallow(
-      <ConciseIssueLocations issue={issue} onFlowSelect={jest.fn()} selectedFlowIndex={undefined} />
-    )
-  ).toMatchSnapshot();
-});
diff --git a/server/sonar-web/src/main/js/apps/issues/conciseIssuesList/__tests__/ConciseIssues-it.tsx b/server/sonar-web/src/main/js/apps/issues/conciseIssuesList/__tests__/ConciseIssues-it.tsx
new file mode 100644 (file)
index 0000000..0b1b38b
--- /dev/null
@@ -0,0 +1,332 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2023 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * 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 userEvent from '@testing-library/user-event';
+import * as React from 'react';
+import { byRole, byText } from 'testing-library-selector';
+import { mockFlowLocation, mockIssue } from '../../../../helpers/testMocks';
+import { renderComponent } from '../../../../helpers/testReactTestingUtils';
+import { FlowType, Issue } from '../../../../types/types';
+import { COLLAPSE_LIMIT } from '../ConciseIssueLocations';
+import ConciseIssuesList, { ConciseIssuesListProps } from '../ConciseIssuesList';
+import ConciseIssuesListHeader, { ConciseIssuesListHeaderProps } from '../ConciseIssuesListHeader';
+
+const loc = mockFlowLocation();
+const issues = [
+  mockIssue(false, {
+    key: 'issue1',
+    message: 'Issue 1',
+    component: 'foo',
+    componentLongName: 'Long Foo',
+  }),
+  mockIssue(false, {
+    key: 'issue2',
+    message: 'Issue 2',
+    component: 'foo',
+    componentLongName: 'Long Foo',
+  }),
+  mockIssue(false, {
+    key: 'issue3',
+    message: 'Issue 3',
+    component: 'bar',
+    componentLongName: 'Long Bar',
+  }),
+  mockIssue(true, {
+    key: 'issue4',
+    message: 'Issue 4',
+    component: 'foo',
+    componentLongName: 'Long Foo',
+    flowsWithType: [
+      {
+        type: FlowType.DATA,
+        description: 'Flow Foo',
+        locations: [mockFlowLocation({ msg: 'loc 1' })],
+      },
+    ],
+  }),
+];
+
+const originalScrollIntoView = HTMLElement.prototype.scrollIntoView;
+
+beforeAll(() => {
+  HTMLElement.prototype.scrollIntoView = jest.fn();
+});
+
+afterAll(() => {
+  HTMLElement.prototype.scrollIntoView = originalScrollIntoView;
+});
+
+describe('rendering', () => {
+  it('should hide the back button', () => {
+    const { ui } = getPageObject();
+    renderConciseIssues(issues, {}, { displayBackButton: false });
+
+    expect(ui.headerBackButton.query()).not.toBeInTheDocument();
+  });
+
+  it('should render concise issues without duplicating component', () => {
+    renderConciseIssues(issues);
+
+    expect(screen.getAllByTitle('Long Foo')).toHaveLength(2);
+    expect(screen.getByTitle('Long Bar')).toBeInTheDocument();
+  });
+
+  it('should scroll issue into view when one of the issue is selected', () => {
+    renderConciseIssues(issues, {
+      selected: 'issue2',
+    });
+
+    expect(HTMLElement.prototype.scrollIntoView).toHaveBeenCalledTimes(1);
+  });
+
+  it('should show locations and flows when selected', () => {
+    renderConciseIssues(issues, {
+      selected: 'issue4',
+      selectedFlowIndex: 0,
+    });
+
+    expect(screen.getByText('Flow Foo')).toBeInTheDocument();
+    expect(screen.getByText('loc 1')).toBeInTheDocument();
+  });
+
+  it('should hide locations and flows when not selected', () => {
+    renderConciseIssues(issues, {
+      selected: 'issue2',
+    });
+
+    expect(screen.queryByText('Flow Foo')).not.toBeInTheDocument();
+    expect(screen.queryByText('loc 1')).not.toBeInTheDocument();
+  });
+
+  it('should not render the expand button if below the collapse limit', () => {
+    const { ui } = getPageObject();
+    renderConciseIssues(
+      [
+        ...issues,
+        mockIssue(true, {
+          key: 'custom',
+          message: 'Custom Issue',
+          flows: Array.from({ length: COLLAPSE_LIMIT - 1 }).map(() => [loc]),
+          secondaryLocations: [loc, loc],
+        }),
+      ],
+      {
+        selected: 'custom',
+      }
+    );
+
+    expect(ui.expandBadgesButton.query()).not.toBeInTheDocument();
+  });
+});
+
+describe('interacting', () => {
+  it('should handle back button properly', async () => {
+    const { ui } = getPageObject();
+    const onBackClick = jest.fn();
+    const { override } = renderConciseIssues(
+      issues,
+      {},
+      {
+        displayBackButton: true,
+        loading: true,
+        onBackClick,
+      }
+    );
+
+    // Back button should be shown, but disabled
+    expect(ui.headerBackButton.get()).toBeInTheDocument();
+    await ui.clickBackButton();
+    expect(onBackClick).toHaveBeenCalledTimes(0);
+
+    // Re-render without loading
+    override(
+      issues,
+      {},
+      {
+        displayBackButton: true,
+        loading: false,
+        onBackClick,
+      }
+    );
+
+    // Back button should be shown and enabled
+    expect(ui.headerBackButton.get()).toBeInTheDocument();
+    await ui.clickBackButton();
+    expect(onBackClick).toHaveBeenCalledTimes(1);
+  });
+
+  it('should scroll selected issue into view', () => {
+    const scrollIntoView = jest.fn();
+    window.HTMLElement.prototype.scrollIntoView = scrollIntoView;
+    const { override } = renderConciseIssues(issues, {
+      selected: 'issue2',
+    });
+
+    expect(scrollIntoView).toHaveBeenCalledTimes(1);
+
+    override(issues, {
+      selected: 'issue4',
+    });
+    expect(scrollIntoView).toHaveBeenCalledTimes(2);
+  });
+
+  it('expand button should work correctly', async () => {
+    const { ui } = getPageObject();
+    renderConciseIssues(
+      [
+        ...issues,
+        mockIssue(true, {
+          key: 'custom',
+          message: 'Custom Issue',
+          flows: Array.from({ length: COLLAPSE_LIMIT }).map(() => [loc]),
+          secondaryLocations: [loc, loc],
+        }),
+      ],
+      {
+        selected: 'custom',
+      }
+    );
+
+    expect(ui.expandBadgesButton.get()).toBeInTheDocument();
+    expect(ui.boxLocationFlowBadgeText.getAll()).toHaveLength(COLLAPSE_LIMIT - 1);
+    await ui.clickExpandBadgesButton();
+
+    expect(ui.expandBadgesButton.query()).not.toBeInTheDocument();
+    expect(ui.boxLocationFlowBadgeText.getAll()).toHaveLength(9);
+  });
+
+  it('issue selection should correctly be handled', async () => {
+    const { user } = getPageObject();
+    const onIssueSelect = jest.fn();
+    renderConciseIssues(issues, {
+      onIssueSelect,
+      selected: 'issue2',
+    });
+
+    expect(onIssueSelect).not.toHaveBeenCalled();
+
+    await user.click(screen.getByRole('button', { name: 'Issue 4' }));
+    expect(onIssueSelect).toHaveBeenCalledTimes(1);
+    expect(onIssueSelect).toHaveBeenLastCalledWith('issue4');
+  });
+
+  it('flow selection should correctly be handled', async () => {
+    const { user } = getPageObject();
+    const onFlowSelect = jest.fn();
+    renderConciseIssues(
+      [
+        ...issues,
+        mockIssue(true, {
+          key: 'custom',
+          message: 'Custom Issue',
+          secondaryLocations: [],
+          flows: [[loc], [loc, loc, loc], [loc]],
+        }),
+      ],
+      {
+        onFlowSelect,
+        selected: 'issue4',
+      }
+    );
+
+    expect(onFlowSelect).not.toHaveBeenCalled();
+
+    await user.click(screen.getByText('+3', { exact: false }));
+    expect(onFlowSelect).toHaveBeenCalledTimes(1);
+    expect(onFlowSelect).toHaveBeenLastCalledWith(1);
+  });
+});
+
+function getPageObject() {
+  const selectors = {
+    headerBackButton: byRole('link', { name: 'issues.return_to_list' }),
+    expandBadgesButton: byRole('button', { name: '...' }),
+    boxLocationFlowBadgeText: byText('issue.this_issue_involves_x_code_locations', {
+      exact: false,
+    }),
+  };
+  const user = userEvent.setup();
+  const ui = {
+    ...selectors,
+    async clickBackButton() {
+      await user.click(ui.headerBackButton.get());
+    },
+    async clickExpandBadgesButton() {
+      await user.click(ui.expandBadgesButton.get());
+    },
+  };
+  return { ui, user };
+}
+
+function renderConciseIssues(
+  issues: Issue[],
+  listProps: Partial<ConciseIssuesListProps> = {},
+  headerProps: Partial<ConciseIssuesListHeaderProps> = {}
+) {
+  const wrapper = renderComponent(
+    <>
+      <ConciseIssuesListHeader
+        displayBackButton={false}
+        loading={false}
+        onBackClick={jest.fn()}
+        {...headerProps}
+      />
+      <ConciseIssuesList
+        issues={issues}
+        onFlowSelect={jest.fn()}
+        onIssueSelect={jest.fn()}
+        onLocationSelect={jest.fn()}
+        selected={undefined}
+        selectedFlowIndex={undefined}
+        selectedLocationIndex={undefined}
+        {...listProps}
+      />
+    </>
+  );
+
+  function override(
+    issues: Issue[],
+    listProps: Partial<ConciseIssuesListProps> = {},
+    headerProps: Partial<ConciseIssuesListHeaderProps> = {}
+  ) {
+    wrapper.rerender(
+      <>
+        <ConciseIssuesListHeader
+          displayBackButton={false}
+          loading={false}
+          onBackClick={jest.fn()}
+          {...headerProps}
+        />
+        <ConciseIssuesList
+          issues={issues}
+          onFlowSelect={jest.fn()}
+          onIssueSelect={jest.fn()}
+          onLocationSelect={jest.fn()}
+          selected={undefined}
+          selectedFlowIndex={undefined}
+          selectedLocationIndex={undefined}
+          {...listProps}
+        />
+      </>
+    );
+  }
+
+  return { ...wrapper, override };
+}
diff --git a/server/sonar-web/src/main/js/apps/issues/conciseIssuesList/__tests__/ConciseIssuesList-test.tsx b/server/sonar-web/src/main/js/apps/issues/conciseIssuesList/__tests__/ConciseIssuesList-test.tsx
deleted file mode 100644 (file)
index 41c5ca6..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2023 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-import { shallow } from 'enzyme';
-import * as React from 'react';
-import { Issue } from '../../../../types/types';
-import ConciseIssuesList from '../ConciseIssuesList';
-
-it('should render', () => {
-  const issues = [{ key: 'foo' }, { key: 'bar' }] as Issue[];
-  expect(
-    shallow(
-      <ConciseIssuesList
-        issues={issues}
-        onFlowSelect={jest.fn()}
-        onIssueSelect={jest.fn()}
-        onLocationSelect={jest.fn()}
-        selected={undefined}
-        selectedFlowIndex={undefined}
-        selectedLocationIndex={undefined}
-      />
-    )
-  ).toMatchSnapshot();
-});
diff --git a/server/sonar-web/src/main/js/apps/issues/conciseIssuesList/__tests__/ConciseIssuesListHeader-test.tsx b/server/sonar-web/src/main/js/apps/issues/conciseIssuesList/__tests__/ConciseIssuesListHeader-test.tsx
deleted file mode 100644 (file)
index 74a8b1d..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2023 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-import { shallow } from 'enzyme';
-import * as React from 'react';
-import ConciseIssuesListHeader, { ConciseIssuesListHeaderProps } from '../ConciseIssuesListHeader';
-
-it('should render correctly', () => {
-  expect(shallowRender()).toMatchSnapshot('default');
-  expect(shallowRender({ loading: true })).toMatchSnapshot('loading');
-  expect(shallowRender({ displayBackButton: true })).toMatchSnapshot('with back button');
-});
-
-function shallowRender(props: Partial<ConciseIssuesListHeaderProps> = {}) {
-  return shallow<ConciseIssuesListHeaderProps>(
-    <ConciseIssuesListHeader
-      displayBackButton={false}
-      loading={false}
-      onBackClick={jest.fn()}
-      {...props}
-    />
-  );
-}
diff --git a/server/sonar-web/src/main/js/apps/issues/conciseIssuesList/__tests__/__snapshots__/ConciseIssue-test.tsx.snap b/server/sonar-web/src/main/js/apps/issues/conciseIssuesList/__tests__/__snapshots__/ConciseIssue-test.tsx.snap
deleted file mode 100644 (file)
index 310f39d..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`should render 1`] = `
-<Fragment>
-  <li>
-    <ConciseIssueComponent
-      path="src/file.js"
-    />
-  </li>
-  <li>
-    <ConciseIssueBox
-      issue={
-        {
-          "actions": [],
-          "component": "",
-          "componentLongName": "src/file.js",
-          "componentQualifier": "",
-          "componentUuid": "",
-          "creationDate": "",
-          "flows": [],
-          "flowsWithType": [],
-          "key": "",
-          "message": "",
-          "project": "",
-          "projectKey": "",
-          "projectName": "",
-          "rule": "",
-          "ruleName": "",
-          "secondaryLocations": [],
-          "severity": "",
-          "status": "",
-          "transitions": [],
-          "type": "BUG",
-        }
-      }
-      onClick={[MockFunction]}
-      onFlowSelect={[MockFunction]}
-      onLocationSelect={[MockFunction]}
-      scroll={[MockFunction]}
-      selected={false}
-    />
-  </li>
-</Fragment>
-`;
diff --git a/server/sonar-web/src/main/js/apps/issues/conciseIssuesList/__tests__/__snapshots__/ConciseIssueBox-test.tsx.snap b/server/sonar-web/src/main/js/apps/issues/conciseIssuesList/__tests__/__snapshots__/ConciseIssueBox-test.tsx.snap
deleted file mode 100644 (file)
index 051deee..0000000
+++ /dev/null
@@ -1,220 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`should render correctly 1`] = `
-<div
-  className="concise-issue-box clearfix"
-  onClick={[Function]}
->
-  <ButtonPlain
-    aria-current={false}
-    className="concise-issue-box-message"
-    innerRef={[Function]}
-    onClick={[Function]}
-  >
-    <IssueMessageHighlighting
-      message="Reduce the number of conditional operators (4) used in the expression"
-    />
-  </ButtonPlain>
-  <div
-    className="concise-issue-box-attributes"
-  >
-    <TypeHelper
-      className="display-block little-spacer-right"
-      type="BUG"
-    />
-    <ConciseIssueLocations
-      issue={
-        {
-          "actions": [],
-          "component": "main.js",
-          "componentEnabled": true,
-          "componentLongName": "main.js",
-          "componentQualifier": "FIL",
-          "componentUuid": "foo1234",
-          "creationDate": "2017-03-01T09:36:01+0100",
-          "flows": [],
-          "flowsWithType": [],
-          "key": "AVsae-CQS-9G3txfbFN2",
-          "line": 25,
-          "message": "Reduce the number of conditional operators (4) used in the expression",
-          "project": "myproject",
-          "projectKey": "foo",
-          "projectName": "Foo",
-          "rule": "javascript:S1067",
-          "ruleName": "foo",
-          "secondaryLocations": [],
-          "severity": "MAJOR",
-          "status": "OPEN",
-          "textRange": {
-            "endLine": 26,
-            "endOffset": 15,
-            "startLine": 25,
-            "startOffset": 0,
-          },
-          "transitions": [],
-          "type": "BUG",
-        }
-      }
-      onFlowSelect={[MockFunction]}
-      selectedFlowIndex={0}
-    />
-  </div>
-</div>
-`;
-
-exports[`should render correctly 2`] = `
-<div
-  className="concise-issue-box clearfix selected"
->
-  <ButtonPlain
-    aria-current={true}
-    className="concise-issue-box-message"
-    innerRef={[Function]}
-    onClick={[Function]}
-  >
-    <IssueMessageHighlighting
-      message="Reduce the number of conditional operators (4) used in the expression"
-    />
-  </ButtonPlain>
-  <div
-    className="concise-issue-box-attributes"
-  >
-    <TypeHelper
-      className="display-block little-spacer-right"
-      type="BUG"
-    />
-    <ConciseIssueLocations
-      issue={
-        {
-          "actions": [],
-          "component": "main.js",
-          "componentEnabled": true,
-          "componentLongName": "main.js",
-          "componentQualifier": "FIL",
-          "componentUuid": "foo1234",
-          "creationDate": "2017-03-01T09:36:01+0100",
-          "flows": [
-            [
-              {
-                "component": "main.js",
-                "textRange": {
-                  "endLine": 2,
-                  "endOffset": 2,
-                  "startLine": 1,
-                  "startOffset": 1,
-                },
-              },
-              {
-                "component": "main.js",
-                "textRange": {
-                  "endLine": 2,
-                  "endOffset": 2,
-                  "startLine": 1,
-                  "startOffset": 1,
-                },
-              },
-              {
-                "component": "main.js",
-                "textRange": {
-                  "endLine": 2,
-                  "endOffset": 2,
-                  "startLine": 1,
-                  "startOffset": 1,
-                },
-              },
-            ],
-            [
-              {
-                "component": "main.js",
-                "textRange": {
-                  "endLine": 2,
-                  "endOffset": 2,
-                  "startLine": 1,
-                  "startOffset": 1,
-                },
-              },
-              {
-                "component": "main.js",
-                "textRange": {
-                  "endLine": 2,
-                  "endOffset": 2,
-                  "startLine": 1,
-                  "startOffset": 1,
-                },
-              },
-            ],
-          ],
-          "flowsWithType": [],
-          "key": "AVsae-CQS-9G3txfbFN2",
-          "line": 25,
-          "message": "Reduce the number of conditional operators (4) used in the expression",
-          "project": "myproject",
-          "projectKey": "foo",
-          "projectName": "Foo",
-          "rule": "javascript:S1067",
-          "ruleName": "foo",
-          "secondaryLocations": [
-            {
-              "component": "main.js",
-              "textRange": {
-                "endLine": 2,
-                "endOffset": 2,
-                "startLine": 1,
-                "startOffset": 1,
-              },
-            },
-            {
-              "component": "main.js",
-              "textRange": {
-                "endLine": 2,
-                "endOffset": 2,
-                "startLine": 1,
-                "startOffset": 1,
-              },
-            },
-          ],
-          "severity": "MAJOR",
-          "status": "OPEN",
-          "textRange": {
-            "endLine": 26,
-            "endOffset": 15,
-            "startLine": 25,
-            "startOffset": 0,
-          },
-          "transitions": [],
-          "type": "BUG",
-        }
-      }
-      onFlowSelect={[MockFunction]}
-      selectedFlowIndex={0}
-    />
-  </div>
-  <LocationsList
-    componentKey="main.js"
-    locations={
-      [
-        {
-          "component": "main.js",
-          "textRange": {
-            "endLine": 2,
-            "endOffset": 2,
-            "startLine": 1,
-            "startOffset": 1,
-          },
-        },
-        {
-          "component": "main.js",
-          "textRange": {
-            "endLine": 2,
-            "endOffset": 2,
-            "startLine": 1,
-            "startOffset": 1,
-          },
-        },
-      ]
-    }
-    onLocationSelect={[MockFunction]}
-    selectedLocationIndex={0}
-  />
-</div>
-`;
diff --git a/server/sonar-web/src/main/js/apps/issues/conciseIssuesList/__tests__/__snapshots__/ConciseIssueComponent-test.tsx.snap b/server/sonar-web/src/main/js/apps/issues/conciseIssuesList/__tests__/__snapshots__/ConciseIssueComponent-test.tsx.snap
deleted file mode 100644 (file)
index a21ab80..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`should render 1`] = `
-<div
-  className="concise-issue-component text-ellipsis note"
-  title="src/app/folder/sub-folder/long-folder/name/app.js"
->
-  <bdi>
-    src/app/folder/sub-folder/long-folder/name/app.js
-  </bdi>
-</div>
-`;
diff --git a/server/sonar-web/src/main/js/apps/issues/conciseIssuesList/__tests__/__snapshots__/ConciseIssueLocationBadge-test.tsx.snap b/server/sonar-web/src/main/js/apps/issues/conciseIssuesList/__tests__/__snapshots__/ConciseIssueLocationBadge-test.tsx.snap
deleted file mode 100644 (file)
index b0ccd9b..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`should render 1`] = `
-<Tooltip
-  mouseEnterDelay={0.5}
-  overlay="issue.this_issue_involves_x_code_locations.7"
->
-  <LocationIndex
-    selected={false}
-  >
-    +
-    7
-  </LocationIndex>
-</Tooltip>
-`;
diff --git a/server/sonar-web/src/main/js/apps/issues/conciseIssuesList/__tests__/__snapshots__/ConciseIssueLocations-test.tsx.snap b/server/sonar-web/src/main/js/apps/issues/conciseIssuesList/__tests__/__snapshots__/ConciseIssueLocations-test.tsx.snap
deleted file mode 100644 (file)
index be3b306..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`should render one flow 1`] = `
-<ConciseIssueLocationBadge
-  count={3}
-  key="0"
-  onClick={[Function]}
-  selected={false}
-/>
-`;
-
-exports[`should render secondary locations 1`] = `
-<ConciseIssueLocationBadge
-  count={3}
-  key="-1"
-  selected={true}
-/>
-`;
-
-exports[`should render several flows 1`] = `
-[
-  <ConciseIssueLocationBadge
-    count={3}
-    key="0"
-    onClick={[Function]}
-    selected={false}
-  />,
-  <ConciseIssueLocationBadge
-    count={2}
-    key="1"
-    onClick={[Function]}
-    selected={false}
-  />,
-  <ConciseIssueLocationBadge
-    count={3}
-    key="2"
-    onClick={[Function]}
-    selected={false}
-  />,
-]
-`;
diff --git a/server/sonar-web/src/main/js/apps/issues/conciseIssuesList/__tests__/__snapshots__/ConciseIssuesList-test.tsx.snap b/server/sonar-web/src/main/js/apps/issues/conciseIssuesList/__tests__/__snapshots__/ConciseIssuesList-test.tsx.snap
deleted file mode 100644 (file)
index d9518d3..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`should render 1`] = `
-<ul>
-  <ConciseIssue
-    issue={
-      {
-        "key": "foo",
-      }
-    }
-    key="foo"
-    onFlowSelect={[MockFunction]}
-    onLocationSelect={[MockFunction]}
-    onSelect={[MockFunction]}
-    scroll={[Function]}
-    selected={false}
-  />
-  <ConciseIssue
-    issue={
-      {
-        "key": "bar",
-      }
-    }
-    key="bar"
-    onFlowSelect={[MockFunction]}
-    onLocationSelect={[MockFunction]}
-    onSelect={[MockFunction]}
-    previousIssue={
-      {
-        "key": "foo",
-      }
-    }
-    scroll={[Function]}
-    selected={false}
-  />
-</ul>
-`;
diff --git a/server/sonar-web/src/main/js/apps/issues/conciseIssuesList/__tests__/__snapshots__/ConciseIssuesListHeader-test.tsx.snap b/server/sonar-web/src/main/js/apps/issues/conciseIssuesList/__tests__/__snapshots__/ConciseIssuesListHeader-test.tsx.snap
deleted file mode 100644 (file)
index 3887851..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`should render correctly: default 1`] = `
-<header
-  className="layout-page-header-panel concise-issues-list-header"
->
-  <div
-    className="layout-page-header-panel-inner concise-issues-list-header-inner display-flex-center display-flex-space-between"
-  >
-    <PageShortcutsTooltip
-      leftLabel="issues.to_navigate_back"
-      metaModifierLabel="issues.to_navigate_issue_locations"
-      upAndDownLabel="issues.to_select_issues"
-    />
-  </div>
-</header>
-`;
-
-exports[`should render correctly: loading 1`] = `
-<header
-  className="layout-page-header-panel concise-issues-list-header"
->
-  <div
-    className="layout-page-header-panel-inner concise-issues-list-header-inner display-flex-center display-flex-space-between"
-  >
-    <PageShortcutsTooltip
-      leftLabel="issues.to_navigate_back"
-      metaModifierLabel="issues.to_navigate_issue_locations"
-      upAndDownLabel="issues.to_select_issues"
-    />
-    <i
-      className="spinner"
-    />
-  </div>
-</header>
-`;
-
-exports[`should render correctly: with back button 1`] = `
-<header
-  className="layout-page-header-panel concise-issues-list-header"
->
-  <div
-    className="layout-page-header-panel-inner concise-issues-list-header-inner display-flex-center display-flex-space-between"
-  >
-    <BackButton
-      disabled={false}
-      onClick={[MockFunction]}
-    />
-    <PageShortcutsTooltip
-      leftLabel="issues.to_navigate_back"
-      metaModifierLabel="issues.to_navigate_issue_locations"
-      upAndDownLabel="issues.to_select_issues"
-    />
-  </div>
-</header>
-`;
index eab7d9b809bc67d0d81e42d1096c760ef408b930..dc0809f441333eaec7ba50192bd1990d68fb6a53 100644 (file)
@@ -314,7 +314,7 @@ export function mockRawIssue(withLocations = false, overrides: Partial<RawIssue>
   };
 }
 
-export function mockIssue(withLocations = false, overrides: Partial<Issue> = {}) {
+export function mockIssue(withLocations = false, overrides: Partial<Issue> = {}): Issue {
   const issue: Issue = {
     actions: [],
     component: 'main.js',