]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-17365 Refactor audit app enzyme to RTL
authorMathieu Suen <mathieu.suen@sonarsource.com>
Wed, 28 Sep 2022 13:38:39 +0000 (15:38 +0200)
committersonartech <sonartech@sonarsource.com>
Thu, 29 Sep 2022 20:03:15 +0000 (20:03 +0000)
16 files changed:
server/sonar-web/package.json
server/sonar-web/src/main/js/api/mocks/AuditLogsServiceMock.ts [deleted file]
server/sonar-web/src/main/js/api/mocks/SettingsServiceMock.ts [new file with mode: 0644]
server/sonar-web/src/main/js/apps/audit-logs/components/AuditApp.tsx
server/sonar-web/src/main/js/apps/audit-logs/components/DownloadButton.tsx
server/sonar-web/src/main/js/apps/audit-logs/components/__tests__/AuditApp-it.tsx
server/sonar-web/src/main/js/apps/audit-logs/components/__tests__/AuditApp-test.tsx [deleted file]
server/sonar-web/src/main/js/apps/audit-logs/components/__tests__/AuditAppRenderer-test.tsx [deleted file]
server/sonar-web/src/main/js/apps/audit-logs/components/__tests__/DownloadButton-test.tsx [deleted file]
server/sonar-web/src/main/js/apps/audit-logs/components/__tests__/__snapshots__/AuditApp-test.tsx.snap [deleted file]
server/sonar-web/src/main/js/apps/audit-logs/components/__tests__/__snapshots__/AuditAppRenderer-test.tsx.snap [deleted file]
server/sonar-web/src/main/js/apps/audit-logs/components/__tests__/__snapshots__/DownloadButton-test.tsx.snap [deleted file]
server/sonar-web/src/main/js/components/controls/DateInput.tsx
server/sonar-web/src/main/js/components/controls/__tests__/__snapshots__/DateInput-test.tsx.snap
server/sonar-web/yarn.lock
sonar-core/src/main/resources/org/sonar/l10n/core.properties

index a2ffdeec0efcae0afa4028dac85d64990b4ebe8f..34541da1e248c3296e321ffaef40b586373fe7e8 100644 (file)
     "postcss-custom-properties": "9.1.1",
     "prettier": "1.19.1",
     "react-select-event": "5.5.1",
+    "testing-library-selector": "0.2.1",
     "typescript": "4.6.3",
     "whatwg-fetch": "3.6.2"
   },
diff --git a/server/sonar-web/src/main/js/api/mocks/AuditLogsServiceMock.ts b/server/sonar-web/src/main/js/api/mocks/AuditLogsServiceMock.ts
deleted file mode 100644 (file)
index 8d52440..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2022 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 { cloneDeep } from 'lodash';
-import { HousekeepingPolicy } from '../../apps/audit-logs/utils';
-import { SettingValue } from '../../types/settings';
-import { getValue } from '../settings';
-
-export default class AuditLogsServiceMock {
-  settingValue: SettingValue;
-  defaultValues: SettingValue = { key: 'test', value: HousekeepingPolicy.Weekly };
-
-  constructor() {
-    this.settingValue = cloneDeep(this.defaultValues);
-    (getValue as jest.Mock).mockImplementation(this.getValuesHandler);
-  }
-
-  getValuesHandler = () => {
-    return Promise.resolve(this.settingValue);
-  };
-
-  resetSettingvalues = () => {
-    this.settingValue = cloneDeep(this.defaultValues);
-  };
-}
diff --git a/server/sonar-web/src/main/js/api/mocks/SettingsServiceMock.ts b/server/sonar-web/src/main/js/api/mocks/SettingsServiceMock.ts
new file mode 100644 (file)
index 0000000..9f02909
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2022 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 { cloneDeep } from 'lodash';
+import { HousekeepingPolicy } from '../../apps/audit-logs/utils';
+import { SettingsKey, SettingValue } from '../../types/settings';
+import { getValue } from '../settings';
+
+export default class SettingsServiceMock {
+  settingValue?: SettingValue;
+  defaultValues: SettingValue = {
+    key: SettingsKey.AuditHouseKeeping,
+    value: HousekeepingPolicy.Weekly
+  };
+
+  constructor() {
+    this.settingValue = cloneDeep(this.defaultValues);
+    (getValue as jest.Mock).mockImplementation(this.getValuesHandler);
+  }
+
+  getValuesHandler = () => {
+    return Promise.resolve(this.settingValue);
+  };
+
+  unsetHousekeepingPolicy() {
+    this.settingValue = undefined;
+  }
+
+  setYearlyHousekeepingPolicy() {
+    this.settingValue = { key: 'test', value: HousekeepingPolicy.Yearly };
+  }
+
+  resetSettingvalues = () => {
+    this.settingValue = cloneDeep(this.defaultValues);
+  };
+}
index 7582b963c922d97517fdd7f8c33949437916bfa4..7cce3ac91ed069d9af95bf9ceba811eea3439caa 100644 (file)
@@ -55,12 +55,6 @@ export class AuditApp extends React.PureComponent<Props, State> {
     }
   }
 
