mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 09:48:58 -04:00
Uptime - Remove timeout for browser monitors (#122498)
* remove timeout for browser monitors * adjust types * update tests Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
parent
b6ff8a6859
commit
99fc4eab1a
17 changed files with 262 additions and 92 deletions
|
@ -48,18 +48,22 @@ export const ZipUrlTLSFieldsCodec = t.partial({
|
|||
export type ZipUrlTLSFields = t.TypeOf<typeof ZipUrlTLSFieldsCodec>;
|
||||
|
||||
// CommonFields
|
||||
export const CommonFieldsCodec = t.interface({
|
||||
[ConfigKey.NAME]: t.string,
|
||||
[ConfigKey.NAMESPACE]: t.string,
|
||||
[ConfigKey.MONITOR_TYPE]: DataStreamCodec,
|
||||
[ConfigKey.ENABLED]: t.boolean,
|
||||
[ConfigKey.SCHEDULE]: Schedule,
|
||||
[ConfigKey.LOCATIONS]: t.array(t.string),
|
||||
[ConfigKey.APM_SERVICE_NAME]: t.string,
|
||||
[ConfigKey.TIMEOUT]: t.string,
|
||||
[ConfigKey.TAGS]: t.array(t.string),
|
||||
[ConfigKey.LOCATIONS]: ServiceLocationsCodec,
|
||||
});
|
||||
export const CommonFieldsCodec = t.intersection([
|
||||
t.interface({
|
||||
[ConfigKey.NAME]: t.string,
|
||||
[ConfigKey.NAMESPACE]: t.string,
|
||||
[ConfigKey.MONITOR_TYPE]: DataStreamCodec,
|
||||
[ConfigKey.ENABLED]: t.boolean,
|
||||
[ConfigKey.SCHEDULE]: Schedule,
|
||||
[ConfigKey.LOCATIONS]: t.array(t.string),
|
||||
[ConfigKey.APM_SERVICE_NAME]: t.string,
|
||||
[ConfigKey.TAGS]: t.array(t.string),
|
||||
[ConfigKey.LOCATIONS]: ServiceLocationsCodec,
|
||||
}),
|
||||
t.partial({
|
||||
[ConfigKey.TIMEOUT]: t.union([t.string, t.null]),
|
||||
}),
|
||||
]);
|
||||
|
||||
export type CommonFields = t.TypeOf<typeof CommonFieldsCodec>;
|
||||
|
||||
|
|
|
@ -21,9 +21,12 @@ interface Props {
|
|||
|
||||
export const BrowserSimpleFields = memo<Props>(({ validate }) => {
|
||||
const { fields, setFields, defaultValues } = useBrowserSimpleFieldsContext();
|
||||
const handleInputChange = ({ value, configKey }: { value: unknown; configKey: ConfigKey }) => {
|
||||
setFields((prevFields) => ({ ...prevFields, [configKey]: value }));
|
||||
};
|
||||
const handleInputChange = useCallback(
|
||||
({ value, configKey }: { value: unknown; configKey: ConfigKey }) => {
|
||||
setFields((prevFields) => ({ ...prevFields, [configKey]: value }));
|
||||
},
|
||||
[setFields]
|
||||
);
|
||||
const onChangeSourceField = useCallback(
|
||||
({
|
||||
zipUrl,
|
||||
|
|
|
@ -5,21 +5,41 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import React, { useEffect } from 'react';
|
||||
import { FormattedMessage } from '@kbn/i18n-react';
|
||||
import { EuiFormRow, EuiFieldText, EuiFieldNumber } from '@elastic/eui';
|
||||
import { Validation } from '../types';
|
||||
import { Validation, DataStream } from '../types';
|
||||
import { ConfigKey, CommonFields as CommonFieldsType } from '../types';
|
||||
import { ComboBox } from '../combo_box';
|
||||
import { OptionalLabel } from '../optional_label';
|
||||
import { usePolicyConfigContext } from '../contexts';
|
||||
|
||||
interface Props {
|
||||
validate: Validation;
|
||||
fields: CommonFieldsType;
|
||||
onChange: ({ value, configKey }: { value: string | string[]; configKey: ConfigKey }) => void;
|
||||
onChange: ({
|
||||
value,
|
||||
configKey,
|
||||
}: {
|
||||
value: string | string[] | null;
|
||||
configKey: ConfigKey;
|
||||
}) => void;
|
||||
}
|
||||
|
||||
export function CommonFields({ fields, onChange, validate }: Props) {
|
||||
const { monitorType } = usePolicyConfigContext();
|
||||
|
||||
const isBrowser = monitorType === DataStream.BROWSER;
|
||||
|
||||
useEffect(() => {
|
||||
if (monitorType === DataStream.BROWSER) {
|
||||
onChange({
|
||||
value: null,
|
||||
configKey: ConfigKey.TIMEOUT,
|
||||
});
|
||||
}
|
||||
}, [onChange, monitorType]);
|
||||
|
||||
return (
|
||||
<>
|
||||
<EuiFormRow
|
||||
|
@ -48,46 +68,48 @@ export function CommonFields({ fields, onChange, validate }: Props) {
|
|||
data-test-subj="syntheticsAPMServiceName"
|
||||
/>
|
||||
</EuiFormRow>
|
||||
<EuiFormRow
|
||||
label={
|
||||
<FormattedMessage
|
||||
id="xpack.uptime.createPackagePolicy.stepConfigure.monitorIntegrationSettingsSection.timeout.label"
|
||||
defaultMessage="Timeout in seconds"
|
||||
/>
|
||||
}
|
||||
isInvalid={!!validate[ConfigKey.TIMEOUT]?.(fields)}
|
||||
error={
|
||||
parseInt(fields[ConfigKey.TIMEOUT], 10) < 0 ? (
|
||||
{!isBrowser && (
|
||||
<EuiFormRow
|
||||
label={
|
||||
<FormattedMessage
|
||||
id="xpack.uptime.createPackagePolicy.stepConfigure.monitorIntegrationSettingsSection.timeout.moreThanZeroError"
|
||||
defaultMessage="Timeout must be greater than or equal to 0"
|
||||
id="xpack.uptime.createPackagePolicy.stepConfigure.monitorIntegrationSettingsSection.timeout.label"
|
||||
defaultMessage="Timeout in seconds"
|
||||
/>
|
||||
) : (
|
||||
<FormattedMessage
|
||||
id="xpack.uptime.createPackagePolicy.stepConfigure.monitorIntegrationSettingsSection.timeout.lessThanIntervalError"
|
||||
defaultMessage="Timeout must be less than the monitor interval"
|
||||
/>
|
||||
)
|
||||
}
|
||||
helpText={
|
||||
<FormattedMessage
|
||||
id="xpack.uptime.createPackagePolicy.stepConfigure.monitorIntegrationSettingsSection.timeout.helpText"
|
||||
defaultMessage="The total time allowed for testing the connection and exchanging data."
|
||||
/>
|
||||
}
|
||||
>
|
||||
<EuiFieldNumber
|
||||
min={0}
|
||||
value={fields[ConfigKey.TIMEOUT]}
|
||||
onChange={(event) =>
|
||||
onChange({
|
||||
value: event.target.value,
|
||||
configKey: ConfigKey.TIMEOUT,
|
||||
})
|
||||
}
|
||||
step={'any'}
|
||||
/>
|
||||
</EuiFormRow>
|
||||
isInvalid={!!validate[ConfigKey.TIMEOUT]?.(fields)}
|
||||
error={
|
||||
parseInt(fields[ConfigKey.TIMEOUT] || '', 10) < 0 ? (
|
||||
<FormattedMessage
|
||||
id="xpack.uptime.createPackagePolicy.stepConfigure.monitorIntegrationSettingsSection.timeout.moreThanZeroError"
|
||||
defaultMessage="Timeout must be greater than or equal to 0"
|
||||
/>
|
||||
) : (
|
||||
<FormattedMessage
|
||||
id="xpack.uptime.createPackagePolicy.stepConfigure.monitorIntegrationSettingsSection.timeout.lessThanIntervalError"
|
||||
defaultMessage="Timeout must be less than the monitor interval"
|
||||
/>
|
||||
)
|
||||
}
|
||||
helpText={
|
||||
<FormattedMessage
|
||||
id="xpack.uptime.createPackagePolicy.stepConfigure.monitorIntegrationSettingsSection.timeout.helpText"
|
||||
defaultMessage="The total time allowed for testing the connection and exchanging data."
|
||||
/>
|
||||
}
|
||||
>
|
||||
<EuiFieldNumber
|
||||
min={0}
|
||||
value={fields[ConfigKey.TIMEOUT] || ''}
|
||||
onChange={(event) =>
|
||||
onChange({
|
||||
value: event.target.value,
|
||||
configKey: ConfigKey.TIMEOUT,
|
||||
})
|
||||
}
|
||||
step={'any'}
|
||||
/>
|
||||
</EuiFormRow>
|
||||
)}
|
||||
<EuiFormRow
|
||||
label={
|
||||
<FormattedMessage
|
||||
|
|
|
@ -22,7 +22,7 @@ export const commonFormatters: CommonFormatMap = {
|
|||
),
|
||||
[ConfigKey.APM_SERVICE_NAME]: null,
|
||||
[ConfigKey.TAGS]: (fields) => arrayToJsonFormatter(fields[ConfigKey.TAGS]),
|
||||
[ConfigKey.TIMEOUT]: (fields) => secondsToCronFormatter(fields[ConfigKey.TIMEOUT]),
|
||||
[ConfigKey.TIMEOUT]: (fields) => secondsToCronFormatter(fields[ConfigKey.TIMEOUT] || undefined),
|
||||
[ConfigKey.NAMESPACE]: null,
|
||||
};
|
||||
|
||||
|
|
|
@ -255,6 +255,28 @@ describe('<CustomFields />', () => {
|
|||
expect(queryByLabelText('Wait in seconds')).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('does not show timeout for browser monitors', () => {
|
||||
const { getByLabelText, queryByLabelText } = render(<WrappedComponent />);
|
||||
const monitorType = getByLabelText('Monitor Type') as HTMLInputElement;
|
||||
let timeout = getByLabelText('Timeout in seconds') as HTMLInputElement;
|
||||
expect(monitorType).toBeInTheDocument();
|
||||
expect(monitorType.value).toEqual(defaultHTTPConfig[ConfigKey.MONITOR_TYPE]);
|
||||
expect(timeout.value).toEqual(defaultHTTPConfig[ConfigKey.TIMEOUT]);
|
||||
|
||||
// change to browser monitor
|
||||
fireEvent.change(monitorType, { target: { value: DataStream.BROWSER } });
|
||||
|
||||
// expect timeout not to be in the DOM
|
||||
expect(queryByLabelText('Timeout in seconds')).not.toBeInTheDocument();
|
||||
|
||||
// change back to HTTP
|
||||
fireEvent.change(monitorType, { target: { value: DataStream.HTTP } });
|
||||
|
||||
// expect timeout value to be present with the correct value
|
||||
timeout = getByLabelText('Timeout in seconds') as HTMLInputElement;
|
||||
expect(timeout.value).toEqual(defaultHTTPConfig[ConfigKey.TIMEOUT]);
|
||||
});
|
||||
|
||||
it('shows resolve hostnames locally field when proxy url is filled for tcp monitors', () => {
|
||||
const { getByLabelText, queryByLabelText } = render(<WrappedComponent />);
|
||||
const monitorType = getByLabelText('Monitor Type') as HTMLInputElement;
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import React, { memo } from 'react';
|
||||
import React, { memo, useCallback } from 'react';
|
||||
import { FormattedMessage } from '@kbn/i18n-react';
|
||||
import { EuiFormRow, EuiFieldText, EuiFieldNumber } from '@elastic/eui';
|
||||
import { ConfigKey, Validation } from '../types';
|
||||
|
@ -20,9 +20,12 @@ interface Props {
|
|||
|
||||
export const HTTPSimpleFields = memo<Props>(({ validate }) => {
|
||||
const { fields, setFields } = useHTTPSimpleFieldsContext();
|
||||
const handleInputChange = ({ value, configKey }: { value: unknown; configKey: ConfigKey }) => {
|
||||
setFields((prevFields) => ({ ...prevFields, [configKey]: value }));
|
||||
};
|
||||
const handleInputChange = useCallback(
|
||||
({ value, configKey }: { value: unknown; configKey: ConfigKey }) => {
|
||||
setFields((prevFields) => ({ ...prevFields, [configKey]: value }));
|
||||
},
|
||||
[setFields]
|
||||
);
|
||||
|
||||
return (
|
||||
<SimpleFieldsWrapper fields={fields} validate={validate} onInputChange={handleInputChange}>
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import React, { memo } from 'react';
|
||||
import React, { memo, useCallback } from 'react';
|
||||
import { FormattedMessage } from '@kbn/i18n-react';
|
||||
import { EuiFormRow, EuiFieldText, EuiFieldNumber } from '@elastic/eui';
|
||||
import { ConfigKey, Validation } from '../types';
|
||||
|
@ -20,9 +20,12 @@ interface Props {
|
|||
|
||||
export const ICMPSimpleFields = memo<Props>(({ validate }) => {
|
||||
const { fields, setFields } = useICMPSimpleFieldsContext();
|
||||
const handleInputChange = ({ value, configKey }: { value: unknown; configKey: ConfigKey }) => {
|
||||
setFields((prevFields) => ({ ...prevFields, [configKey]: value }));
|
||||
};
|
||||
const handleInputChange = useCallback(
|
||||
({ value, configKey }: { value: unknown; configKey: ConfigKey }) => {
|
||||
setFields((prevFields) => ({ ...prevFields, [configKey]: value }));
|
||||
},
|
||||
[setFields]
|
||||
);
|
||||
|
||||
return (
|
||||
<SimpleFieldsWrapper fields={fields} validate={validate} onInputChange={handleInputChange}>
|
||||
|
|
|
@ -710,21 +710,17 @@ describe('<SyntheticsPolicyCreateExtension />', () => {
|
|||
|
||||
const zipUrl = getByRole('textbox', { name: 'Zip URL' }) as HTMLInputElement;
|
||||
const monitorIntervalNumber = getByLabelText('Number') as HTMLInputElement;
|
||||
const timeout = getByLabelText('Timeout in seconds') as HTMLInputElement;
|
||||
|
||||
// create errors
|
||||
fireEvent.change(zipUrl, { target: { value: '' } });
|
||||
fireEvent.change(monitorIntervalNumber, { target: { value: '-1' } });
|
||||
fireEvent.change(timeout, { target: { value: '-1' } });
|
||||
|
||||
await waitFor(() => {
|
||||
const hostError = getByText('Zip URL is required');
|
||||
const monitorIntervalError = getByText('Monitor interval is required');
|
||||
const timeoutError = getByText('Timeout must be greater than or equal to 0');
|
||||
|
||||
expect(hostError).toBeInTheDocument();
|
||||
expect(monitorIntervalError).toBeInTheDocument();
|
||||
expect(timeoutError).toBeInTheDocument();
|
||||
expect(onChange).toBeCalledWith(
|
||||
expect.objectContaining({
|
||||
isValid: false,
|
||||
|
@ -735,12 +731,10 @@ describe('<SyntheticsPolicyCreateExtension />', () => {
|
|||
// resolve errors
|
||||
fireEvent.change(zipUrl, { target: { value: 'http://github.com/tests.zip' } });
|
||||
fireEvent.change(monitorIntervalNumber, { target: { value: '1' } });
|
||||
fireEvent.change(timeout, { target: { value: '1' } });
|
||||
|
||||
await waitFor(() => {
|
||||
expect(queryByText('Zip URL is required')).not.toBeInTheDocument();
|
||||
expect(queryByText('Monitor interval is required')).not.toBeInTheDocument();
|
||||
expect(queryByText('Timeout must be greater than or equal to 0')).not.toBeInTheDocument();
|
||||
expect(onChange).toBeCalledWith(
|
||||
expect.objectContaining({
|
||||
isValid: true,
|
||||
|
|
|
@ -643,21 +643,17 @@ describe('<SyntheticsPolicyEditExtension />', () => {
|
|||
|
||||
const zipUrl = getByRole('textbox', { name: 'Zip URL' }) as HTMLInputElement;
|
||||
const monitorIntervalNumber = getByLabelText('Number') as HTMLInputElement;
|
||||
const timeout = getByLabelText('Timeout in seconds') as HTMLInputElement;
|
||||
|
||||
// create errors
|
||||
fireEvent.change(zipUrl, { target: { value: '' } });
|
||||
fireEvent.change(monitorIntervalNumber, { target: { value: '-1' } });
|
||||
fireEvent.change(timeout, { target: { value: '-1' } });
|
||||
|
||||
await waitFor(() => {
|
||||
const hostError = getByText('Zip URL is required');
|
||||
const monitorIntervalError = getByText('Monitor interval is required');
|
||||
const timeoutError = getByText('Timeout must be greater than or equal to 0');
|
||||
|
||||
expect(hostError).toBeInTheDocument();
|
||||
expect(monitorIntervalError).toBeInTheDocument();
|
||||
expect(timeoutError).toBeInTheDocument();
|
||||
expect(onChange).toBeCalledWith(
|
||||
expect.objectContaining({
|
||||
isValid: false,
|
||||
|
@ -668,10 +664,8 @@ describe('<SyntheticsPolicyEditExtension />', () => {
|
|||
await waitFor(() => {
|
||||
fireEvent.change(zipUrl, { target: { value: 'http://github.com/tests.zip' } });
|
||||
fireEvent.change(monitorIntervalNumber, { target: { value: '2' } });
|
||||
fireEvent.change(timeout, { target: { value: '1' } });
|
||||
expect(zipUrl.value).toEqual('http://github.com/tests.zip');
|
||||
expect(monitorIntervalNumber.value).toEqual('2');
|
||||
expect(timeout.value).toEqual('1');
|
||||
expect(queryByText('Zip URL is required')).not.toBeInTheDocument();
|
||||
expect(queryByText('Monitor interval is required')).not.toBeInTheDocument();
|
||||
expect(queryByText('Timeout must be greater than or equal to 0')).not.toBeInTheDocument();
|
||||
|
@ -1088,7 +1082,6 @@ describe('<SyntheticsPolicyEditExtension />', () => {
|
|||
const monitorIntervalNumber = getByLabelText('Number') as HTMLInputElement;
|
||||
const monitorIntervalUnit = getByLabelText('Unit') as HTMLInputElement;
|
||||
const apmServiceName = getByLabelText('APM service name') as HTMLInputElement;
|
||||
const timeout = getByLabelText('Timeout in seconds') as HTMLInputElement;
|
||||
expect(zipUrl).toBeInTheDocument();
|
||||
expect(zipUrl.value).toEqual(defaultBrowserConfig[ConfigKey.SOURCE_ZIP_URL]);
|
||||
expect(monitorIntervalNumber).toBeInTheDocument();
|
||||
|
@ -1097,8 +1090,6 @@ describe('<SyntheticsPolicyEditExtension />', () => {
|
|||
expect(monitorIntervalUnit.value).toEqual(defaultBrowserConfig[ConfigKey.SCHEDULE].unit);
|
||||
expect(apmServiceName).toBeInTheDocument();
|
||||
expect(apmServiceName.value).toEqual(defaultBrowserConfig[ConfigKey.APM_SERVICE_NAME]);
|
||||
expect(timeout).toBeInTheDocument();
|
||||
expect(timeout.value).toEqual(`${defaultBrowserConfig[ConfigKey.TIMEOUT]}`);
|
||||
|
||||
// ensure other monitor type options are not in the DOM
|
||||
expect(queryByLabelText('Url')).not.toBeInTheDocument();
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import React, { memo } from 'react';
|
||||
import React, { memo, useCallback } from 'react';
|
||||
import { FormattedMessage } from '@kbn/i18n-react';
|
||||
import { EuiFormRow, EuiFieldText } from '@elastic/eui';
|
||||
import { ConfigKey, Validation } from '../types';
|
||||
|
@ -19,9 +19,12 @@ interface Props {
|
|||
|
||||
export const TCPSimpleFields = memo<Props>(({ validate }) => {
|
||||
const { fields, setFields } = useTCPSimpleFieldsContext();
|
||||
const handleInputChange = ({ value, configKey }: { value: unknown; configKey: ConfigKey }) => {
|
||||
setFields((prevFields) => ({ ...prevFields, [configKey]: value }));
|
||||
};
|
||||
const handleInputChange = useCallback(
|
||||
({ value, configKey }: { value: unknown; configKey: ConfigKey }) => {
|
||||
setFields((prevFields) => ({ ...prevFields, [configKey]: value }));
|
||||
},
|
||||
[setFields]
|
||||
);
|
||||
|
||||
return (
|
||||
<SimpleFieldsWrapper fields={fields} validate={validate} onInputChange={handleInputChange}>
|
||||
|
|
|
@ -0,0 +1,74 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import {
|
||||
ConfigKey,
|
||||
DataStream,
|
||||
HTTPFields,
|
||||
BrowserFields,
|
||||
MonitorFields,
|
||||
ScheduleUnit,
|
||||
} from '../../../common/runtime_types';
|
||||
import { validate } from './validation';
|
||||
|
||||
describe('[Monitor Management] validation', () => {
|
||||
const commonPropsValid: Partial<MonitorFields> = {
|
||||
[ConfigKey.SCHEDULE]: { number: '5', unit: ScheduleUnit.MINUTES },
|
||||
[ConfigKey.TIMEOUT]: '3m',
|
||||
};
|
||||
|
||||
describe('HTTP', () => {
|
||||
const httpPropsValid: Partial<HTTPFields> = {
|
||||
...commonPropsValid,
|
||||
[ConfigKey.RESPONSE_STATUS_CHECK]: ['200', '204'],
|
||||
[ConfigKey.RESPONSE_HEADERS_CHECK]: { 'Content-Type': 'application/json' },
|
||||
[ConfigKey.REQUEST_HEADERS_CHECK]: { 'Accept-Language': 'en-GB,en-US;q=0.9,en;q=0.8' },
|
||||
[ConfigKey.MAX_REDIRECTS]: '3',
|
||||
[ConfigKey.URLS]: 'https:// example-url.com',
|
||||
};
|
||||
|
||||
it('should return false for all valid props', () => {
|
||||
const validators = validate[DataStream.HTTP];
|
||||
const keysToValidate = [
|
||||
ConfigKey.SCHEDULE,
|
||||
ConfigKey.TIMEOUT,
|
||||
ConfigKey.RESPONSE_STATUS_CHECK,
|
||||
ConfigKey.RESPONSE_HEADERS_CHECK,
|
||||
ConfigKey.REQUEST_HEADERS_CHECK,
|
||||
ConfigKey.MAX_REDIRECTS,
|
||||
ConfigKey.URLS,
|
||||
];
|
||||
const validatorFns = keysToValidate.map((key) => validators[key]);
|
||||
const result = validatorFns.map((fn) => fn?.(httpPropsValid) ?? true);
|
||||
|
||||
expect(result).not.toEqual(expect.arrayContaining([true]));
|
||||
});
|
||||
});
|
||||
|
||||
describe.each([
|
||||
[ConfigKey.SOURCE_INLINE, 'step(() => {});'],
|
||||
[ConfigKey.SOURCE_ZIP_URL, 'https://test.zip'],
|
||||
])('Browser', (configKey, value) => {
|
||||
const browserProps: Partial<BrowserFields> = {
|
||||
...commonPropsValid,
|
||||
[ConfigKey.MONITOR_TYPE]: DataStream.BROWSER,
|
||||
[ConfigKey.TIMEOUT]: null,
|
||||
[configKey]: value,
|
||||
};
|
||||
|
||||
it('should return false for all valid props', () => {
|
||||
const validators = validate[DataStream.BROWSER];
|
||||
const keysToValidate = [ConfigKey.SCHEDULE, ConfigKey.TIMEOUT, configKey];
|
||||
const validatorFns = keysToValidate.map((key) => validators[key]);
|
||||
const result = validatorFns.map((fn) => fn?.(browserProps) ?? true);
|
||||
|
||||
expect(result).not.toEqual(expect.arrayContaining([true]));
|
||||
});
|
||||
});
|
||||
|
||||
// TODO: Add test for other monitor types if needed
|
||||
});
|
|
@ -55,9 +55,18 @@ const validateCommon: ValidationLibrary = {
|
|||
const parsedFloat = parseFloat(number);
|
||||
return !parsedFloat || !unit || parsedFloat < 1;
|
||||
},
|
||||
[ConfigKey.TIMEOUT]: ({ [ConfigKey.TIMEOUT]: timeout, [ConfigKey.SCHEDULE]: schedule }) => {
|
||||
[ConfigKey.TIMEOUT]: ({
|
||||
[ConfigKey.MONITOR_TYPE]: monitorType,
|
||||
[ConfigKey.TIMEOUT]: timeout,
|
||||
[ConfigKey.SCHEDULE]: schedule,
|
||||
}) => {
|
||||
const { number, unit } = schedule as MonitorFields[ConfigKey.SCHEDULE];
|
||||
|
||||
// Timeout is not currently supported by browser monitors
|
||||
if (monitorType === DataStream.BROWSER) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return (
|
||||
!timeout ||
|
||||
parseFloat(timeout) < 0 ||
|
||||
|
|
|
@ -9,6 +9,7 @@ import {
|
|||
ConfigKey,
|
||||
DataStream,
|
||||
HTTPFields,
|
||||
BrowserFields,
|
||||
MonitorFields,
|
||||
ScheduleUnit,
|
||||
ServiceLocations,
|
||||
|
@ -90,5 +91,37 @@ describe('[Monitor Management] validation', () => {
|
|||
});
|
||||
});
|
||||
|
||||
describe.each([
|
||||
[ConfigKey.SOURCE_INLINE, 'step(() => {});'],
|
||||
[ConfigKey.SOURCE_ZIP_URL, 'https://test.zip'],
|
||||
])('Browser', (configKey, value) => {
|
||||
const browserProps: Partial<BrowserFields> = {
|
||||
...commonPropsValid,
|
||||
[ConfigKey.MONITOR_TYPE]: DataStream.BROWSER,
|
||||
[ConfigKey.TIMEOUT]: undefined,
|
||||
[configKey]: value,
|
||||
};
|
||||
|
||||
it('should return false for all valid props', () => {
|
||||
const validators = validate[DataStream.BROWSER];
|
||||
const keysToValidate = [ConfigKey.SCHEDULE, ConfigKey.TIMEOUT, configKey];
|
||||
const validatorFns = keysToValidate.map((key) => validators[key]);
|
||||
const result = validatorFns.map((fn) => fn?.(browserProps) ?? true);
|
||||
|
||||
expect(result).not.toEqual(expect.arrayContaining([true]));
|
||||
});
|
||||
|
||||
it('should invalidate when locations is empty', () => {
|
||||
const validators = validate[DataStream.BROWSER];
|
||||
const validatorFn = validators[ConfigKey.LOCATIONS];
|
||||
const result = [undefined, null, []].map(
|
||||
(testValue) =>
|
||||
validatorFn?.({ [ConfigKey.LOCATIONS]: testValue } as Partial<MonitorFields>) ?? false
|
||||
);
|
||||
|
||||
expect(result).toEqual([true, true, true]);
|
||||
});
|
||||
});
|
||||
|
||||
// TODO: Add test for other monitor types if needed
|
||||
});
|
||||
|
|
|
@ -64,9 +64,18 @@ export const validateCommon: Validation = {
|
|||
const parsedFloat = parseFloat(number);
|
||||
return !parsedFloat || !unit || parsedFloat < 1;
|
||||
},
|
||||
[ConfigKey.TIMEOUT]: ({ [ConfigKey.TIMEOUT]: timeout, [ConfigKey.SCHEDULE]: schedule }) => {
|
||||
[ConfigKey.TIMEOUT]: ({
|
||||
[ConfigKey.MONITOR_TYPE]: monitorType,
|
||||
[ConfigKey.TIMEOUT]: timeout,
|
||||
[ConfigKey.SCHEDULE]: schedule,
|
||||
}) => {
|
||||
const { number, unit } = schedule as MonitorFields[ConfigKey.SCHEDULE];
|
||||
|
||||
// Timeout is not currently supported by browser monitors
|
||||
if (monitorType === DataStream.BROWSER) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return (
|
||||
!timeout ||
|
||||
parseFloat(timeout) < 0 ||
|
||||
|
|
|
@ -23,7 +23,7 @@ export const commonFormatters: CommonFormatMap = {
|
|||
`@every ${fields[ConfigKey.SCHEDULE]?.number}${fields[ConfigKey.SCHEDULE]?.unit}`,
|
||||
[ConfigKey.APM_SERVICE_NAME]: null,
|
||||
[ConfigKey.TAGS]: (fields) => arrayFormatter(fields[ConfigKey.TAGS]),
|
||||
[ConfigKey.TIMEOUT]: (fields) => secondsToCronFormatter(fields[ConfigKey.TIMEOUT]),
|
||||
[ConfigKey.TIMEOUT]: (fields) => secondsToCronFormatter(fields[ConfigKey.TIMEOUT] || undefined),
|
||||
[ConfigKey.NAMESPACE]: null,
|
||||
};
|
||||
|
||||
|
|
|
@ -282,14 +282,14 @@ describe('validateMonitor', () => {
|
|||
const testMonitor = {
|
||||
...testTCPFields,
|
||||
...({
|
||||
[ConfigKey.TIMEOUT]: undefined,
|
||||
[ConfigKey.NAME]: undefined,
|
||||
} as unknown as Partial<TCPFields>),
|
||||
} as MonitorFields;
|
||||
|
||||
const result = validateMonitor(testMonitor);
|
||||
|
||||
expect(result.details).toEqual(expect.stringContaining('Invalid value'));
|
||||
expect(result.details).toEqual(expect.stringContaining(ConfigKey.TIMEOUT));
|
||||
expect(result.details).toEqual(expect.stringContaining(ConfigKey.NAME));
|
||||
expect(result).toMatchObject({
|
||||
valid: false,
|
||||
reason: `Monitor is not a valid monitor of type ${DataStream.TCP}`,
|
||||
|
|
|
@ -555,7 +555,7 @@ export default function (providerContext: FtrProviderContext) {
|
|||
config: {
|
||||
screenshots: 'on',
|
||||
schedule: '@every 3m',
|
||||
timeout: '16s',
|
||||
timeout: null,
|
||||
tags: [config.tags],
|
||||
throttling: '5d/3u/20l',
|
||||
'service.name': config.apmServiceName,
|
||||
|
@ -605,7 +605,7 @@ export default function (providerContext: FtrProviderContext) {
|
|||
config: {
|
||||
screenshots: 'on',
|
||||
schedule: '@every 3m',
|
||||
timeout: '16s',
|
||||
timeout: null,
|
||||
tags: [config.tags],
|
||||
throttling: '5d/3u/20l',
|
||||
'service.name': config.apmServiceName,
|
||||
|
@ -664,7 +664,7 @@ export default function (providerContext: FtrProviderContext) {
|
|||
config: {
|
||||
screenshots: advancedConfig.screenshots,
|
||||
schedule: '@every 3m',
|
||||
timeout: '16s',
|
||||
timeout: null,
|
||||
tags: [config.tags],
|
||||
throttling: '1337d/1338u/1339l',
|
||||
'service.name': config.apmServiceName,
|
||||
|
@ -728,7 +728,7 @@ export default function (providerContext: FtrProviderContext) {
|
|||
config: {
|
||||
screenshots: advancedConfig.screenshots,
|
||||
schedule: '@every 3m',
|
||||
timeout: '16s',
|
||||
timeout: null,
|
||||
tags: [config.tags],
|
||||
'service.name': config.apmServiceName,
|
||||
'source.zip_url.url': config.zipUrl,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue