Browse Source

SONAR-17365 Refactor audit app enzyme to RTL

tags/9.7.0.61563
Mathieu Suen 1 year ago
parent
commit
8723b6a9d7

+ 1
- 0
server/sonar-web/package.json View File

@@ -105,6 +105,7 @@
"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"
},

server/sonar-web/src/main/js/api/mocks/AuditLogsServiceMock.ts → server/sonar-web/src/main/js/api/mocks/SettingsServiceMock.ts View File

@@ -19,12 +19,15 @@
*/
import { cloneDeep } from 'lodash';
import { HousekeepingPolicy } from '../../apps/audit-logs/utils';
import { SettingValue } from '../../types/settings';
import { SettingsKey, SettingValue } from '../../types/settings';
import { getValue } from '../settings';

export default class AuditLogsServiceMock {
settingValue: SettingValue;
defaultValues: SettingValue = { key: 'test', value: HousekeepingPolicy.Weekly };
export default class SettingsServiceMock {
settingValue?: SettingValue;
defaultValues: SettingValue = {
key: SettingsKey.AuditHouseKeeping,
value: HousekeepingPolicy.Weekly
};

constructor() {
this.settingValue = cloneDeep(this.defaultValues);
@@ -35,6 +38,14 @@ export default class AuditLogsServiceMock {
return Promise.resolve(this.settingValue);
};

unsetHousekeepingPolicy() {
this.settingValue = undefined;
}

setYearlyHousekeepingPolicy() {
this.settingValue = { key: 'test', value: HousekeepingPolicy.Yearly };
}

resetSettingvalues = () => {
this.settingValue = cloneDeep(this.defaultValues);
};

+ 0
- 6
server/sonar-web/src/main/js/apps/audit-logs/components/AuditApp.tsx View 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 });


+ 3
- 0
server/sonar-web/src/main/js/apps/audit-logs/components/DownloadButton.tsx View 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"

+ 118
- 15
server/sonar-web/src/main/js/apps/audit-logs/components/__tests__/AuditApp-it.tsx View File

@@ -19,7 +19,12 @@
*/
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 });
}

+ 0
- 110
server/sonar-web/src/main/js/apps/audit-logs/components/__tests__/AuditApp-test.tsx View File

@@ -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}
/>
);
}

+ 0
- 55
server/sonar-web/src/main/js/apps/audit-logs/components/__tests__/AuditAppRenderer-test.tsx View File

@@ -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}
/>
);
}

+ 0
- 81
server/sonar-web/src/main/js/apps/audit-logs/components/__tests__/DownloadButton-test.tsx View File

@@ -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}
/>
);
}

+ 0
- 12
server/sonar-web/src/main/js/apps/audit-logs/components/__tests__/__snapshots__/AuditApp-test.tsx.snap View File

@@ -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"
/>
`;

+ 0
- 501
server/sonar-web/src/main/js/apps/audit-logs/components/__tests__/__snapshots__/AuditAppRenderer-test.tsx.snap View File

@@ -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>
`;

+ 0
- 90
server/sonar-web/src/main/js/apps/audit-logs/components/__tests__/__snapshots__/DownloadButton-test.tsx.snap View File

@@ -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>
`;

+ 2
- 0
server/sonar-web/src/main/js/components/controls/DateInput.tsx View 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}

+ 2
- 0
server/sonar-web/src/main/js/components/controls/__tests__/__snapshots__/DateInput-test.tsx.snap View 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={

+ 10
- 0
server/sonar-web/yarn.lock View 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"

+ 2
- 0
sonar-core/src/main/resources/org/sonar/l10n/core.properties View File

@@ -367,6 +367,8 @@ We=We
Th=Th
Fr=Fr
Sa=Sa
select_month=Select a month
select_year=Select a year

#------------------------------------------------------------------------------
#

Loading…
Cancel
Save