-  componentDidUpdate(prevProps: Props) {
-    if (prevProps.adminPages !== this.props.adminPages && this.hasGovernanceExtension()) {
-      this.fetchHouseKeepingPolicy();
-    }
-  }
-
   fetchHouseKeepingPolicy = async () => {
     const result = await getValue({ key: SettingsKey.AuditHouseKeeping });
 
index ab00e68fbeae9a14b01cc551dd31e165fb58d0e7..ae80edbfffab210bee5379ea3369875a312a5a71 100644 (file)
@@ -45,6 +45,8 @@ const toISODateString = (date: Date) => date.toISOString();
 function getRangeParams(selection: RangeOption, dateRange?: { from?: Date; to?: Date }) {
   if (selection === RangeOption.Custom) {
     // dateRange should be complete if 'custom' is selected
+    // This is not strickly necessary since submit is disable
+    // when the if condition is true.
     if (!(dateRange?.to && dateRange?.from)) {
       return '';
     }
@@ -78,6 +80,7 @@ export default function DownloadButton(props: DownloadButtonProps) {
       <a
         className={classNames('button button-primary', { disabled: downloadDisabled })}
         download="audit_logs.json"
+        aria-disabled={downloadDisabled}
         onClick={downloadDisabled ? undefined : props.onStartDownload}
         href={downloadUrl}
         rel="noopener noreferrer"
index 9000cadeb795384cbde1136fa55ef8b3813bc30c..80128101cbe99bfc7d74db1903cc0314fd16bdf1 100644 (file)
  */
 import { screen } from '@testing-library/react';
 import userEvent from '@testing-library/user-event';
-import AuditLogsServiceMock from '../../../../api/mocks/AuditLogsServiceMock';
+import { getDate, getMonth, getYear, subDays } from 'date-fns';
+import selectEvent from 'react-select-event';
+import { byPlaceholderText, byRole, byText } from 'testing-library-selector';
+import SettingsServiceMock from '../../../../api/mocks/SettingsServiceMock';
+import { now } from '../../../../helpers/dates';
+import { getShortMonthName } from '../../../../helpers/l10n';
 import { renderAppWithAdminContext } from '../../../../helpers/testReactTestingUtils';
 import { AdminPageExtension } from '../../../../types/extension';
 import routes from '../../routes';
@@ -32,33 +37,131 @@ const extensions = [
   { key: 'license/support', name: 'Support' }
 ];
 
-let handler: AuditLogsServiceMock;
+jest.mock('date-fns', () => {
+  // Timezone will not play well so we fake the response from lib.
+  const dateFns = jest.requireActual('date-fns');
+  return {
+    ...dateFns,
+    endOfDay: jest.fn().mockImplementation(d => d),
+    startOfDay: jest.fn().mockImplementation(d => d)
+  };
+});
 
-beforeAll(() => {
-  handler = new AuditLogsServiceMock();
+jest.mock('../../../../helpers/dates', () => {
+  return {
+    ...jest.requireActual('../../../../helpers/dates'),
+    now: jest.fn(() => new Date('2020-07-21T12:00:00Z'))
+  };
 });
 
-afterEach(() => handler.resetSettingvalues());
+const ui = {
+  pageTitle: byRole('heading', { name: 'audit_logs.page' }),
+  downloadButton: byRole('link', { name: 'download_verb' }),
+  todayRadio: byRole('radio', { name: 'audit_logs.range_option.today' }),
+  weekRadio: byRole('radio', { name: 'audit_logs.range_option.7days' }),
+  monthRadio: byRole('radio', { name: 'audit_logs.range_option.30days' }),
+  trimesterRadio: byRole('radio', { name: 'audit_logs.range_option.90days' }),
+  customRadio: byRole('radio', { name: 'audit_logs.range_option.custom' }),
+  downloadSentenceStart: byText('audit_logs.download_start.sentence.1'),
+  startDateInput: byPlaceholderText('start_date'),
+  endDateInput: byPlaceholderText('end_date')
+};
 
-it('should render audit logs page correctly', async () => {
-  renderAuditLogs();
-  expect(await screen.findByText('audit_logs.page')).toBeInTheDocument();
+let handler: SettingsServiceMock;
+
+beforeAll(() => {
+  handler = new SettingsServiceMock();
 });
 
+afterEach(() => handler.resetSettingvalues());
+
 it('should handle download button click', async () => {
   const user = userEvent.setup();
+  handler.setYearlyHousekeepingPolicy();
   renderAuditLogs();
-  const downloadButton = await screen.findByText('download_verb');
+  const downloadButton = await ui.downloadButton.find();
   expect(downloadButton).toBeInTheDocument();
+  expect(downloadButton).toHaveAttribute(
+    'href',
+    '/api/audit_logs/download?from=2020-07-21T12%3A00%3A00.000Z&to=2020-07-21T12%3A00%3A00.000Z'
+  );
+  await user.click(ui.weekRadio.get());
+  expect(downloadButton).toHaveAttribute(
+    'href',
+    '/api/audit_logs/download?from=2020-07-14T12%3A00%3A00.000Z&to=2020-07-21T12%3A00%3A00.000Z'
+  );
+  await user.click(ui.monthRadio.get());
+  expect(downloadButton).toHaveAttribute(
+    'href',
+    '/api/audit_logs/download?from=2020-06-21T12%3A00%3A00.000Z&to=2020-07-21T12%3A00%3A00.000Z'
+  );
+  await user.click(ui.trimesterRadio.get());
+  expect(downloadButton).toHaveAttribute(
+    'href',
+    '/api/audit_logs/download?from=2020-04-22T12%3A00%3A00.000Z&to=2020-07-21T12%3A00%3A00.000Z'
+  );
 
   await user.click(downloadButton);
 
-  expect(await screen.findByText('download_verb')).toHaveAttribute('href', '#');
-  expect(screen.getByText('audit_logs.download_start.sentence.1')).toBeInTheDocument();
-  expect(screen.getByText('audit_logs.download_start.sentence.2')).toBeInTheDocument();
-  expect(screen.getByText('audit_logs.download_start.sentence.3')).toBeInTheDocument();
+  expect(await ui.downloadButton.find()).toHaveAttribute('aria-disabled', 'true');
+  expect(ui.downloadSentenceStart.get()).toBeInTheDocument();
+
+  // Custom date
+  const startDay = subDays(now(), 5);
+  const endDate = subDays(now(), 1);
+  await user.click(ui.customRadio.get());
+  expect(ui.downloadButton.get()).toHaveAttribute('aria-disabled', 'true');
+  await user.click(ui.startDateInput.get());
+
+  await selectEvent.select(screen.getByRole('textbox', { name: 'select_month' }), [
+    getShortMonthName(getMonth(startDay))
+  ]);
+  await selectEvent.select(screen.getByRole('textbox', { name: 'select_year' }), [
+    getYear(startDay)
+  ]);
+  await user.click(screen.getByText(getDate(startDay)));
+  await user.click(ui.endDateInput.get());
+
+  await selectEvent.select(screen.getByRole('textbox', { name: 'select_month' }), [
+    getShortMonthName(getMonth(endDate))
+  ]);
+  await selectEvent.select(screen.getByRole('textbox', { name: 'select_year' }), [
+    getYear(endDate)
+  ]);
+  await user.click(screen.getByText(getDate(endDate)));
+
+  expect(await ui.downloadButton.find()).toHaveAttribute('aria-disabled', 'false');
+  await user.click(downloadButton);
+  expect(await ui.downloadButton.find()).toHaveAttribute('aria-disabled', 'true');
+});
+
+it('should not render if governance is not enable', () => {
+  renderAuditLogs([]);
+  expect(ui.pageTitle.query()).not.toBeInTheDocument();
+});
+
+it('should show right option when keeping log for month', async () => {
+  handler.unsetHousekeepingPolicy();
+  renderAuditLogs();
+  expect(await ui.pageTitle.find()).toBeInTheDocument();
+  expect(ui.todayRadio.get()).toBeInTheDocument();
+  expect(ui.weekRadio.get()).toBeInTheDocument();
+  expect(ui.monthRadio.get()).toBeInTheDocument();
+  expect(ui.customRadio.get()).toBeInTheDocument();
+  expect(ui.trimesterRadio.query()).not.toBeInTheDocument();
+});
+
+it('should show right option when keeping log for year', async () => {
+  handler.setYearlyHousekeepingPolicy();
+  renderAuditLogs();
+  expect(await ui.pageTitle.find()).toBeInTheDocument();
+  expect(ui.todayRadio.get()).toBeInTheDocument();
+  expect(ui.weekRadio.get()).toBeInTheDocument();
+  expect(ui.monthRadio.get()).toBeInTheDocument();
+  expect(ui.trimesterRadio.get()).toBeInTheDocument();
+  expect(ui.customRadio.get()).toBeInTheDocument();
 });
 
-function renderAuditLogs() {
-  renderAppWithAdminContext('admin/audit', routes, {}, { adminPages: extensions });
+function renderAuditLogs(adminPages = extensions) {
+  renderAppWithAdminContext('admin/audit', routes, {}, { adminPages });
 }
diff --git a/server/sonar-web/src/main/js/apps/audit-logs/components/__tests__/AuditApp-test.tsx b/server/sonar-web/src/main/js/apps/audit-logs/components/__tests__/AuditApp-test.tsx
deleted file mode 100644 (file)
index 21ffca8..0000000
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2022 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 { subDays } from 'date-fns';
-import { shallow } from 'enzyme';
-import * as React from 'react';
-import { getValue } from '../../../../api/settings';
-import { waitAndUpdate } from '../../../../helpers/testUtils';
-import { AdminPageExtension } from '../../../../types/extension';
-import { HousekeepingPolicy, RangeOption } from '../../utils';
-import { AuditApp } from '../AuditApp';
-import AuditAppRenderer from '../AuditAppRenderer';
-
-jest.mock('../../../../api/settings', () => ({
-  getValue: jest.fn().mockResolvedValue({})
-}));
-
-beforeEach(() => {
-  jest.clearAllMocks();
-});
-
-it('should render correctly', () => {
-  expect(shallowRender()).toMatchSnapshot();
-});
-
-it('should do nothing if governance is not available', async () => {
-  const wrapper = shallowRender({ adminPages: [] });
-  await waitAndUpdate(wrapper);
-
-  expect(wrapper.type()).toBeNull();
-  expect(getValue).not.toBeCalled();
-});
-
-it('should handle housekeeping policy', async () => {
-  (getValue as jest.Mock).mockResolvedValueOnce({ value: HousekeepingPolicy.Weekly });
-
-  const wrapper = shallowRender();
-
-  await waitAndUpdate(wrapper);
-
-  expect(wrapper.find(AuditAppRenderer).props().housekeepingPolicy).toBe(HousekeepingPolicy.Weekly);
-});
-
-it('should handle date selection', () => {
-  const wrapper = shallowRender();
-  const range = { from: subDays(new Date(), 2), to: new Date() };
-
-  expect(wrapper.state().selection).toBe(RangeOption.Today);
-
-  wrapper
-    .find(AuditAppRenderer)
-    .props()
-    .handleDateSelection(range);
-
-  expect(wrapper.state().selection).toBe(RangeOption.Custom);
-  expect(wrapper.state().dateRange).toBe(range);
-});
-
-it('should handle predefined selection', () => {
-  const wrapper = shallowRender();
-  const dateRange = { from: subDays(new Date(), 2), to: new Date() };
-
-  wrapper.setState({ dateRange, selection: RangeOption.Custom });
-
-  wrapper
-    .find(AuditAppRenderer)
-    .props()
-    .handleOptionSelection(RangeOption.Week);
-
-  expect(wrapper.state().selection).toBe(RangeOption.Week);
-  expect(wrapper.state().dateRange).toBeUndefined();
-});
-
-it('should handle update to admin pages', async () => {
-  const wrapper = shallowRender({ adminPages: [] });
-  await waitAndUpdate(wrapper);
-
-  expect(wrapper.type()).toBeNull();
-  expect(getValue).not.toBeCalled();
-
-  wrapper.setProps({ adminPages: [{ key: AdminPageExtension.GovernanceConsole, name: 'name' }] });
-  await waitAndUpdate(wrapper);
-
-  expect(getValue).toBeCalled();
-});
-
-function shallowRender(props: Partial<AuditApp['props']> = {}) {
-  return shallow<AuditApp>(
-    <AuditApp
-      adminPages={[{ key: AdminPageExtension.GovernanceConsole, name: 'name' }]}
-      {...props}
-    />
-  );
-}
diff --git a/server/sonar-web/src/main/js/apps/audit-logs/components/__tests__/AuditAppRenderer-test.tsx b/server/sonar-web/src/main/js/apps/audit-logs/components/__tests__/AuditAppRenderer-test.tsx
deleted file mode 100644 (file)
index d28fbb0..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2022 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 { now } from '../../../../helpers/dates';
-import { HousekeepingPolicy, RangeOption } from '../../utils';
-import AuditAppRenderer, { AuditAppRendererProps } from '../AuditAppRenderer';
-
-jest.mock('../../../../helpers/dates', () => {
-  return {
-    ...jest.requireActual('../../../../helpers/dates'),
-    now: jest.fn(() => new Date('2020-07-21T12:00:00Z'))
-  };
-});
-
-it.each([
-  [HousekeepingPolicy.Weekly],
-  [HousekeepingPolicy.Monthly],
-  [HousekeepingPolicy.Trimestrial],
-  [HousekeepingPolicy.Yearly]
-])('should render correctly for %s housekeeping policy', housekeepingPolicy => {
-  expect(shallowRender({ housekeepingPolicy })).toMatchSnapshot();
-  now();
-});
-
-function shallowRender(props: Partial<AuditAppRendererProps> = {}) {
-  return shallow(
-    <AuditAppRenderer
-      downloadStarted={false}
-      handleDateSelection={jest.fn()}
-      handleOptionSelection={jest.fn()}
-      handleStartDownload={jest.fn()}
-      housekeepingPolicy={HousekeepingPolicy.Yearly}
-      selection={RangeOption.Today}
-      {...props}
-    />
-  );
-}
diff --git a/server/sonar-web/src/main/js/apps/audit-logs/components/__tests__/DownloadButton-test.tsx b/server/sonar-web/src/main/js/apps/audit-logs/components/__tests__/DownloadButton-test.tsx
deleted file mode 100644 (file)
index 27b74db..0000000
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2022 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 { subDays } from 'date-fns';
-import { shallow } from 'enzyme';
-import * as React from 'react';
-import { RangeOption } from '../../utils';
-import DownloadButton, { DownloadButtonProps } from '../DownloadButton';
-
-jest.mock('date-fns', () => {
-  const { subDays } = jest.requireActual('date-fns');
-  return {
-    endOfDay: jest.fn().mockImplementation(d => d),
-    startOfDay: jest.fn().mockImplementation(d => d),
-    subDays
-  };
-});
-
-jest.mock('../../../../helpers/dates', () => {
-  return {
-    ...jest.requireActual('../../../../helpers/dates'),
-    now: jest.fn(() => new Date('2020-07-21T12:00:00Z'))
-  };
-});
-
-it.each([[RangeOption.Today], [RangeOption.Week], [RangeOption.Month], [RangeOption.Trimester]])(
-  'should render correctly for %s',
-  selection => {
-    expect(shallowRender({ selection })).toMatchSnapshot('default');
-  }
-);
-
-it('should render correctly for custom range', () => {
-  const baseDate = new Date('2020-07-21T12:00:00Z');
-
-  expect(shallowRender({ selection: RangeOption.Custom })).toMatchSnapshot('no dates');
-  expect(
-    shallowRender({
-      dateRange: { from: subDays(baseDate, 2), to: baseDate },
-      selection: RangeOption.Custom
-    })
-  ).toMatchSnapshot('with dates');
-});
-
-it('should handle download', () => {
-  const onStartDownload = jest.fn();
-  const wrapper = shallowRender({ onStartDownload });
-
-  wrapper.find('a').simulate('click');
-  wrapper.setProps({ downloadStarted: true });
-  wrapper.find('a').simulate('click');
-
-  expect(onStartDownload).toBeCalledTimes(1);
-});
-
-function shallowRender(props: Partial<DownloadButtonProps> = {}) {
-  return shallow<DownloadButtonProps>(
-    <DownloadButton
-      downloadStarted={false}
-      selection={RangeOption.Today}
-      onStartDownload={jest.fn()}
-      {...props}
-    />
-  );
-}
diff --git a/server/sonar-web/src/main/js/apps/audit-logs/components/__tests__/__snapshots__/AuditApp-test.tsx.snap b/server/sonar-web/src/main/js/apps/audit-logs/components/__tests__/__snapshots__/AuditApp-test.tsx.snap
deleted file mode 100644 (file)
index 7520c26..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`should render correctly 1`] = `
-<AuditAppRenderer
-  downloadStarted={false}
-  handleDateSelection={[Function]}
-  handleOptionSelection={[Function]}
-  handleStartDownload={[Function]}
-  housekeepingPolicy="Monthly"
-  selection="today"
-/>
-`;
diff --git a/server/sonar-web/src/main/js/apps/audit-logs/components/__tests__/__snapshots__/AuditAppRenderer-test.tsx.snap b/server/sonar-web/src/main/js/apps/audit-logs/components/__tests__/__snapshots__/AuditAppRenderer-test.tsx.snap
deleted file mode 100644 (file)
index db78b92..0000000
+++ /dev/null
@@ -1,501 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`should render correctly for Monthly housekeeping policy 1`] = `
-<div
-  className="page page-limited"
-  id="marketplace-page"
->
-  <Suggestions
-    suggestions="audit-logs"
-  />
-  <Helmet
-    defer={true}
-    encodeSpecialCharacters={true}
-    prioritizeSeoTags={false}
-    title="audit_logs.page"
-  />
-  <header
-    className="page-header"
-  >
-    <h1
-      className="page-title"
-    >
-      audit_logs.page
-    </h1>
-  </header>
-  <p
-    className="big-spacer-bottom"
-  >
-    audit_logs.page.description.1
-    <br />
-    <FormattedMessage
-      defaultMessage="audit_logs.page.description.2"
-      id="audit_logs.page.description.2"
-      values={
-        Object {
-          "housekeeping": "audit_logs.housekeeping_policy.Monthly",
-          "link": <ForwardRef(Link)
-            to={
-              Object {
-                "hash": "#auditLogs",
-                "pathname": "/admin/settings",
-                "search": "?category=housekeeping",
-              }
-            }
-          >
-            audit_logs.page.description.link
-          </ForwardRef(Link)>,
-        }
-      }
-    />
-  </p>
-  <div
-    className="huge-spacer-bottom"
-  >
-    <h2
-      className="big-spacer-bottom"
-    >
-      audit_logs.download
-    </h2>
-    <ul>
-      <li
-        className="spacer-bottom"
-        key="today"
-      >
-        <Radio
-          checked={true}
-          onCheck={[MockFunction]}
-          value="today"
-        >
-          audit_logs.range_option.today
-        </Radio>
-      </li>
-      <li
-        className="spacer-bottom"
-        key="7days"
-      >
-        <Radio
-          checked={false}
-          onCheck={[MockFunction]}
-          value="7days"
-        >
-          audit_logs.range_option.7days
-        </Radio>
-      </li>
-      <li
-        className="spacer-bottom"
-        key="30days"
-      >
-        <Radio
-          checked={false}
-          onCheck={[MockFunction]}
-          value="30days"
-        >
-          audit_logs.range_option.30days
-        </Radio>
-      </li>
-      <li
-        className="spacer-bottom"
-        key="custom"
-      >
-        <Radio
-          checked={false}
-          onCheck={[MockFunction]}
-          value="custom"
-        >
-          audit_logs.range_option.custom
-        </Radio>
-      </li>
-    </ul>
-    <DateRangeInput
-      className="big-spacer-left"
-      maxDate={2020-07-21T12:00:00.000Z}
-      minDate={2020-06-21T12:00:00.000Z}
-      onChange={[MockFunction]}
-    />
-  </div>
-  <DownloadButton
-    downloadStarted={false}
-    onStartDownload={[MockFunction]}
-    selection="today"
-  />
-</div>
-`;
-
-exports[`should render correctly for Trimestrial housekeeping policy 1`] = `
-<div
-  className="page page-limited"
-  id="marketplace-page"
->
-  <Suggestions
-    suggestions="audit-logs"
-  />
-  <Helmet
-    defer={true}
-    encodeSpecialCharacters={true}
-    prioritizeSeoTags={false}
-    title="audit_logs.page"
-  />
-  <header
-    className="page-header"
-  >
-    <h1
-      className="page-title"
-    >
-      audit_logs.page
-    </h1>
-  </header>
-  <p
-    className="big-spacer-bottom"
-  >
-    audit_logs.page.description.1
-    <br />
-    <FormattedMessage
-      defaultMessage="audit_logs.page.description.2"
-      id="audit_logs.page.description.2"
-      values={
-        Object {
-          "housekeeping": "audit_logs.housekeeping_policy.Trimestrial",
-          "link": <ForwardRef(Link)
-            to={
-              Object {
-                "hash": "#auditLogs",
-                "pathname": "/admin/settings",
-                "search": "?category=housekeeping",
-              }
-            }
-          >
-            audit_logs.page.description.link
-          </ForwardRef(Link)>,
-        }
-      }
-    />
-  </p>
-  <div
-    className="huge-spacer-bottom"
-  >
-    <h2
-      className="big-spacer-bottom"
-    >
-      audit_logs.download
-    </h2>
-    <ul>
-      <li
-        className="spacer-bottom"
-        key="today"
-      >
-        <Radio
-          checked={true}
-          onCheck={[MockFunction]}
-          value="today"
-        >
-          audit_logs.range_option.today
-        </Radio>
-      </li>
-      <li
-        className="spacer-bottom"
-        key="7days"
-      >
-        <Radio
-          checked={false}
-          onCheck={[MockFunction]}
-          value="7days"
-        >
-          audit_logs.range_option.7days
-        </Radio>
-      </li>
-      <li
-        className="spacer-bottom"
-        key="30days"
-      >
-        <Radio
-          checked={false}
-          onCheck={[MockFunction]}
-          value="30days"
-        >
-          audit_logs.range_option.30days
-        </Radio>
-      </li>
-      <li
-        className="spacer-bottom"
-        key="90days"
-      >
-        <Radio
-          checked={false}
-          onCheck={[MockFunction]}
-          value="90days"
-        >
-          audit_logs.range_option.90days
-        </Radio>
-      </li>
-      <li
-        className="spacer-bottom"
-        key="custom"
-      >
-        <Radio
-          checked={false}
-          onCheck={[MockFunction]}
-          value="custom"
-        >
-          audit_logs.range_option.custom
-        </Radio>
-      </li>
-    </ul>
-    <DateRangeInput
-      className="big-spacer-left"
-      maxDate={2020-07-21T12:00:00.000Z}
-      minDate={2020-04-22T12:00:00.000Z}
-      onChange={[MockFunction]}
-    />
-  </div>
-  <DownloadButton
-    downloadStarted={false}
-    onStartDownload={[MockFunction]}
-    selection="today"
-  />
-</div>
-`;
-
-exports[`should render correctly for Weekly housekeeping policy 1`] = `
-<div
-  className="page page-limited"
-  id="marketplace-page"
->
-  <Suggestions
-    suggestions="audit-logs"
-  />
-  <Helmet
-    defer={true}
-    encodeSpecialCharacters={true}
-    prioritizeSeoTags={false}
-    title="audit_logs.page"
-  />
-  <header
-    className="page-header"
-  >
-    <h1
-      className="page-title"
-    >
-      audit_logs.page
-    </h1>
-  </header>
-  <p
-    className="big-spacer-bottom"
-  >
-    audit_logs.page.description.1
-    <br />
-    <FormattedMessage
-      defaultMessage="audit_logs.page.description.2"
-      id="audit_logs.page.description.2"
-      values={
-        Object {
-          "housekeeping": "audit_logs.housekeeping_policy.Weekly",
-          "link": <ForwardRef(Link)
-            to={
-              Object {
-                "hash": "#auditLogs",
-                "pathname": "/admin/settings",
-                "search": "?category=housekeeping",
-              }
-            }
-          >
-            audit_logs.page.description.link
-          </ForwardRef(Link)>,
-        }
-      }
-    />
-  </p>
-  <div
-    className="huge-spacer-bottom"
-  >
-    <h2
-      className="big-spacer-bottom"
-    >
-      audit_logs.download
-    </h2>
-    <ul>
-      <li
-        className="spacer-bottom"
-        key="today"
-      >
-        <Radio
-          checked={true}
-          onCheck={[MockFunction]}
-          value="today"
-        >
-          audit_logs.range_option.today
-        </Radio>
-      </li>
-      <li
-        className="spacer-bottom"
-        key="7days"
-      >
-        <Radio
-          checked={false}
-          onCheck={[MockFunction]}
-          value="7days"
-        >
-          audit_logs.range_option.7days
-        </Radio>
-      </li>
-      <li
-        className="spacer-bottom"
-        key="custom"
-      >
-        <Radio
-          checked={false}
-          onCheck={[MockFunction]}
-          value="custom"
-        >
-          audit_logs.range_option.custom
-        </Radio>
-      </li>
-    </ul>
-    <DateRangeInput
-      className="big-spacer-left"
-      maxDate={2020-07-21T12:00:00.000Z}
-      minDate={2020-07-14T12:00:00.000Z}
-      onChange={[MockFunction]}
-    />
-  </div>
-  <DownloadButton
-    downloadStarted={false}
-    onStartDownload={[MockFunction]}
-    selection="today"
-  />
-</div>
-`;
-
-exports[`should render correctly for Yearly housekeeping policy 1`] = `
-<div
-  className="page page-limited"
-  id="marketplace-page"
->
-  <Suggestions
-    suggestions="audit-logs"
-  />
-  <Helmet
-    defer={true}
-    encodeSpecialCharacters={true}
-    prioritizeSeoTags={false}
-    title="audit_logs.page"
-  />
-  <header
-    className="page-header"
-  >
-    <h1
-      className="page-title"
-    >
-      audit_logs.page
-    </h1>
-  </header>
-  <p
-    className="big-spacer-bottom"
-  >
-    audit_logs.page.description.1
-    <br />
-    <FormattedMessage
-      defaultMessage="audit_logs.page.description.2"
-      id="audit_logs.page.description.2"
-      values={
-        Object {
-          "housekeeping": "audit_logs.housekeeping_policy.Yearly",
-          "link": <ForwardRef(Link)
-            to={
-              Object {
-                "hash": "#auditLogs",
-                "pathname": "/admin/settings",
-                "search": "?category=housekeeping",
-              }
-            }
-          >
-            audit_logs.page.description.link
-          </ForwardRef(Link)>,
-        }
-      }
-    />
-  </p>
-  <div
-    className="huge-spacer-bottom"
-  >
-    <h2
-      className="big-spacer-bottom"
-    >
-      audit_logs.download
-    </h2>
-    <ul>
-      <li
-        className="spacer-bottom"
-        key="today"
-      >
-        <Radio
-          checked={true}
-          onCheck={[MockFunction]}
-          value="today"
-        >
-          audit_logs.range_option.today
-        </Radio>
-      </li>
-      <li
-        className="spacer-bottom"
-        key="7days"
-      >
-        <Radio
-          checked={false}
-          onCheck={[MockFunction]}
-          value="7days"
-        >
-          audit_logs.range_option.7days
-        </Radio>
-      </li>
-      <li
-        className="spacer-bottom"
-        key="30days"
-      >
-        <Radio
-          checked={false}
-          onCheck={[MockFunction]}
-          value="30days"
-        >
-          audit_logs.range_option.30days
-        </Radio>
-      </li>
-      <li
-        className="spacer-bottom"
-        key="90days"
-      >
-        <Radio
-          checked={false}
-          onCheck={[MockFunction]}
-          value="90days"
-        >
-          audit_logs.range_option.90days
-        </Radio>
-      </li>
-      <li
-        className="spacer-bottom"
-        key="custom"
-      >
-        <Radio
-          checked={false}
-          onCheck={[MockFunction]}
-          value="custom"
-        >
-          audit_logs.range_option.custom
-        </Radio>
-      </li>
-    </ul>
-    <DateRangeInput
-      className="big-spacer-left"
-      maxDate={2020-07-21T12:00:00.000Z}
-      minDate={2019-07-22T12:00:00.000Z}
-      onChange={[MockFunction]}
-    />
-  </div>
-  <DownloadButton
-    downloadStarted={false}
-    onStartDownload={[MockFunction]}
-    selection="today"
-  />
-</div>
-`;
diff --git a/server/sonar-web/src/main/js/apps/audit-logs/components/__tests__/__snapshots__/DownloadButton-test.tsx.snap b/server/sonar-web/src/main/js/apps/audit-logs/components/__tests__/__snapshots__/DownloadButton-test.tsx.snap
deleted file mode 100644 (file)
index 2bd20ad..0000000
+++ /dev/null
@@ -1,90 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`should render correctly for 7days: default 1`] = `
-<Fragment>
-  <a
-    className="button button-primary"
-    download="audit_logs.json"
-    href="/api/audit_logs/download?from=2020-07-14T12%3A00%3A00.000Z&to=2020-07-21T12%3A00%3A00.000Z"
-    onClick={[MockFunction]}
-    rel="noopener noreferrer"
-    target="_blank"
-  >
-    download_verb
-  </a>
-</Fragment>
-`;
-
-exports[`should render correctly for 30days: default 1`] = `
-<Fragment>
-  <a
-    className="button button-primary"
-    download="audit_logs.json"
-    href="/api/audit_logs/download?from=2020-06-21T12%3A00%3A00.000Z&to=2020-07-21T12%3A00%3A00.000Z"
-    onClick={[MockFunction]}
-    rel="noopener noreferrer"
-    target="_blank"
-  >
-    download_verb
-  </a>
-</Fragment>
-`;
-
-exports[`should render correctly for 90days: default 1`] = `
-<Fragment>
-  <a
-    className="button button-primary"
-    download="audit_logs.json"
-    href="/api/audit_logs/download?from=2020-04-22T12%3A00%3A00.000Z&to=2020-07-21T12%3A00%3A00.000Z"
-    onClick={[MockFunction]}
-    rel="noopener noreferrer"
-    target="_blank"
-  >
-    download_verb
-  </a>
-</Fragment>
-`;
-
-exports[`should render correctly for custom range: no dates 1`] = `
-<Fragment>
-  <a
-    className="button button-primary disabled"
-    download="audit_logs.json"
-    href="#"
-    rel="noopener noreferrer"
-    target="_blank"
-  >
-    download_verb
-  </a>
-</Fragment>
-`;
-
-exports[`should render correctly for custom range: with dates 1`] = `
-<Fragment>
-  <a
-    className="button button-primary"
-    download="audit_logs.json"
-    href="/api/audit_logs/download?from=2020-07-19T12%3A00%3A00.000Z&to=2020-07-21T12%3A00%3A00.000Z"
-    onClick={[MockFunction]}
-    rel="noopener noreferrer"
-    target="_blank"
-  >
-    download_verb
-  </a>
-</Fragment>
-`;
-
-exports[`should render correctly for today: default 1`] = `
-<Fragment>
-  <a
-    className="button button-primary"
-    download="audit_logs.json"
-    href="/api/audit_logs/download?from=2020-07-21T12%3A00%3A00.000Z&to=2020-07-21T12%3A00%3A00.000Z"
-    onClick={[MockFunction]}
-    rel="noopener noreferrer"
-    target="_blank"
-  >
-    download_verb
-  </a>
-</Fragment>
-`;
index b54fbcd0158ed75940e4fbb4d90648dbabaf411d..9ed6b165b109b8fa9c8812fa541138d95e1cbd06 100644 (file)
@@ -191,12 +191,14 @@ export default class DateInput extends React.PureComponent<Props, State> {
                 </ButtonIcon>
                 <div className="date-input-calender-month">
                   <Select
+                    aria-label={translate('select_month')}
                     className="date-input-calender-month-select"
                     onChange={this.handleCurrentMonthChange}
                     options={monthOptions}
                     value={monthOptions.find(month => month.value === currentMonth.getMonth())}
                   />
                   <Select
+                    aria-label={translate('select_year')}
                     className="date-input-calender-month-select spacer-left"
                     onChange={this.handleCurrentYearChange}
                     options={yearOptions}
index 41ff0ea47e1c9c453fecd14a1a7b81f085d082c2..fab0f857c18a7d3a4facad27fc5dc44ac6051669 100644 (file)
@@ -103,6 +103,7 @@ exports[`should render 3`] = `
           className="date-input-calender-month"
         >
           <Select
+            aria-label="select_month"
             className="date-input-calender-month-select"
             onChange={[Function]}
             options={
@@ -165,6 +166,7 @@ exports[`should render 3`] = `
             }
           />
           <Select
+            aria-label="select_year"
             className="date-input-calender-month-select spacer-left"
             onChange={[Function]}
             options={
index de40c1812c37d803eff409999197f69da87a73c5..4045263e11a57067cbdb0bab6195eaa60555803b 100644 (file)
@@ -2408,6 +2408,7 @@ __metadata:
     remark-custom-blocks: 2.5.1
     remark-react: 7
     remark-rehype: 6.0.0
+    testing-library-selector: 0.2.1
     typescript: 4.6.3
     unist-util-visit: 2.0.2
     valid-url: 1.0.9
@@ -10536,6 +10537,15 @@ resolve@^1.3.2:
   languageName: node
   linkType: hard
 
+"testing-library-selector@npm:0.2.1":
+  version: 0.2.1
+  resolution: "testing-library-selector@npm:0.2.1"
+  peerDependencies:
+    "@testing-library/dom": ^8.2.0
+  checksum: 4bb6d071f20b89f7954b03addd6c97479817e348c5a63f2c40693a5a93010b40418d90e30c0dfd7dc2a05e2f66a880ff4b1fa9004e7def5fbf489130b70b050b
+  languageName: node
+  linkType: hard
+
 "text-table@npm:^0.2.0":
   version: 0.2.0
   resolution: "text-table@npm:0.2.0"
index 3bacb7f7a63636f218c871f74e41d6a21d14b46d..c726b2367b04690eaa72a77b446320fbec91cc7f 100644 (file)
@@ -367,6 +367,8 @@ We=We
 Th=Th
 Fr=Fr
 Sa=Sa
+select_month=Select a month
+select_year=Select a year
 
 #------------------------------------------------------------------------------
 #