mirror of
https://github.com/elastic/kibana.git
synced 2025-06-28 11:05:39 -04:00
[ResponseOps][MaintenanceWindows] Fix startDate not forwarded to custom recurrence component (#223949)
## Summary - Forwards `startDate` correctly to the `CustomRecurringSchedule` component. The missing prop caused the monthly custom frequency sub-options to not show up. - Fixes the `CustomRecurringSchedule` component type to correctly reflect the required prop. - Removes the `custom-recurring-form` data test subject from the `<CustomRecurringSchedule>` JSX tag. The test subject wasn't forwarded to any DOM element, but the only test with an assertion using that test subject was passing because it was checking its absence (`not.toBeInTheDocument()`). ## Verification steps 1. Open the Maintenance Window creation page 2. Toggle "Repeat" on 3. In the recurrence form, check that all the custom frequencies work, showing the correct sub-options
This commit is contained in:
parent
d017a33f99
commit
73a2469bff
4 changed files with 156 additions and 131 deletions
|
@ -37,6 +37,8 @@ const TestWrapper = ({ children, iv = initialValue }: PropsWithChildren<{ iv?: F
|
||||||
return <Form form={form}>{children}</Form>;
|
return <Form form={form}>{children}</Form>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const startDate = new Date().toISOString();
|
||||||
|
|
||||||
describe('CustomRecurringSchedule', () => {
|
describe('CustomRecurringSchedule', () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
jest.clearAllMocks();
|
jest.clearAllMocks();
|
||||||
|
@ -45,7 +47,7 @@ describe('CustomRecurringSchedule', () => {
|
||||||
it('renders all form fields', async () => {
|
it('renders all form fields', async () => {
|
||||||
render(
|
render(
|
||||||
<TestWrapper>
|
<TestWrapper>
|
||||||
<CustomRecurringSchedule />
|
<CustomRecurringSchedule startDate={startDate} />
|
||||||
</TestWrapper>
|
</TestWrapper>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -58,7 +60,7 @@ describe('CustomRecurringSchedule', () => {
|
||||||
it('renders byweekday field if custom frequency = weekly', async () => {
|
it('renders byweekday field if custom frequency = weekly', async () => {
|
||||||
render(
|
render(
|
||||||
<TestWrapper>
|
<TestWrapper>
|
||||||
<CustomRecurringSchedule />
|
<CustomRecurringSchedule startDate={startDate} />
|
||||||
</TestWrapper>
|
</TestWrapper>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -83,7 +85,7 @@ describe('CustomRecurringSchedule', () => {
|
||||||
};
|
};
|
||||||
render(
|
render(
|
||||||
<TestWrapper iv={iv}>
|
<TestWrapper iv={iv}>
|
||||||
<CustomRecurringSchedule />
|
<CustomRecurringSchedule startDate={startDate} />
|
||||||
</TestWrapper>
|
</TestWrapper>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -93,7 +95,7 @@ describe('CustomRecurringSchedule', () => {
|
||||||
it('renders bymonth field if custom frequency = monthly', async () => {
|
it('renders bymonth field if custom frequency = monthly', async () => {
|
||||||
render(
|
render(
|
||||||
<TestWrapper>
|
<TestWrapper>
|
||||||
<CustomRecurringSchedule />
|
<CustomRecurringSchedule startDate={startDate} />
|
||||||
</TestWrapper>
|
</TestWrapper>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -111,7 +113,7 @@ describe('CustomRecurringSchedule', () => {
|
||||||
it('should initialize the form when no initialValue provided', () => {
|
it('should initialize the form when no initialValue provided', () => {
|
||||||
render(
|
render(
|
||||||
<TestWrapper>
|
<TestWrapper>
|
||||||
<CustomRecurringSchedule />
|
<CustomRecurringSchedule startDate={startDate} />
|
||||||
</TestWrapper>
|
</TestWrapper>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -139,7 +141,7 @@ describe('CustomRecurringSchedule', () => {
|
||||||
};
|
};
|
||||||
render(
|
render(
|
||||||
<TestWrapper iv={iv}>
|
<TestWrapper iv={iv}>
|
||||||
<CustomRecurringSchedule />
|
<CustomRecurringSchedule startDate={startDate} />
|
||||||
</TestWrapper>
|
</TestWrapper>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
* License v3.0 only", or the "Server Side Public License, v 1".
|
* License v3.0 only", or the "Server Side Public License, v 1".
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import React, { useMemo } from 'react';
|
import React, { memo, useMemo } from 'react';
|
||||||
import { Frequency } from '@kbn/rrule';
|
import { Frequency } from '@kbn/rrule';
|
||||||
import moment from 'moment';
|
import moment from 'moment';
|
||||||
import { css } from '@emotion/react';
|
import { css } from '@emotion/react';
|
||||||
|
@ -42,136 +42,134 @@ const styles = {
|
||||||
};
|
};
|
||||||
|
|
||||||
export interface CustomRecurringScheduleProps {
|
export interface CustomRecurringScheduleProps {
|
||||||
startDate?: string;
|
startDate: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const CustomRecurringSchedule: React.FC = React.memo(
|
export const CustomRecurringSchedule = memo(({ startDate }: CustomRecurringScheduleProps) => {
|
||||||
({ startDate }: CustomRecurringScheduleProps) => {
|
const [{ recurringSchedule }] = useFormData<{ recurringSchedule: RecurringSchedule }>({
|
||||||
const [{ recurringSchedule }] = useFormData<{ recurringSchedule: RecurringSchedule }>({
|
watch: [
|
||||||
watch: [
|
'recurringSchedule.frequency',
|
||||||
'recurringSchedule.frequency',
|
'recurringSchedule.interval',
|
||||||
'recurringSchedule.interval',
|
'recurringSchedule.customFrequency',
|
||||||
'recurringSchedule.customFrequency',
|
],
|
||||||
],
|
});
|
||||||
});
|
|
||||||
|
|
||||||
const parsedSchedule = useMemo(() => {
|
const parsedSchedule = useMemo(() => {
|
||||||
return parseSchedule(recurringSchedule);
|
return parseSchedule(recurringSchedule);
|
||||||
}, [recurringSchedule]);
|
}, [recurringSchedule]);
|
||||||
|
|
||||||
const frequencyOptions = useMemo(
|
const frequencyOptions = useMemo(
|
||||||
() => RECURRING_SCHEDULE_FORM_CUSTOM_FREQUENCY(parsedSchedule?.interval),
|
() => RECURRING_SCHEDULE_FORM_CUSTOM_FREQUENCY(parsedSchedule?.interval),
|
||||||
[parsedSchedule?.interval]
|
[parsedSchedule?.interval]
|
||||||
);
|
);
|
||||||
|
|
||||||
const bymonthOptions = useMemo(() => {
|
const bymonthOptions = useMemo(() => {
|
||||||
if (!startDate) return [];
|
if (!startDate) return [];
|
||||||
const date = moment(startDate);
|
const date = moment(startDate);
|
||||||
const { dayOfWeek, nthWeekdayOfMonth, isLastOfMonth } = getWeekdayInfo(date, 'ddd');
|
const { dayOfWeek, nthWeekdayOfMonth, isLastOfMonth } = getWeekdayInfo(date, 'ddd');
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
id: 'day',
|
id: 'day',
|
||||||
label: RECURRING_SCHEDULE_FORM_CUSTOM_REPEAT_MONTHLY_ON_DAY(date),
|
label: RECURRING_SCHEDULE_FORM_CUSTOM_REPEAT_MONTHLY_ON_DAY(date),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'weekday',
|
id: 'weekday',
|
||||||
label:
|
label:
|
||||||
RECURRING_SCHEDULE_FORM_WEEKDAY_SHORT(dayOfWeek)[isLastOfMonth ? 0 : nthWeekdayOfMonth],
|
RECURRING_SCHEDULE_FORM_WEEKDAY_SHORT(dayOfWeek)[isLastOfMonth ? 0 : nthWeekdayOfMonth],
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
}, [startDate]);
|
}, [startDate]);
|
||||||
|
|
||||||
const defaultByWeekday = useMemo(() => getInitialByWeekday([], moment(startDate)), [startDate]);
|
const defaultByWeekday = useMemo(() => getInitialByWeekday([], moment(startDate)), [startDate]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{parsedSchedule?.frequency !== Frequency.DAILY ? (
|
{parsedSchedule?.frequency !== Frequency.DAILY ? (
|
||||||
<>
|
<>
|
||||||
<EuiSpacer size="s" />
|
<EuiSpacer size="s" />
|
||||||
<EuiFlexGroup gutterSize="s" alignItems="flexStart">
|
<EuiFlexGroup gutterSize="s" alignItems="flexStart">
|
||||||
<EuiFlexItem>
|
<EuiFlexItem>
|
||||||
<UseField
|
<UseField
|
||||||
path="recurringSchedule.interval"
|
path="recurringSchedule.interval"
|
||||||
css={styles.flexField}
|
css={styles.flexField}
|
||||||
componentProps={{
|
componentProps={{
|
||||||
'data-test-subj': 'interval-field',
|
'data-test-subj': 'interval-field',
|
||||||
id: 'interval',
|
id: 'interval',
|
||||||
euiFieldProps: {
|
euiFieldProps: {
|
||||||
'data-test-subj': 'customRecurringScheduleIntervalInput',
|
'data-test-subj': 'customRecurringScheduleIntervalInput',
|
||||||
min: 1,
|
min: 1,
|
||||||
prepend: (
|
prepend: (
|
||||||
<EuiFormLabel htmlFor={'interval'}>
|
<EuiFormLabel htmlFor={'interval'}>
|
||||||
{RECURRING_SCHEDULE_FORM_INTERVAL_EVERY}
|
{RECURRING_SCHEDULE_FORM_INTERVAL_EVERY}
|
||||||
</EuiFormLabel>
|
</EuiFormLabel>
|
||||||
),
|
),
|
||||||
},
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</EuiFlexItem>
|
|
||||||
<EuiFlexItem>
|
|
||||||
<UseField
|
|
||||||
path="recurringSchedule.customFrequency"
|
|
||||||
componentProps={{
|
|
||||||
'data-test-subj': 'custom-frequency-field',
|
|
||||||
euiFieldProps: {
|
|
||||||
'data-test-subj': 'customRecurringScheduleFrequencySelect',
|
|
||||||
options: frequencyOptions,
|
|
||||||
},
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</EuiFlexItem>
|
|
||||||
</EuiFlexGroup>
|
|
||||||
<EuiSpacer size="s" />
|
|
||||||
</>
|
|
||||||
) : null}
|
|
||||||
{Number(parsedSchedule?.customFrequency) === Frequency.WEEKLY ||
|
|
||||||
parsedSchedule?.frequency === Frequency.DAILY ? (
|
|
||||||
<UseField
|
|
||||||
path="recurringSchedule.byweekday"
|
|
||||||
config={{
|
|
||||||
type: FIELD_TYPES.MULTI_BUTTON_GROUP,
|
|
||||||
label: '',
|
|
||||||
validations: [
|
|
||||||
{
|
|
||||||
validator: ({ value }) => {
|
|
||||||
if (
|
|
||||||
Object.values(value as MultiButtonGroupFieldValue).every((v) => v === false)
|
|
||||||
) {
|
|
||||||
return {
|
|
||||||
message: RECURRING_SCHEDULE_FORM_BYWEEKDAY_REQUIRED,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</EuiFlexItem>
|
||||||
|
<EuiFlexItem>
|
||||||
|
<UseField
|
||||||
|
path="recurringSchedule.customFrequency"
|
||||||
|
componentProps={{
|
||||||
|
'data-test-subj': 'custom-frequency-field',
|
||||||
|
euiFieldProps: {
|
||||||
|
'data-test-subj': 'customRecurringScheduleFrequencySelect',
|
||||||
|
options: frequencyOptions,
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</EuiFlexItem>
|
||||||
|
</EuiFlexGroup>
|
||||||
|
<EuiSpacer size="s" />
|
||||||
|
</>
|
||||||
|
) : null}
|
||||||
|
{Number(parsedSchedule?.customFrequency) === Frequency.WEEKLY ||
|
||||||
|
parsedSchedule?.frequency === Frequency.DAILY ? (
|
||||||
|
<UseField
|
||||||
|
path="recurringSchedule.byweekday"
|
||||||
|
config={{
|
||||||
|
type: FIELD_TYPES.MULTI_BUTTON_GROUP,
|
||||||
|
label: '',
|
||||||
|
validations: [
|
||||||
|
{
|
||||||
|
validator: ({ value }) => {
|
||||||
|
if (
|
||||||
|
Object.values(value as MultiButtonGroupFieldValue).every((v) => v === false)
|
||||||
|
) {
|
||||||
|
return {
|
||||||
|
message: RECURRING_SCHEDULE_FORM_BYWEEKDAY_REQUIRED,
|
||||||
|
};
|
||||||
|
}
|
||||||
},
|
},
|
||||||
],
|
|
||||||
defaultValue: defaultByWeekday,
|
|
||||||
}}
|
|
||||||
componentProps={{
|
|
||||||
'data-test-subj': 'byweekday-field',
|
|
||||||
euiFieldProps: {
|
|
||||||
'data-test-subj': 'customRecurringScheduleByWeekdayButtonGroup',
|
|
||||||
legend: 'Repeat on weekday',
|
|
||||||
options: WEEKDAY_OPTIONS,
|
|
||||||
},
|
},
|
||||||
}}
|
],
|
||||||
/>
|
defaultValue: defaultByWeekday,
|
||||||
) : null}
|
}}
|
||||||
|
componentProps={{
|
||||||
|
'data-test-subj': 'byweekday-field',
|
||||||
|
euiFieldProps: {
|
||||||
|
'data-test-subj': 'customRecurringScheduleByWeekdayButtonGroup',
|
||||||
|
legend: 'Repeat on weekday',
|
||||||
|
options: WEEKDAY_OPTIONS,
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
) : null}
|
||||||
|
|
||||||
{Number(parsedSchedule?.customFrequency) === Frequency.MONTHLY ? (
|
{Number(parsedSchedule?.customFrequency) === Frequency.MONTHLY ? (
|
||||||
<UseField
|
<UseField
|
||||||
path="recurringSchedule.bymonth"
|
path="recurringSchedule.bymonth"
|
||||||
componentProps={{
|
componentProps={{
|
||||||
'data-test-subj': 'bymonth-field',
|
'data-test-subj': 'bymonth-field',
|
||||||
euiFieldProps: {
|
euiFieldProps: {
|
||||||
legend: 'Repeat on weekday or month day',
|
legend: 'Repeat on weekday or month day',
|
||||||
options: bymonthOptions,
|
options: bymonthOptions,
|
||||||
},
|
},
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
) : null}
|
) : null}
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
});
|
||||||
);
|
|
||||||
|
|
||||||
CustomRecurringSchedule.displayName = 'CustomRecurringSchedule';
|
CustomRecurringSchedule.displayName = 'CustomRecurringSchedule';
|
||||||
|
|
|
@ -18,6 +18,7 @@ import type { RecurringSchedule } from '../types';
|
||||||
import { Form, useForm } from '@kbn/es-ui-shared-plugin/static/forms/hook_form_lib';
|
import { Form, useForm } from '@kbn/es-ui-shared-plugin/static/forms/hook_form_lib';
|
||||||
import { getRecurringScheduleFormSchema } from '../schemas/recurring_schedule_form_schema';
|
import { getRecurringScheduleFormSchema } from '../schemas/recurring_schedule_form_schema';
|
||||||
import { RecurrenceEnd } from '../constants';
|
import { RecurrenceEnd } from '../constants';
|
||||||
|
import { Frequency } from '@kbn/rrule';
|
||||||
|
|
||||||
const baseProps: RecurringScheduleFieldsProps = {
|
const baseProps: RecurringScheduleFieldsProps = {
|
||||||
startDate: '2023-03-24',
|
startDate: '2023-03-24',
|
||||||
|
@ -29,7 +30,7 @@ interface FormValue {
|
||||||
|
|
||||||
const initialValue: FormValue = {
|
const initialValue: FormValue = {
|
||||||
recurringSchedule: {
|
recurringSchedule: {
|
||||||
frequency: 'CUSTOM',
|
frequency: Frequency.WEEKLY,
|
||||||
ends: RecurrenceEnd.NEVER,
|
ends: RecurrenceEnd.NEVER,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@ -57,7 +58,7 @@ describe('RecurringScheduleForm', () => {
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(screen.getByTestId('frequency-field')).toBeInTheDocument();
|
expect(screen.getByTestId('frequency-field')).toBeInTheDocument();
|
||||||
expect(screen.queryByTestId('custom-recurring-form')).not.toBeInTheDocument();
|
expect(screen.queryByTestId('customRecurringScheduleIntervalInput')).not.toBeInTheDocument();
|
||||||
expect(screen.getByTestId('ends-field')).toBeInTheDocument();
|
expect(screen.getByTestId('ends-field')).toBeInTheDocument();
|
||||||
expect(screen.queryByTestId('until-field')).not.toBeInTheDocument();
|
expect(screen.queryByTestId('until-field')).not.toBeInTheDocument();
|
||||||
expect(screen.queryByTestId('count-field')).not.toBeInTheDocument();
|
expect(screen.queryByTestId('count-field')).not.toBeInTheDocument();
|
||||||
|
@ -88,4 +89,28 @@ describe('RecurringScheduleForm', () => {
|
||||||
await userEvent.click(btn);
|
await userEvent.click(btn);
|
||||||
expect(await screen.findByTestId('count-field')).toBeInTheDocument();
|
expect(await screen.findByTestId('count-field')).toBeInTheDocument();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('renders custom schedule if frequency = daily', async () => {
|
||||||
|
render(
|
||||||
|
<TestWrapper
|
||||||
|
iv={{ recurringSchedule: { frequency: Frequency.DAILY, ends: RecurrenceEnd.NEVER } }}
|
||||||
|
>
|
||||||
|
<RecurringScheduleFormFields {...baseProps} />
|
||||||
|
</TestWrapper>
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(
|
||||||
|
await screen.findByTestId('customRecurringScheduleByWeekdayButtonGroup')
|
||||||
|
).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('renders custom schedule if frequency = custom', async () => {
|
||||||
|
render(
|
||||||
|
<TestWrapper iv={{ recurringSchedule: { frequency: 'CUSTOM', ends: RecurrenceEnd.NEVER } }}>
|
||||||
|
<RecurringScheduleFormFields {...baseProps} />
|
||||||
|
</TestWrapper>
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(await screen.findByTestId('customRecurringScheduleIntervalInput')).toBeInTheDocument();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -59,7 +59,7 @@ export const toMoment = (value: string): Moment => moment(value);
|
||||||
export const toString = (value: Moment): string => value.toISOString();
|
export const toString = (value: Moment): string => value.toISOString();
|
||||||
|
|
||||||
export interface RecurringScheduleFieldsProps {
|
export interface RecurringScheduleFieldsProps {
|
||||||
startDate?: string;
|
startDate: string;
|
||||||
endDate?: string;
|
endDate?: string;
|
||||||
timezone?: string[];
|
timezone?: string[];
|
||||||
allowInfiniteRecurrence?: boolean;
|
allowInfiniteRecurrence?: boolean;
|
||||||
|
@ -147,7 +147,7 @@ export const RecurringScheduleFormFields = memo(
|
||||||
/>
|
/>
|
||||||
{(parsedSchedule?.frequency === Frequency.DAILY ||
|
{(parsedSchedule?.frequency === Frequency.DAILY ||
|
||||||
parsedSchedule?.frequency === 'CUSTOM') && (
|
parsedSchedule?.frequency === 'CUSTOM') && (
|
||||||
<CustomRecurringSchedule data-test-subj="custom-recurring-form" />
|
<CustomRecurringSchedule startDate={startDate} />
|
||||||
)}
|
)}
|
||||||
<UseField
|
<UseField
|
||||||
path="recurringSchedule.ends"
|
path="recurringSchedule.ends"
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue