]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-20254 Migrate app-level component tests to RTL
authorJay <jeremy.davis@sonarsource.com>
Thu, 31 Aug 2023 13:52:25 +0000 (15:52 +0200)
committersonartech <sonartech@sonarsource.com>
Thu, 31 Aug 2023 20:02:57 +0000 (20:02 +0000)
13 files changed:
server/sonar-web/src/main/js/app/components/AdminContainer.tsx
server/sonar-web/src/main/js/app/components/__tests__/AdminContainer-test.tsx
server/sonar-web/src/main/js/app/components/__tests__/App-test.tsx
server/sonar-web/src/main/js/app/components/__tests__/KeyboardShortcutsModal-test.tsx
server/sonar-web/src/main/js/app/components/__tests__/MigrationContainer-test.tsx
server/sonar-web/src/main/js/app/components/__tests__/PageTracker-test.tsx
server/sonar-web/src/main/js/app/components/__tests__/ProjectAdminContainer-test.tsx
server/sonar-web/src/main/js/app/components/__tests__/__snapshots__/AdminContainer-test.tsx.snap [deleted file]
server/sonar-web/src/main/js/app/components/__tests__/__snapshots__/App-test.tsx.snap [deleted file]
server/sonar-web/src/main/js/app/components/__tests__/__snapshots__/KeyboardShortcutsModal-test.tsx.snap [deleted file]
server/sonar-web/src/main/js/app/components/__tests__/__snapshots__/MigrationContainer-test.tsx.snap [deleted file]
server/sonar-web/src/main/js/app/components/__tests__/__snapshots__/PageTracker-test.tsx.snap [deleted file]
server/sonar-web/src/main/js/app/components/__tests__/__snapshots__/ProjectAdminContainer-test.tsx.snap [deleted file]

index 80db793918413d4cfedb243c7c593de71d148775..ab8cfaa98680da8876c5256313b6f7957496bce4 100644 (file)
@@ -103,7 +103,7 @@ export class AdminContainer extends React.PureComponent<AdminContainerProps, Sta
       ({ status }) => {
         if (this.mounted) {
           this.setState({ systemStatus: status });
-          document.location.reload();
+          window.location.reload();
         }
       },
       () => {}
index cd238b028f4318f7a70e109a979ebfa514b2b256..143cf6af20f0e420ce4e8fbfc9991a47a373c783 100644 (file)
  * 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 userEvent from '@testing-library/user-event';
 import * as React from 'react';
+import { Route, useOutletContext } from 'react-router-dom';
+import { getSystemStatus, waitSystemUPStatus } from '../../../api/system';
 import { mockAppState } from '../../../helpers/testMocks';
+import { renderAppRoutes } from '../../../helpers/testReactTestingUtils';
+import { byLabelText, byRole, byText } from '../../../helpers/testSelector';
+import { AdminPagesContext } from '../../../types/admin';
 import { AdminContainer, AdminContainerProps } from '../AdminContainer';
+import AdminContext from '../AdminContext';
+
+jest.mock('../../../api/navigation', () => ({
+  getSettingsNavigation: jest
+    .fn()
+    .mockResolvedValue({ extensions: [{ key: 'asd', name: 'asdf' }] }),
+}));
 
 jest.mock('../../../api/plugins', () => ({
-  getSettingsNavigation: jest.fn().mockResolvedValue({}),
-  getPendingPlugins: jest.fn().mockResolvedValue({}),
+  getPendingPlugins: jest.fn().mockResolvedValue({
+    installing: [{ key: '1', name: 'installing' }],
+    updating: [
+      { key: '2', name: 'updating' },
+      { key: '2b', name: 'update this too' },
+    ],
+    removing: [{ key: '3', name: 'removing' }],
+  }),
 }));
 
 jest.mock('../../../api/system', () => ({
-  getSystemStatus: jest.fn().mockResolvedValue({}),
+  getSystemStatus: jest.fn().mockResolvedValue({ status: 'DOWN' }),
+  waitSystemUPStatus: jest.fn().mockResolvedValue({ status: 'RESTARTING' }),
 }));
 
-it('should render correctly', () => {
-  const wrapper = shallowRender();
-  expect(wrapper).toMatchSnapshot();
+const originalLocation = window.location;
+const reload = jest.fn();
+
+beforeAll(() => {
+  Object.defineProperty(window, 'location', {
+    writable: true,
+    value: { reload },
+  });
 });
 
-function shallowRender(props: Partial<AdminContainerProps> = {}) {
-  return shallow(
-    <AdminContainer
-      appState={mockAppState({
-        canAdmin: true,
-      })}
-      {...props}
+afterAll(() => {
+  Object.defineProperty(window, 'location', {
+    writable: true,
+    value: originalLocation,
+  });
+});
+
+it('should render nav and provide context to children', async () => {
+  const user = userEvent.setup();
+  renderAdminContainer();
+
+  expect(await ui.navHeader.find()).toBeInTheDocument();
+
+  expect(ui.pagesList.byRole('listitem').getAll()).toHaveLength(1);
+  expect(ui.pagesList.byText('asdf').get()).toBeInTheDocument();
+
+  expect(ui.pluginsInstallingList.byRole('listitem').getAll()).toHaveLength(1);
+  expect(ui.pluginsInstallingList.byText('installing').get()).toBeInTheDocument();
+
+  expect(ui.pluginsUpdatingList.byRole('listitem').getAll()).toHaveLength(2);
+  expect(ui.pluginsUpdatingList.byText('updating').get()).toBeInTheDocument();
+  expect(ui.pluginsUpdatingList.byText('update this too').get()).toBeInTheDocument();
+
+  expect(ui.pluginsRemovingList.byRole('listitem').getAll()).toHaveLength(1);
+  expect(ui.pluginsRemovingList.byText('removing').get()).toBeInTheDocument();
+
+  expect(byText('DOWN').get()).toBeInTheDocument();
+
+  // Trigger a status update
+  jest.mocked(getSystemStatus).mockResolvedValueOnce({ id: '', version: '', status: 'RESTARTING' });
+  jest.mocked(waitSystemUPStatus).mockResolvedValueOnce({ id: '', version: '', status: 'UP' });
+  await user.click(ui.fetchStatusButton.get());
+
+  expect(await byText('UP').find()).toBeInTheDocument();
+  expect(reload).toHaveBeenCalled();
+});
+
+function renderAdminContainer(props: Partial<AdminContainerProps> = {}) {
+  return renderAppRoutes('admin', () => (
+    <Route
+      path="admin"
+      element={
+        <AdminContainer
+          appState={mockAppState({
+            canAdmin: true,
+          })}
+          {...props}
+        />
+      }
     >
-      <div />
-    </AdminContainer>
+      <Route index element={<TestChildComponent />} />
+    </Route>
+  ));
+}
+
+function TestChildComponent() {
+  const { adminPages } = useOutletContext<AdminPagesContext>();
+
+  const { fetchPendingPlugins, fetchSystemStatus, pendingPlugins, systemStatus } =
+    React.useContext(AdminContext);
+
+  return (
+    <div>
+      <ul aria-label="pages">
+        {adminPages.map((page) => (
+          <li key={page.key}>{page.name}</li>
+        ))}
+      </ul>
+
+      <ul aria-label="plugins - installing">
+        {pendingPlugins.installing.map((p) => (
+          <li key={p.key}>{p.name}</li>
+        ))}
+      </ul>
+      <ul aria-label="plugins - removing">
+        {pendingPlugins.removing.map((p) => (
+          <li key={p.key}>{p.name}</li>
+        ))}
+      </ul>
+      <ul aria-label="plugins - updating">
+        {pendingPlugins.updating.map((p) => (
+          <li key={p.key}>{p.name}</li>
+        ))}
+      </ul>
+      <button type="button" onClick={fetchPendingPlugins}>
+        fetch plugins
+      </button>
+
+      {systemStatus}
+      <button type="button" onClick={fetchSystemStatus}>
+        fetch status
+      </button>
+    </div>
   );
 }
+
+const ui = {
+  navHeader: byRole('heading', { name: 'layout.settings' }),
+  pagesList: byLabelText('pages'),
+  pluginsInstallingList: byLabelText('plugins - installing'),
+  pluginsUpdatingList: byLabelText('plugins - updating'),
+  pluginsRemovingList: byLabelText('plugins - removing'),
+
+  fetchPluginsButton: byRole('button', { name: 'fetch plugins' }),
+  fetchStatusButton: byRole('button', { name: 'fetch status' }),
+};
index a4726fa085b9bdf1456dd22ee4c5533086e49e6c..e8f00fce9f9ae9f74c54ea7793371b5f26c22d45 100644 (file)
  * 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 { mockAppState } from '../../../helpers/testMocks';
+import { renderComponent } from '../../../helpers/testReactTestingUtils';
 import { App } from '../App';
 
-it('should render correctly', () => {
-  expect(shallowRender()).toMatchSnapshot('default');
-  expect(
-    shallowRender({
-      appState: mockAppState({
-        settings: {
-          'sonar.lf.enableGravatar': 'true',
-          'sonar.lf.gravatarServerUrl': 'http://example.com',
-        },
-      }),
-    })
-  ).toMatchSnapshot('with gravatar');
+it('should render correctly with gravatar', () => {
+  renderApp({
+    appState: mockAppState({
+      settings: {
+        'sonar.lf.enableGravatar': 'true',
+        'sonar.lf.gravatarServerUrl': 'http://example.com',
+      },
+    }),
+  });
+
+  // eslint-disable-next-line testing-library/no-node-access
+  expect(document.head.querySelector('link')).toHaveAttribute('href', 'http://example.com');
 });
 
 it('should correctly set the scrollbar width as a custom property', () => {
-  shallowRender();
+  renderApp();
   expect(document.body.style.getPropertyValue('--sbw')).toBe('0px');
 });
 
-function shallowRender(props: Partial<App['props']> = {}) {
-  return shallow<App>(
+function renderApp(props: Partial<App['props']> = {}) {
+  return renderComponent(
     <App
       appState={mockAppState({
         settings: {
index 9fad44d2f9ca019d6879323d5b0f585910e2320f..0ef752c29be4eccbb3e87d025b1548d52459e9bc 100644 (file)
  * 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 { act } from '@testing-library/react';
+import userEvent from '@testing-library/user-event';
 import React from 'react';
-import Modal from '../../../components/controls/Modal';
-import { mockEvent } from '../../../helpers/testUtils';
+import { renderComponent } from '../../../helpers/testReactTestingUtils';
+import { byRole } from '../../../helpers/testSelector';
 import KeyboardShortcutsModal from '../KeyboardShortcutsModal';
 
-jest.mock('react', () => {
-  let close: () => void;
-  return {
-    ...jest.requireActual('react'),
-    useEffect: jest.fn().mockImplementation((f) => {
-      close = f();
-    }),
-    clean: () => {
-      close();
-    },
-  };
-});
+it('should render correctly', async () => {
+  const user = userEvent.setup();
+  renderKeyboardShortcutsModal();
 
-afterEach(() => {
-  if ((React as any).clean as () => void) {
-    (React as any).clean();
-  }
-});
+  expect(ui.modalTitle.query()).not.toBeInTheDocument();
 
-it('should render correctly', () => {
-  const wrapper = shallowRender();
-  expect(wrapper).toMatchSnapshot('hidden');
+  await act(() => user.keyboard('?'));
 
-  document.dispatchEvent(new KeyboardEvent('keydown', { key: '?' }));
+  expect(ui.modalTitle.get()).toBeInTheDocument();
 
-  expect(wrapper).toMatchSnapshot('visible');
-});
+  await user.click(ui.closeButton.get());
 
-it('should close correctly', () => {
-  const wrapper = shallowRender();
-  document.dispatchEvent(new KeyboardEvent('keydown', { key: '?' }));
+  expect(ui.modalTitle.query()).not.toBeInTheDocument();
+});
 
-  wrapper.find(Modal).props().onRequestClose!(mockEvent());
+it('should ignore other keydownes', async () => {
+  const user = userEvent.setup();
+  renderKeyboardShortcutsModal();
 
-  expect(wrapper.type()).toBeNull();
-});
+  await act(() => user.keyboard('!'));
 
-it('should ignore other keydownes', () => {
-  const wrapper = shallowRender();
-  document.dispatchEvent(new KeyboardEvent('keydown', { key: '!' }));
-  expect(wrapper.type()).toBeNull();
+  expect(ui.modalTitle.query()).not.toBeInTheDocument();
 });
 
-it.each([['input'], ['select'], ['textarea']])('should ignore events on a %s', (type) => {
-  const wrapper = shallowRender();
-
-  const fakeEvent = new KeyboardEvent('keydown', { key: '!' });
+it('should ignore events in an input', async () => {
+  const user = userEvent.setup();
 
-  Object.defineProperty(fakeEvent, 'target', {
-    value: document.createElement(type),
-  });
+  renderKeyboardShortcutsModal();
 
-  document.dispatchEvent(fakeEvent);
+  await user.click(ui.textInput.get());
+  await act(() => user.keyboard('?'));
 
-  expect(wrapper.type()).toBeNull();
+  expect(ui.modalTitle.query()).not.toBeInTheDocument();
 });
 
-function shallowRender() {
-  return shallow(<KeyboardShortcutsModal />);
+function renderKeyboardShortcutsModal() {
+  return renderComponent(
+    <>
+      <KeyboardShortcutsModal />
+      <input type="text" />
+    </>
+  );
 }
+
+const ui = {
+  modalTitle: byRole('heading', { name: 'keyboard_shortcuts.title' }),
+  closeButton: byRole('button', { name: 'close' }),
+
+  textInput: byRole('textbox'),
+};
index affc20629eaa328581c8a0d1cec1c2d6dbd0db13..d04c07c03f28dc36abb99f5b44dcdd98d917c35c 100644 (file)
  * 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 { Route } from 'react-router-dom';
 import { getSystemStatus } from '../../../helpers/system';
+import { renderAppRoutes } from '../../../helpers/testReactTestingUtils';
+import { byText } from '../../../helpers/testSelector';
 import MigrationContainer from '../MigrationContainer';
 
 jest.mock('../../../helpers/system', () => ({
@@ -49,14 +51,26 @@ afterAll(() => {
 
 it('should render correctly if system is up', () => {
   (getSystemStatus as jest.Mock).mockReturnValueOnce('UP');
-  expect(shallowRender()).toMatchSnapshot();
+
+  renderMigrationContainer();
+
+  expect(byText('children').get()).toBeInTheDocument();
 });
 
 it('should render correctly if system is starting', () => {
   (getSystemStatus as jest.Mock).mockReturnValueOnce('STARTING');
-  expect(shallowRender()).toMatchSnapshot();
+
+  renderMigrationContainer();
+
+  expect(
+    byText('/maintenance?return_to=%2Fprojects%3Fquery%3Dtoto%23hash').get()
+  ).toBeInTheDocument();
 });
 
-function shallowRender() {
-  return shallow(<MigrationContainer />);
+function renderMigrationContainer() {
+  return renderAppRoutes('/', () => (
+    <Route element={<MigrationContainer />}>
+      <Route index element={<div>children</div>} />
+    </Route>
+  ));
 }
index 10504a10e74c4cdad9fd7f54322760f08f3f637f..f59f12f53bb46c386ee18c4eb68ad811ab22ff4a 100644 (file)
  * 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 userEvent from '@testing-library/user-event';
 import * as React from 'react';
+import { Link } from 'react-router-dom';
 import { installScript } from '../../../helpers/extensions';
 import { getWebAnalyticsPageHandlerFromCache } from '../../../helpers/extensionsHandler';
-import { mockAppState, mockLocation } from '../../../helpers/testMocks';
-import { PageTracker } from '../PageTracker';
+import { mockAppState } from '../../../helpers/testMocks';
+import { renderComponent } from '../../../helpers/testReactTestingUtils';
+import { byRole } from '../../../helpers/testSelector';
+import PageTracker from '../PageTracker';
 
 jest.mock('../../../helpers/extensions', () => ({
   installScript: jest.fn().mockResolvedValue({}),
@@ -43,28 +46,41 @@ afterEach(() => {
 });
 
 it('should not trigger if no analytics system is given', () => {
-  const wrapper = shallowRender();
-  expect(wrapper).toMatchSnapshot();
+  renderPageTracker();
+
   expect(installScript).not.toHaveBeenCalled();
 });
 
-it('should work for WebAnalytics plugin', () => {
+it('should work for WebAnalytics plugin', async () => {
+  const user = userEvent.setup({ delay: null });
   const pageChange = jest.fn();
   const webAnalyticsJsPath = '/static/pluginKey/web_analytics.js';
-  const wrapper = shallowRender({ appState: mockAppState({ webAnalyticsJsPath }) });
+  renderPageTracker(mockAppState({ webAnalyticsJsPath }));
 
-  expect(wrapper).toMatchSnapshot();
-  expect(wrapper.find('Helmet').prop('onChangeClientState')).toBe(wrapper.instance().trackPage);
   expect(installScript).toHaveBeenCalledWith(webAnalyticsJsPath, 'head');
-  (getWebAnalyticsPageHandlerFromCache as jest.Mock).mockReturnValueOnce(pageChange);
 
-  wrapper.instance().trackPage();
+  jest.mocked(getWebAnalyticsPageHandlerFromCache).mockClear().mockReturnValueOnce(pageChange);
+
+  // trigger trackPage
+  await user.click(byRole('link').get());
+
   jest.runAllTimers();
-  expect(pageChange).toHaveBeenCalledWith('/path');
+  expect(pageChange).toHaveBeenCalledWith('/newpath');
 });
 
-function shallowRender(props: Partial<PageTracker['props']> = {}) {
-  return shallow<PageTracker>(
-    <PageTracker appState={mockAppState()} location={mockLocation()} {...props} />
+function renderPageTracker(appState = mockAppState()) {
+  return renderComponent(<WrappingComponent />, '', { appState });
+}
+
+function WrappingComponent() {
+  const [metatag, setmetatag] = React.useState<React.ReactNode>(null);
+
+  return (
+    <>
+      <PageTracker>{metatag}</PageTracker>
+      <Link to="newpath" onClick={() => setmetatag(<meta name="toto" />)}>
+        trigger change
+      </Link>
+    </>
   );
 }
index d3ed20ab64f710e87aef30f3a0f9a9e354bee19f..b3acd7522840437d8281bd0b4db2a999bffc2f7a 100644 (file)
  * along with this program; if not, write to the Free Software Foundation,
  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  */
-import { mount, shallow } from 'enzyme';
 import * as React from 'react';
+import { Route } from 'react-router-dom';
 import handleRequiredAuthorization from '../../../app/utils/handleRequiredAuthorization';
 import { mockComponent } from '../../../helpers/mocks/component';
+import { renderAppRoutes } from '../../../helpers/testReactTestingUtils';
+import { byText } from '../../../helpers/testSelector';
 import { ProjectAdminContainer } from '../ProjectAdminContainer';
 
 jest.mock('../../utils/handleRequiredAuthorization', () => {
@@ -28,30 +30,33 @@ jest.mock('../../utils/handleRequiredAuthorization', () => {
 });
 
 it('should render correctly', () => {
-  expect(shallowRender()).toMatchSnapshot();
+  renderProjectAdminContainer();
+
+  expect(byText('children').get()).toBeInTheDocument();
 });
 
 it('should redirect for authorization if needed', () => {
   jest.useFakeTimers();
-  mountRender({ component: mockComponent({ configuration: { showSettings: false } }) });
+  renderProjectAdminContainer({
+    component: mockComponent({ configuration: { showSettings: false } }),
+  });
   jest.runAllTimers();
   expect(handleRequiredAuthorization).toHaveBeenCalled();
   jest.useRealTimers();
 });
 
-function mountRender(props: Partial<ProjectAdminContainer['props']> = {}) {
-  return mount(createComponent(props));
-}
-
-function shallowRender(props: Partial<ProjectAdminContainer['props']> = {}) {
-  return shallow(createComponent(props));
-}
-
-function createComponent(props: Partial<ProjectAdminContainer['props']> = {}) {
-  return (
-    <ProjectAdminContainer
-      component={mockComponent({ configuration: { showSettings: true } })}
-      {...props}
-    />
-  );
+function renderProjectAdminContainer(props: Partial<ProjectAdminContainer['props']> = {}) {
+  return renderAppRoutes('project/settings', () => (
+    <Route
+      path="project/settings"
+      element={
+        <ProjectAdminContainer
+          component={mockComponent({ configuration: { showSettings: true } })}
+          {...props}
+        />
+      }
+    >
+      <Route index element={<div>children</div>} />
+    </Route>
+  ));
 }
diff --git a/server/sonar-web/src/main/js/app/components/__tests__/__snapshots__/AdminContainer-test.tsx.snap b/server/sonar-web/src/main/js/app/components/__tests__/__snapshots__/AdminContainer-test.tsx.snap
deleted file mode 100644 (file)
index 631a82f..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`should render correctly 1`] = `
-<Fragment>
-  <Helmet
-    defer={false}
-    encodeSpecialCharacters={true}
-    prioritizeSeoTags={false}
-    titleTemplate="page_title.template.with_category.layout.settings"
-  />
-  <WithLocation
-    extensions={[]}
-    fetchPendingPlugins={[Function]}
-    fetchSystemStatus={[Function]}
-    pendingPlugins={
-      {
-        "installing": [],
-        "removing": [],
-        "updating": [],
-      }
-    }
-    systemStatus="UP"
-  />
-  <ContextProvider
-    value={
-      {
-        "fetchPendingPlugins": [Function],
-        "fetchSystemStatus": [Function],
-        "pendingPlugins": {
-          "installing": [],
-          "removing": [],
-          "updating": [],
-        },
-        "systemStatus": "UP",
-      }
-    }
-  >
-    <Outlet
-      context={
-        {
-          "adminPages": [],
-        }
-      }
-    />
-  </ContextProvider>
-</Fragment>
-`;
diff --git a/server/sonar-web/src/main/js/app/components/__tests__/__snapshots__/App-test.tsx.snap b/server/sonar-web/src/main/js/app/components/__tests__/__snapshots__/App-test.tsx.snap
deleted file mode 100644 (file)
index 1937a13..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`should render correctly: default 1`] = `
-<Fragment>
-  <withRouter(withAppStateContext(PageTracker)) />
-  <Outlet />
-  <KeyboardShortcutsModal />
-</Fragment>
-`;
-
-exports[`should render correctly: with gravatar 1`] = `
-<Fragment>
-  <withRouter(withAppStateContext(PageTracker))>
-    <link
-      href="http://example.com"
-      rel="preconnect"
-    />
-  </withRouter(withAppStateContext(PageTracker))>
-  <Outlet />
-  <KeyboardShortcutsModal />
-</Fragment>
-`;
diff --git a/server/sonar-web/src/main/js/app/components/__tests__/__snapshots__/KeyboardShortcutsModal-test.tsx.snap b/server/sonar-web/src/main/js/app/components/__tests__/__snapshots__/KeyboardShortcutsModal-test.tsx.snap
deleted file mode 100644 (file)
index f637098..0000000
+++ /dev/null
@@ -1,583 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`should render correctly: hidden 1`] = `""`;
-
-exports[`should render correctly: visible 1`] = `
-<Modal
-  contentLabel="keyboard_shortcuts.title"
-  onRequestClose={[Function]}
-  size="medium"
->
-  <div
-    className="modal-head display-flex-space-between"
-  >
-    <h2>
-      keyboard_shortcuts.title
-    </h2>
-    <ForwardRef(Link)
-      onClick={[Function]}
-      to="/account"
-    >
-      keyboard_shortcuts.disable_link
-    </ForwardRef(Link)>
-  </div>
-  <div
-    className="modal-body modal-container markdown display-flex-start shortcuts-modal"
-  >
-    <div
-      className="flex-1"
-    >
-      <div
-        className="spacer-bottom"
-        key="global"
-      >
-        <h3
-          className="null-spacer-top"
-        >
-          keyboard_shortcuts.global.title
-        </h3>
-        <table>
-          <thead>
-            <tr>
-              <th>
-                keyboard_shortcuts.shortcut
-              </th>
-              <th>
-                keyboard_shortcuts.action
-              </th>
-            </tr>
-          </thead>
-          <tbody>
-            <tr
-              key="search"
-            >
-              <td>
-                <code
-                  className="little-spacer-right"
-                  key="s"
-                >
-                  s
-                </code>
-              </td>
-              <td>
-                keyboard_shortcuts.global.search
-              </td>
-            </tr>
-            <tr
-              key="open_shortcuts"
-            >
-              <td>
-                <code
-                  className="little-spacer-right"
-                  key="?"
-                >
-                  ?
-                </code>
-              </td>
-              <td>
-                keyboard_shortcuts.global.open_shortcuts
-              </td>
-            </tr>
-          </tbody>
-        </table>
-      </div>
-      <div
-        className="spacer-bottom"
-        key="issues_page"
-      >
-        <h3
-          className="null-spacer-top"
-        >
-          keyboard_shortcuts.issues_page.title
-        </h3>
-        <table>
-          <thead>
-            <tr>
-              <th>
-                keyboard_shortcuts.shortcut
-              </th>
-              <th>
-                keyboard_shortcuts.action
-              </th>
-            </tr>
-          </thead>
-          <tbody>
-            <tr
-              key="navigate"
-            >
-              <td>
-                <code
-                  className="little-spacer-right"
-                  key="↑"
-                >
-                  ↑
-                </code>
-                <code
-                  className="little-spacer-right"
-                  key="↓"
-                >
-                  ↓
-                </code>
-              </td>
-              <td>
-                keyboard_shortcuts.issues_page.navigate
-              </td>
-            </tr>
-            <tr
-              key="source_code"
-            >
-              <td>
-                <code
-                  className="little-spacer-right"
-                  key="→"
-                >
-                  →
-                </code>
-              </td>
-              <td>
-                keyboard_shortcuts.issues_page.source_code
-              </td>
-            </tr>
-            <tr
-              key="back"
-            >
-              <td>
-                <code
-                  className="little-spacer-right"
-                  key="←"
-                >
-                  ←
-                </code>
-              </td>
-              <td>
-                keyboard_shortcuts.issues_page.back
-              </td>
-            </tr>
-            <tr
-              key="navigate_locations"
-            >
-              <td>
-                <code
-                  className="little-spacer-right"
-                  key="alt"
-                >
-                  alt
-                </code>
-                <span
-                  className="little-spacer-right"
-                  key="+"
-                >
-                  +
-                </span>
-                <code
-                  className="little-spacer-right"
-                  key="↑"
-                >
-                  ↑
-                </code>
-                <code
-                  className="little-spacer-right"
-                  key="↓"
-                >
-                  ↓
-                </code>
-              </td>
-              <td>
-                keyboard_shortcuts.issues_page.navigate_locations
-              </td>
-            </tr>
-            <tr
-              key="switch_flows"
-            >
-              <td>
-                <code
-                  className="little-spacer-right"
-                  key="alt"
-                >
-                  alt
-                </code>
-                <span
-                  className="little-spacer-right"
-                  key="+"
-                >
-                  +
-                </span>
-                <code
-                  className="little-spacer-right"
-                  key="←"
-                >
-                  ←
-                </code>
-                <code
-                  className="little-spacer-right"
-                  key="→"
-                >
-                  →
-                </code>
-              </td>
-              <td>
-                keyboard_shortcuts.issues_page.switch_flows
-              </td>
-            </tr>
-            <tr
-              key="transition"
-            >
-              <td>
-                <code
-                  className="little-spacer-right"
-                  key="f"
-                >
-                  f
-                </code>
-              </td>
-              <td>
-                keyboard_shortcuts.issues_page.transition
-              </td>
-            </tr>
-            <tr
-              key="assign"
-            >
-              <td>
-                <code
-                  className="little-spacer-right"
-                  key="a"
-                >
-                  a
-                </code>
-              </td>
-              <td>
-                keyboard_shortcuts.issues_page.assign
-              </td>
-            </tr>
-            <tr
-              key="assign_to_me"
-            >
-              <td>
-                <code
-                  className="little-spacer-right"
-                  key="m"
-                >
-                  m
-                </code>
-              </td>
-              <td>
-                keyboard_shortcuts.issues_page.assign_to_me
-              </td>
-            </tr>
-            <tr
-              key="severity"
-            >
-              <td>
-                <code
-                  className="little-spacer-right"
-                  key="i"
-                >
-                  i
-                </code>
-              </td>
-              <td>
-                keyboard_shortcuts.issues_page.severity
-              </td>
-            </tr>
-            <tr
-              key="comment"
-            >
-              <td>
-                <code
-                  className="little-spacer-right"
-                  key="c"
-                >
-                  c
-                </code>
-              </td>
-              <td>
-                keyboard_shortcuts.issues_page.comment
-              </td>
-            </tr>
-            <tr
-              key="submit_comment"
-            >
-              <td>
-                <code
-                  className="little-spacer-right"
-                  key="ctrl"
-                >
-                  ctrl
-                </code>
-                <span
-                  className="little-spacer-right"
-                  key="+"
-                >
-                  +
-                </span>
-                <code
-                  className="little-spacer-right"
-                  key="enter"
-                >
-                  enter
-                </code>
-              </td>
-              <td>
-                keyboard_shortcuts.issues_page.submit_comment
-              </td>
-            </tr>
-            <tr
-              key="tags"
-            >
-              <td>
-                <code
-                  className="little-spacer-right"
-                  key="t"
-                >
-                  t
-                </code>
-              </td>
-              <td>
-                keyboard_shortcuts.issues_page.tags
-              </td>
-            </tr>
-          </tbody>
-        </table>
-      </div>
-    </div>
-    <div
-      className="flex-1 huge-spacer-left"
-    >
-      <div
-        className="spacer-bottom"
-        key="code_page"
-      >
-        <h3
-          className="null-spacer-top"
-        >
-          keyboard_shortcuts.code_page.title
-        </h3>
-        <table>
-          <thead>
-            <tr>
-              <th>
-                keyboard_shortcuts.shortcut
-              </th>
-              <th>
-                keyboard_shortcuts.action
-              </th>
-            </tr>
-          </thead>
-          <tbody>
-            <tr
-              key="select_files"
-            >
-              <td>
-                <code
-                  className="little-spacer-right"
-                  key="↑"
-                >
-                  ↑
-                </code>
-                <code
-                  className="little-spacer-right"
-                  key="↓"
-                >
-                  ↓
-                </code>
-              </td>
-              <td>
-                keyboard_shortcuts.code_page.select_files
-              </td>
-            </tr>
-            <tr
-              key="open_file"
-            >
-              <td>
-                <code
-                  className="little-spacer-right"
-                  key="→"
-                >
-                  →
-                </code>
-              </td>
-              <td>
-                keyboard_shortcuts.code_page.open_file
-              </td>
-            </tr>
-            <tr
-              key="back"
-            >
-              <td>
-                <code
-                  className="little-spacer-right"
-                  key="←"
-                >
-                  ←
-                </code>
-              </td>
-              <td>
-                keyboard_shortcuts.code_page.back
-              </td>
-            </tr>
-          </tbody>
-        </table>
-      </div>
-      <div
-        className="spacer-bottom"
-        key="measures_page"
-      >
-        <h3
-          className="null-spacer-top"
-        >
-          keyboard_shortcuts.measures_page.title
-        </h3>
-        <table>
-          <thead>
-            <tr>
-              <th>
-                keyboard_shortcuts.shortcut
-              </th>
-              <th>
-                keyboard_shortcuts.action
-              </th>
-            </tr>
-          </thead>
-          <tbody>
-            <tr
-              key="select_files"
-            >
-              <td>
-                <code
-                  className="little-spacer-right"
-                  key="↑"
-                >
-                  ↑
-                </code>
-                <code
-                  className="little-spacer-right"
-                  key="↓"
-                >
-                  ↓
-                </code>
-              </td>
-              <td>
-                keyboard_shortcuts.measures_page.select_files
-              </td>
-            </tr>
-            <tr
-              key="open_file"
-            >
-              <td>
-                <code
-                  className="little-spacer-right"
-                  key="→"
-                >
-                  →
-                </code>
-              </td>
-              <td>
-                keyboard_shortcuts.measures_page.open_file
-              </td>
-            </tr>
-            <tr
-              key="back"
-            >
-              <td>
-                <code
-                  className="little-spacer-right"
-                  key="←"
-                >
-                  ←
-                </code>
-              </td>
-              <td>
-                keyboard_shortcuts.measures_page.back
-              </td>
-            </tr>
-          </tbody>
-        </table>
-      </div>
-      <div
-        className="spacer-bottom"
-        key="rules_page"
-      >
-        <h3
-          className="null-spacer-top"
-        >
-          keyboard_shortcuts.rules_page.title
-        </h3>
-        <table>
-          <thead>
-            <tr>
-              <th>
-                keyboard_shortcuts.shortcut
-              </th>
-              <th>
-                keyboard_shortcuts.action
-              </th>
-            </tr>
-          </thead>
-          <tbody>
-            <tr
-              key="navigate"
-            >
-              <td>
-                <code
-                  className="little-spacer-right"
-                  key="↑"
-                >
-                  ↑
-                </code>
-                <code
-                  className="little-spacer-right"
-                  key="↓"
-                >
-                  ↓
-                </code>
-              </td>
-              <td>
-                keyboard_shortcuts.rules_page.navigate
-              </td>
-            </tr>
-            <tr
-              key="rule_details"
-            >
-              <td>
-                <code
-                  className="little-spacer-right"
-                  key="→"
-                >
-                  →
-                </code>
-              </td>
-              <td>
-                keyboard_shortcuts.rules_page.rule_details
-              </td>
-            </tr>
-            <tr
-              key="back"
-            >
-              <td>
-                <code
-                  className="little-spacer-right"
-                  key="←"
-                >
-                  ←
-                </code>
-              </td>
-              <td>
-                keyboard_shortcuts.rules_page.back
-              </td>
-            </tr>
-          </tbody>
-        </table>
-      </div>
-    </div>
-  </div>
-  <div
-    className="modal-foot"
-  >
-    <Button
-      onClick={[Function]}
-    >
-      close
-    </Button>
-  </div>
-</Modal>
-`;
diff --git a/server/sonar-web/src/main/js/app/components/__tests__/__snapshots__/MigrationContainer-test.tsx.snap b/server/sonar-web/src/main/js/app/components/__tests__/__snapshots__/MigrationContainer-test.tsx.snap
deleted file mode 100644 (file)
index 304a45e..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`should render correctly if system is starting 1`] = `
-<Navigate
-  to={
-    {
-      "pathname": "/maintenance",
-      "search": "return_to=%2Fprojects%3Fquery%3Dtoto%23hash",
-    }
-  }
-/>
-`;
-
-exports[`should render correctly if system is up 1`] = `<Outlet />`;
diff --git a/server/sonar-web/src/main/js/app/components/__tests__/__snapshots__/PageTracker-test.tsx.snap b/server/sonar-web/src/main/js/app/components/__tests__/__snapshots__/PageTracker-test.tsx.snap
deleted file mode 100644 (file)
index e8b8c18..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`should not trigger if no analytics system is given 1`] = `
-<Helmet
-  defer={false}
-  encodeSpecialCharacters={true}
-  prioritizeSeoTags={false}
-/>
-`;
-
-exports[`should work for WebAnalytics plugin 1`] = `
-<Helmet
-  defer={false}
-  encodeSpecialCharacters={true}
-  onChangeClientState={[Function]}
-  prioritizeSeoTags={false}
-/>
-`;
diff --git a/server/sonar-web/src/main/js/app/components/__tests__/__snapshots__/ProjectAdminContainer-test.tsx.snap b/server/sonar-web/src/main/js/app/components/__tests__/__snapshots__/ProjectAdminContainer-test.tsx.snap
deleted file mode 100644 (file)
index 0d01829..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`should render correctly 1`] = `
-<main>
-  <A11ySkipTarget
-    anchor="admin_main"
-  />
-  <Outlet />
-</main>
-`;