mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 17:59:23 -04:00
[Uptime] [Synthetics Integration] browser - add script recorder option (#115184)
* Add script recorder tab for browser based monitors * implement policy edit flow for script recorder * add tests and translations * adjust types * update metadata key and add test * merge master * adjust usePolicy and source_field * revert merge master * adjust types * use reusable hook * update zip url tls default fields * rename content constant * adjust error handling and remove ts-ignore * adjust error default value * remove unnecessary fragment * adjust types * update tech preview content Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
parent
ba20ea1630
commit
78003671fc
21 changed files with 735 additions and 212 deletions
|
@ -9,9 +9,9 @@ import { BrowserFields, ConfigKeys } from '../types';
|
|||
import {
|
||||
Formatter,
|
||||
commonFormatters,
|
||||
objectToJsonFormatter,
|
||||
arrayToJsonFormatter,
|
||||
stringToJsonFormatter,
|
||||
objectToJsonFormatter,
|
||||
} from '../common/formatters';
|
||||
import {
|
||||
tlsValueToYamlFormatter,
|
||||
|
|
|
@ -14,7 +14,6 @@ import {
|
|||
} from '../common/normalizers';
|
||||
|
||||
import { defaultBrowserSimpleFields, defaultBrowserAdvancedFields } from '../contexts';
|
||||
import { tlsJsonToObjectNormalizer, tlsStringToObjectNormalizer } from '../tls/normalizers';
|
||||
|
||||
export type BrowserNormalizerMap = Record<keyof BrowserFields, Normalizer>;
|
||||
|
||||
|
@ -42,33 +41,22 @@ export const browserNormalizers: BrowserNormalizerMap = {
|
|||
[ConfigKeys.PARAMS]: getBrowserNormalizer(ConfigKeys.PARAMS),
|
||||
[ConfigKeys.SCREENSHOTS]: getBrowserNormalizer(ConfigKeys.SCREENSHOTS),
|
||||
[ConfigKeys.SYNTHETICS_ARGS]: getBrowserJsonToJavascriptNormalizer(ConfigKeys.SYNTHETICS_ARGS),
|
||||
[ConfigKeys.ZIP_URL_TLS_CERTIFICATE_AUTHORITIES]: (fields) =>
|
||||
tlsJsonToObjectNormalizer(
|
||||
fields?.[ConfigKeys.ZIP_URL_TLS_CERTIFICATE_AUTHORITIES]?.value,
|
||||
ConfigKeys.TLS_CERTIFICATE_AUTHORITIES
|
||||
),
|
||||
[ConfigKeys.ZIP_URL_TLS_CERTIFICATE]: (fields) =>
|
||||
tlsJsonToObjectNormalizer(
|
||||
fields?.[ConfigKeys.ZIP_URL_TLS_CERTIFICATE]?.value,
|
||||
ConfigKeys.TLS_CERTIFICATE
|
||||
),
|
||||
[ConfigKeys.ZIP_URL_TLS_KEY]: (fields) =>
|
||||
tlsJsonToObjectNormalizer(fields?.[ConfigKeys.ZIP_URL_TLS_KEY]?.value, ConfigKeys.TLS_KEY),
|
||||
[ConfigKeys.ZIP_URL_TLS_KEY_PASSPHRASE]: (fields) =>
|
||||
tlsStringToObjectNormalizer(
|
||||
fields?.[ConfigKeys.ZIP_URL_TLS_KEY_PASSPHRASE]?.value,
|
||||
ConfigKeys.TLS_KEY_PASSPHRASE
|
||||
),
|
||||
[ConfigKeys.ZIP_URL_TLS_VERIFICATION_MODE]: (fields) =>
|
||||
tlsStringToObjectNormalizer(
|
||||
fields?.[ConfigKeys.ZIP_URL_TLS_VERIFICATION_MODE]?.value,
|
||||
ConfigKeys.TLS_VERIFICATION_MODE
|
||||
),
|
||||
[ConfigKeys.ZIP_URL_TLS_VERSION]: (fields) =>
|
||||
tlsJsonToObjectNormalizer(
|
||||
fields?.[ConfigKeys.ZIP_URL_TLS_VERSION]?.value,
|
||||
ConfigKeys.TLS_VERSION
|
||||
),
|
||||
[ConfigKeys.ZIP_URL_TLS_CERTIFICATE_AUTHORITIES]: getBrowserJsonToJavascriptNormalizer(
|
||||
ConfigKeys.ZIP_URL_TLS_CERTIFICATE_AUTHORITIES
|
||||
),
|
||||
[ConfigKeys.ZIP_URL_TLS_CERTIFICATE]: getBrowserJsonToJavascriptNormalizer(
|
||||
ConfigKeys.ZIP_URL_TLS_CERTIFICATE
|
||||
),
|
||||
[ConfigKeys.ZIP_URL_TLS_KEY]: getBrowserJsonToJavascriptNormalizer(ConfigKeys.ZIP_URL_TLS_KEY),
|
||||
[ConfigKeys.ZIP_URL_TLS_KEY_PASSPHRASE]: getBrowserNormalizer(
|
||||
ConfigKeys.ZIP_URL_TLS_KEY_PASSPHRASE
|
||||
),
|
||||
[ConfigKeys.ZIP_URL_TLS_VERIFICATION_MODE]: getBrowserNormalizer(
|
||||
ConfigKeys.ZIP_URL_TLS_VERIFICATION_MODE
|
||||
),
|
||||
[ConfigKeys.ZIP_URL_TLS_VERSION]: getBrowserJsonToJavascriptNormalizer(
|
||||
ConfigKeys.ZIP_URL_TLS_VERSION
|
||||
),
|
||||
[ConfigKeys.JOURNEY_FILTERS_MATCH]: getBrowserJsonToJavascriptNormalizer(
|
||||
ConfigKeys.JOURNEY_FILTERS_MATCH
|
||||
),
|
||||
|
|
|
@ -0,0 +1,125 @@
|
|||
/*
|
||||
* 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 React from 'react';
|
||||
import { fireEvent, waitFor } from '@testing-library/react';
|
||||
import { render } from '../../../lib/helper/rtl_helpers';
|
||||
import { ScriptRecorderFields } from './script_recorder_fields';
|
||||
import { PolicyConfigContextProvider } from '../contexts';
|
||||
|
||||
jest.mock('@elastic/eui/lib/services/accessibility/html_id_generator', () => ({
|
||||
...jest.requireActual('@elastic/eui/lib/services/accessibility/html_id_generator'),
|
||||
htmlIdGenerator: () => () => `id-${Math.random()}`,
|
||||
}));
|
||||
|
||||
const onChange = jest.fn();
|
||||
|
||||
describe('<ScriptRecorderFields />', () => {
|
||||
let file: File;
|
||||
const testScript = 'step(() => {})';
|
||||
const WrappedComponent = ({
|
||||
isEditable = true,
|
||||
script = '',
|
||||
fileName = '',
|
||||
}: {
|
||||
isEditable?: boolean;
|
||||
script?: string;
|
||||
fileName?: string;
|
||||
}) => {
|
||||
return (
|
||||
<PolicyConfigContextProvider isEditable={isEditable}>
|
||||
<ScriptRecorderFields script={script} fileName={fileName} onChange={onChange} />
|
||||
</PolicyConfigContextProvider>
|
||||
);
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
file = new File([testScript], 'samplescript.js', { type: 'text/javascript' });
|
||||
});
|
||||
|
||||
it('renders ScriptRecorderFields', () => {
|
||||
const { getByText, queryByText } = render(<WrappedComponent />);
|
||||
|
||||
const downloadLink = getByText('Download the Elastic Synthetics Recorder');
|
||||
|
||||
expect(downloadLink).toBeInTheDocument();
|
||||
expect(downloadLink).toHaveAttribute('target', '_blank');
|
||||
|
||||
expect(queryByText('Show script')).not.toBeInTheDocument();
|
||||
expect(queryByText('Remove script')).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('handles uploading files', async () => {
|
||||
const { getByTestId } = render(<WrappedComponent />);
|
||||
|
||||
const uploader = getByTestId('syntheticsFleetScriptRecorderUploader');
|
||||
|
||||
fireEvent.change(uploader, {
|
||||
target: { files: [file] },
|
||||
});
|
||||
|
||||
await waitFor(() => {
|
||||
expect(onChange).toBeCalledWith({ scriptText: testScript, fileName: 'samplescript.js' });
|
||||
});
|
||||
});
|
||||
|
||||
it('shows user errors for invalid file types', async () => {
|
||||
const { getByTestId, getByText } = render(<WrappedComponent />);
|
||||
file = new File(['journey(() => {})'], 'samplescript.js', { type: 'text/javascript' });
|
||||
|
||||
let uploader = getByTestId('syntheticsFleetScriptRecorderUploader') as HTMLInputElement;
|
||||
|
||||
fireEvent.change(uploader, {
|
||||
target: { files: [file] },
|
||||
});
|
||||
|
||||
uploader = getByTestId('syntheticsFleetScriptRecorderUploader') as HTMLInputElement;
|
||||
|
||||
await waitFor(() => {
|
||||
expect(onChange).not.toBeCalled();
|
||||
expect(
|
||||
getByText(
|
||||
'Error uploading file. Please upload a .js file generated by the Elastic Synthetics Recorder in inline script format.'
|
||||
)
|
||||
).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
it('shows show script button when script is available', () => {
|
||||
const { getByText, queryByText } = render(<WrappedComponent script={testScript} />);
|
||||
|
||||
const showScriptBtn = getByText('Show script');
|
||||
|
||||
expect(queryByText(testScript)).not.toBeInTheDocument();
|
||||
|
||||
fireEvent.click(showScriptBtn);
|
||||
|
||||
expect(getByText(testScript)).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('shows show remove script button when script is available and isEditable is true', async () => {
|
||||
const { getByText, getByTestId } = render(
|
||||
<WrappedComponent script={testScript} isEditable={true} />
|
||||
);
|
||||
|
||||
const showScriptBtn = getByText('Show script');
|
||||
fireEvent.click(showScriptBtn);
|
||||
|
||||
expect(getByText(testScript)).toBeInTheDocument();
|
||||
|
||||
fireEvent.click(getByTestId('euiFlyoutCloseButton'));
|
||||
|
||||
const removeScriptBtn = getByText('Remove script');
|
||||
|
||||
fireEvent.click(removeScriptBtn);
|
||||
|
||||
await waitFor(() => {
|
||||
expect(onChange).toBeCalledWith({ scriptText: '', fileName: '' });
|
||||
});
|
||||
});
|
||||
});
|
|
@ -0,0 +1,134 @@
|
|||
/*
|
||||
* 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 React, { useState, useCallback } from 'react';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { FormattedMessage } from '@kbn/i18n/react';
|
||||
import {
|
||||
EuiLink,
|
||||
EuiFlexGroup,
|
||||
EuiFlexItem,
|
||||
EuiFlyout,
|
||||
EuiFlyoutHeader,
|
||||
EuiFormRow,
|
||||
EuiCodeBlock,
|
||||
EuiTitle,
|
||||
EuiButton,
|
||||
EuiSpacer,
|
||||
EuiText,
|
||||
} from '@elastic/eui';
|
||||
import { usePolicyConfigContext } from '../contexts/policy_config_context';
|
||||
import { Uploader } from './uploader';
|
||||
|
||||
interface Props {
|
||||
onChange: ({ scriptText, fileName }: { scriptText: string; fileName: string }) => void;
|
||||
script: string;
|
||||
fileName?: string;
|
||||
}
|
||||
|
||||
export function ScriptRecorderFields({ onChange, script, fileName }: Props) {
|
||||
const [showScript, setShowScript] = useState(false);
|
||||
const { isEditable } = usePolicyConfigContext();
|
||||
|
||||
const handleUpload = useCallback(
|
||||
({ scriptText, fileName: fileNameT }: { scriptText: string; fileName: string }) => {
|
||||
onChange({ scriptText, fileName: fileNameT });
|
||||
},
|
||||
[onChange]
|
||||
);
|
||||
|
||||
return (
|
||||
<>
|
||||
<EuiSpacer size="m" />
|
||||
<EuiLink href="https://github.com/elastic/synthetics-recorder/releases/" target="_blank">
|
||||
<FormattedMessage
|
||||
id="xpack.uptime.createPackagePolicy.stepConfigure.monitorIntegrationSettingsSection.browser.zipUrl.recorderLink"
|
||||
defaultMessage="Download the Elastic Synthetics Recorder"
|
||||
/>
|
||||
</EuiLink>
|
||||
<EuiSpacer size="m" />
|
||||
{isEditable && script ? (
|
||||
<EuiFormRow label="Testing script">
|
||||
<EuiText size="s">
|
||||
<strong>{fileName}</strong>
|
||||
</EuiText>
|
||||
</EuiFormRow>
|
||||
) : (
|
||||
<Uploader onUpload={handleUpload} />
|
||||
)}
|
||||
{script && (
|
||||
<>
|
||||
<EuiSpacer size="m" />
|
||||
<EuiFlexGroup gutterSize="s">
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiButton
|
||||
onClick={() => setShowScript(true)}
|
||||
iconType="editorCodeBlock"
|
||||
iconSide="right"
|
||||
>
|
||||
<FormattedMessage
|
||||
id="xpack.uptime.createPackagePolicy.stepConfigure.monitorIntegrationSettingsSection.browser.zipUrl.showScriptLabel"
|
||||
defaultMessage="Show script"
|
||||
/>
|
||||
</EuiButton>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem grow={false}>
|
||||
{isEditable && (
|
||||
<EuiButton
|
||||
onClick={() => onChange({ scriptText: '', fileName: '' })}
|
||||
iconType="trash"
|
||||
iconSide="right"
|
||||
color="danger"
|
||||
>
|
||||
<FormattedMessage
|
||||
id="xpack.uptime.createPackagePolicy.stepConfigure.monitorIntegrationSettingsSection.browser.zipUrl.removeScriptLabel"
|
||||
defaultMessage="Remove script"
|
||||
/>
|
||||
</EuiButton>
|
||||
)}
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
</>
|
||||
)}
|
||||
{showScript && (
|
||||
<EuiFlyout
|
||||
ownFocus
|
||||
onClose={() => setShowScript(false)}
|
||||
aria-labelledby="syntheticsBrowserScriptBlockHeader"
|
||||
closeButtonAriaLabel={CLOSE_BUTTON_LABEL}
|
||||
>
|
||||
<EuiFlyoutHeader hasBorder>
|
||||
<EuiTitle size="m">
|
||||
<span id="syntheticsBrowserScriptBlockHeader">
|
||||
{fileName || PLACEHOLDER_FILE_NAME}
|
||||
</span>
|
||||
</EuiTitle>
|
||||
</EuiFlyoutHeader>
|
||||
<div style={{ height: '100%' }}>
|
||||
<EuiCodeBlock language="js" overflowHeight={'100%'} fontSize="m" isCopyable>
|
||||
{script}
|
||||
</EuiCodeBlock>
|
||||
</div>
|
||||
</EuiFlyout>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
const PLACEHOLDER_FILE_NAME = i18n.translate(
|
||||
'xpack.uptime.createPackagePolicy.stepConfigure.monitorIntegrationSettingsSection.browser.scriptRecorder.mockFileName',
|
||||
{
|
||||
defaultMessage: 'test_script.js',
|
||||
}
|
||||
);
|
||||
|
||||
const CLOSE_BUTTON_LABEL = i18n.translate(
|
||||
'xpack.uptime.createPackagePolicy.stepConfigure.monitorIntegrationSettingsSection.browser.scriptRecorder.closeButtonLabel',
|
||||
{
|
||||
defaultMessage: 'Close script flyout',
|
||||
}
|
||||
);
|
|
@ -24,7 +24,17 @@ export const BrowserSimpleFields = memo<Props>(({ validate }) => {
|
|||
setFields((prevFields) => ({ ...prevFields, [configKey]: value }));
|
||||
};
|
||||
const onChangeSourceField = useCallback(
|
||||
({ zipUrl, folder, username, password, inlineScript, params, proxyUrl }) => {
|
||||
({
|
||||
zipUrl,
|
||||
folder,
|
||||
username,
|
||||
password,
|
||||
inlineScript,
|
||||
params,
|
||||
proxyUrl,
|
||||
isGeneratedScript,
|
||||
fileName,
|
||||
}) => {
|
||||
setFields((prevFields) => ({
|
||||
...prevFields,
|
||||
[ConfigKeys.SOURCE_ZIP_URL]: zipUrl,
|
||||
|
@ -34,6 +44,13 @@ export const BrowserSimpleFields = memo<Props>(({ validate }) => {
|
|||
[ConfigKeys.SOURCE_ZIP_PASSWORD]: password,
|
||||
[ConfigKeys.SOURCE_INLINE]: inlineScript,
|
||||
[ConfigKeys.PARAMS]: params,
|
||||
[ConfigKeys.METADATA]: {
|
||||
...prevFields[ConfigKeys.METADATA],
|
||||
script_source: {
|
||||
is_generated_script: isGeneratedScript,
|
||||
file_name: fileName,
|
||||
},
|
||||
},
|
||||
}));
|
||||
},
|
||||
[setFields]
|
||||
|
@ -87,6 +104,9 @@ export const BrowserSimpleFields = memo<Props>(({ validate }) => {
|
|||
password: defaultValues[ConfigKeys.SOURCE_ZIP_PASSWORD],
|
||||
inlineScript: defaultValues[ConfigKeys.SOURCE_INLINE],
|
||||
params: defaultValues[ConfigKeys.PARAMS],
|
||||
isGeneratedScript:
|
||||
defaultValues[ConfigKeys.METADATA].script_source?.is_generated_script,
|
||||
fileName: defaultValues[ConfigKeys.METADATA].script_source?.file_name,
|
||||
}),
|
||||
[defaultValues]
|
||||
)}
|
||||
|
|
|
@ -5,23 +5,28 @@
|
|||
* 2.0.
|
||||
*/
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import styled from 'styled-components';
|
||||
import { FormattedMessage } from '@kbn/i18n/react';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
|
||||
import {
|
||||
EuiTabbedContent,
|
||||
EuiFormRow,
|
||||
EuiFieldText,
|
||||
EuiFieldPassword,
|
||||
EuiSpacer,
|
||||
EuiBetaBadge,
|
||||
EuiFlexGroup,
|
||||
EuiFlexItem,
|
||||
} from '@elastic/eui';
|
||||
import { OptionalLabel } from '../optional_label';
|
||||
import { CodeEditor } from '../code_editor';
|
||||
import { ScriptRecorderFields } from './script_recorder_fields';
|
||||
import { ZipUrlTLSFields } from './zip_url_tls_fields';
|
||||
import { MonacoEditorLangId } from '../types';
|
||||
|
||||
enum SourceType {
|
||||
INLINE = 'syntheticsBrowserInlineConfig',
|
||||
SCRIPT_RECORDER = 'syntheticsBrowserScriptRecorderConfig',
|
||||
ZIP = 'syntheticsBrowserZipURLConfig',
|
||||
}
|
||||
|
||||
|
@ -33,6 +38,8 @@ interface SourceConfig {
|
|||
password: string;
|
||||
inlineScript: string;
|
||||
params: string;
|
||||
isGeneratedScript?: boolean;
|
||||
fileName?: string;
|
||||
}
|
||||
|
||||
interface Props {
|
||||
|
@ -48,12 +55,22 @@ export const defaultValues = {
|
|||
password: '',
|
||||
inlineScript: '',
|
||||
params: '',
|
||||
isGeneratedScript: false,
|
||||
fileName: '',
|
||||
};
|
||||
|
||||
const getDefaultTab = (defaultConfig: SourceConfig) => {
|
||||
if (defaultConfig.inlineScript && defaultConfig.isGeneratedScript) {
|
||||
return SourceType.SCRIPT_RECORDER;
|
||||
} else if (defaultConfig.inlineScript) {
|
||||
return SourceType.INLINE;
|
||||
}
|
||||
|
||||
return SourceType.ZIP;
|
||||
};
|
||||
|
||||
export const SourceField = ({ onChange, defaultConfig = defaultValues }: Props) => {
|
||||
const [sourceType, setSourceType] = useState<SourceType>(
|
||||
defaultConfig.inlineScript ? SourceType.INLINE : SourceType.ZIP
|
||||
);
|
||||
const [sourceType, setSourceType] = useState<SourceType>(getDefaultTab(defaultConfig));
|
||||
const [config, setConfig] = useState<SourceConfig>(defaultConfig);
|
||||
|
||||
useEffect(() => {
|
||||
|
@ -264,6 +281,52 @@ export const SourceField = ({ onChange, defaultConfig = defaultValues }: Props)
|
|||
</EuiFormRow>
|
||||
),
|
||||
},
|
||||
{
|
||||
id: 'syntheticsBrowserScriptRecorderConfig',
|
||||
name: (
|
||||
<EuiFlexGroup responsive={false} alignItems="center" gutterSize="xs">
|
||||
<EuiFlexItem grow={false}>
|
||||
<FormattedMessage
|
||||
id="xpack.uptime.createPackagePolicy.stepConfigure.browser.scriptRecorder.label"
|
||||
defaultMessage="Script recorder"
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
<StyledBetaBadgeWrapper grow={false}>
|
||||
<EuiBetaBadge
|
||||
label={i18n.translate(
|
||||
'xpack.uptime.createPackagePolicy.stepConfigure.browser.scriptRecorder.experimentalLabel',
|
||||
{
|
||||
defaultMessage: 'Tech preview',
|
||||
}
|
||||
)}
|
||||
iconType="beaker"
|
||||
tooltipContent={i18n.translate(
|
||||
'xpack.uptime.createPackagePolicy.stepConfigure.browser.scriptRecorder.experimentalTooltip',
|
||||
{
|
||||
defaultMessage:
|
||||
'Preview the quickest way to create Elastic Synthetics monitoring scripts with our Elastic Synthetics Recorder',
|
||||
}
|
||||
)}
|
||||
/>
|
||||
</StyledBetaBadgeWrapper>
|
||||
</EuiFlexGroup>
|
||||
),
|
||||
'data-test-subj': 'syntheticsSourceTab__scriptRecorder',
|
||||
content: (
|
||||
<ScriptRecorderFields
|
||||
onChange={({ scriptText, fileName }) =>
|
||||
setConfig((prevConfig) => ({
|
||||
...prevConfig,
|
||||
inlineScript: scriptText,
|
||||
isGeneratedScript: true,
|
||||
fileName,
|
||||
}))
|
||||
}
|
||||
script={config.inlineScript}
|
||||
fileName={config.fileName}
|
||||
/>
|
||||
),
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
|
@ -272,11 +335,17 @@ export const SourceField = ({ onChange, defaultConfig = defaultValues }: Props)
|
|||
initialSelectedTab={tabs.find((tab) => tab.id === sourceType)}
|
||||
autoFocus="selected"
|
||||
onTabClick={(tab) => {
|
||||
setSourceType(tab.id as SourceType);
|
||||
if (tab.id !== sourceType) {
|
||||
setConfig(defaultValues);
|
||||
}
|
||||
setSourceType(tab.id as SourceType);
|
||||
}}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
const StyledBetaBadgeWrapper = styled(EuiFlexItem)`
|
||||
.euiToolTipAnchor {
|
||||
display: flex;
|
||||
}
|
||||
`;
|
||||
|
|
|
@ -0,0 +1,93 @@
|
|||
/*
|
||||
* 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 React, { useState, useRef } from 'react';
|
||||
|
||||
import { i18n } from '@kbn/i18n';
|
||||
|
||||
import { EuiFormRow, EuiFilePicker } from '@elastic/eui';
|
||||
|
||||
interface Props {
|
||||
onUpload: ({ scriptText, fileName }: { scriptText: string; fileName: string }) => void;
|
||||
}
|
||||
|
||||
export function Uploader({ onUpload }: Props) {
|
||||
const fileReader = useRef<null | FileReader>(null);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
const filePickerRef = useRef<EuiFilePicker>(null);
|
||||
|
||||
const handleFileRead = (fileName: string) => {
|
||||
const content = fileReader?.current?.result as string;
|
||||
|
||||
if (content?.trim().slice(0, 4) !== 'step') {
|
||||
setError(PARSING_ERROR);
|
||||
filePickerRef.current?.removeFiles();
|
||||
return;
|
||||
}
|
||||
|
||||
onUpload({ scriptText: content, fileName });
|
||||
setError(null);
|
||||
};
|
||||
|
||||
const handleFileChosen = (files: FileList | null) => {
|
||||
if (!files || !files.length) {
|
||||
onUpload({ scriptText: '', fileName: '' });
|
||||
return;
|
||||
}
|
||||
if (files.length && files[0].type !== 'text/javascript') {
|
||||
setError(INVALID_FILE_ERROR);
|
||||
filePickerRef.current?.removeFiles();
|
||||
return;
|
||||
}
|
||||
fileReader.current = new FileReader();
|
||||
fileReader.current.onloadend = () => handleFileRead(files[0].name);
|
||||
fileReader.current.readAsText(files[0]);
|
||||
};
|
||||
|
||||
return (
|
||||
<EuiFormRow isInvalid={Boolean(error)} error={error} label={TESTING_SCRIPT_LABEL}>
|
||||
<EuiFilePicker
|
||||
id="syntheticsFleetScriptRecorderUploader"
|
||||
data-test-subj="syntheticsFleetScriptRecorderUploader"
|
||||
ref={filePickerRef}
|
||||
initialPromptText={PROMPT_TEXT}
|
||||
onChange={handleFileChosen}
|
||||
display={'large'}
|
||||
/>
|
||||
</EuiFormRow>
|
||||
);
|
||||
}
|
||||
|
||||
const TESTING_SCRIPT_LABEL = i18n.translate(
|
||||
'xpack.uptime.createPackagePolicy.stepConfigure.monitorIntegrationSettingsSection.browser.uploader.fieldLabel',
|
||||
{
|
||||
defaultMessage: 'Testing script',
|
||||
}
|
||||
);
|
||||
|
||||
const PROMPT_TEXT = i18n.translate(
|
||||
'xpack.uptime.createPackagePolicy.stepConfigure.monitorIntegrationSettingsSection.browser.uploader.label',
|
||||
{
|
||||
defaultMessage: 'Select recorder-generated .js file',
|
||||
}
|
||||
);
|
||||
|
||||
const INVALID_FILE_ERROR = i18n.translate(
|
||||
'xpack.uptime.createPackagePolicy.stepConfigure.monitorIntegrationSettingsSection.browser.uploader.invalidFileError',
|
||||
{
|
||||
defaultMessage:
|
||||
'Invalid file type. Please upload a .js file generated by the Elastic Synthetics Recorder.',
|
||||
}
|
||||
);
|
||||
|
||||
const PARSING_ERROR = i18n.translate(
|
||||
'xpack.uptime.createPackagePolicy.stepConfigure.monitorIntegrationSettingsSection.browser.uploader.parsingError',
|
||||
{
|
||||
defaultMessage:
|
||||
'Error uploading file. Please upload a .js file generated by the Elastic Synthetics Recorder in inline script format.',
|
||||
}
|
||||
);
|
|
@ -12,7 +12,11 @@ import { EuiSwitch, EuiFormRow } from '@elastic/eui';
|
|||
import { FormattedMessage } from '@kbn/i18n/react';
|
||||
|
||||
import { TLSOptions, TLSConfig } from '../common/tls_options';
|
||||
import { useBrowserSimpleFieldsContext, usePolicyConfigContext } from '../contexts';
|
||||
import {
|
||||
useBrowserSimpleFieldsContext,
|
||||
usePolicyConfigContext,
|
||||
defaultTLSFields,
|
||||
} from '../contexts';
|
||||
|
||||
import { ConfigKeys } from '../types';
|
||||
|
||||
|
@ -67,12 +71,23 @@ export const ZipUrlTLSFields = () => {
|
|||
{isZipUrlTLSEnabled ? (
|
||||
<TLSOptions
|
||||
defaultValues={{
|
||||
certificateAuthorities: defaultValues[ConfigKeys.ZIP_URL_TLS_CERTIFICATE_AUTHORITIES],
|
||||
certificate: defaultValues[ConfigKeys.ZIP_URL_TLS_CERTIFICATE],
|
||||
key: defaultValues[ConfigKeys.ZIP_URL_TLS_KEY],
|
||||
keyPassphrase: defaultValues[ConfigKeys.ZIP_URL_TLS_KEY_PASSPHRASE],
|
||||
verificationMode: defaultValues[ConfigKeys.ZIP_URL_TLS_VERIFICATION_MODE],
|
||||
version: defaultValues[ConfigKeys.ZIP_URL_TLS_VERSION],
|
||||
certificateAuthorities:
|
||||
defaultValues[ConfigKeys.ZIP_URL_TLS_CERTIFICATE_AUTHORITIES] ||
|
||||
defaultTLSFields[ConfigKeys.TLS_CERTIFICATE_AUTHORITIES],
|
||||
certificate:
|
||||
defaultValues[ConfigKeys.ZIP_URL_TLS_CERTIFICATE] ||
|
||||
defaultTLSFields[ConfigKeys.TLS_CERTIFICATE],
|
||||
key:
|
||||
defaultValues[ConfigKeys.ZIP_URL_TLS_KEY] || defaultTLSFields[ConfigKeys.TLS_KEY],
|
||||
keyPassphrase:
|
||||
defaultValues[ConfigKeys.ZIP_URL_TLS_KEY_PASSPHRASE] ||
|
||||
defaultTLSFields[ConfigKeys.TLS_KEY_PASSPHRASE],
|
||||
verificationMode:
|
||||
defaultValues[ConfigKeys.ZIP_URL_TLS_VERIFICATION_MODE] ||
|
||||
defaultTLSFields[ConfigKeys.TLS_VERIFICATION_MODE],
|
||||
version:
|
||||
defaultValues[ConfigKeys.ZIP_URL_TLS_VERSION] ||
|
||||
defaultTLSFields[ConfigKeys.TLS_VERSION],
|
||||
}}
|
||||
onChange={handleOnChange}
|
||||
tlsRole="client"
|
||||
|
|
|
@ -8,7 +8,6 @@
|
|||
import React, { createContext, useContext, useMemo, useState } from 'react';
|
||||
import { IBrowserSimpleFields, ConfigKeys, DataStream } from '../types';
|
||||
import { defaultValues as commonDefaultValues } from '../common/default_values';
|
||||
import { defaultValues as tlsDefaultValues } from '../tls/default_values';
|
||||
|
||||
interface IBrowserSimpleFieldsContext {
|
||||
setFields: React.Dispatch<React.SetStateAction<IBrowserSimpleFields>>;
|
||||
|
@ -24,6 +23,10 @@ interface IBrowserSimpleFieldsContextProvider {
|
|||
export const initialValues: IBrowserSimpleFields = {
|
||||
...commonDefaultValues,
|
||||
[ConfigKeys.METADATA]: {
|
||||
script_source: {
|
||||
is_generated_script: false,
|
||||
file_name: '',
|
||||
},
|
||||
is_zip_url_tls_enabled: false,
|
||||
},
|
||||
[ConfigKeys.MONITOR_TYPE]: DataStream.BROWSER,
|
||||
|
@ -34,13 +37,12 @@ export const initialValues: IBrowserSimpleFields = {
|
|||
[ConfigKeys.SOURCE_ZIP_PROXY_URL]: '',
|
||||
[ConfigKeys.SOURCE_INLINE]: '',
|
||||
[ConfigKeys.PARAMS]: '',
|
||||
[ConfigKeys.ZIP_URL_TLS_CERTIFICATE_AUTHORITIES]:
|
||||
tlsDefaultValues[ConfigKeys.TLS_CERTIFICATE_AUTHORITIES],
|
||||
[ConfigKeys.ZIP_URL_TLS_CERTIFICATE]: tlsDefaultValues[ConfigKeys.TLS_CERTIFICATE],
|
||||
[ConfigKeys.ZIP_URL_TLS_KEY]: tlsDefaultValues[ConfigKeys.TLS_KEY],
|
||||
[ConfigKeys.ZIP_URL_TLS_KEY_PASSPHRASE]: tlsDefaultValues[ConfigKeys.TLS_KEY_PASSPHRASE],
|
||||
[ConfigKeys.ZIP_URL_TLS_VERIFICATION_MODE]: tlsDefaultValues[ConfigKeys.TLS_VERIFICATION_MODE],
|
||||
[ConfigKeys.ZIP_URL_TLS_VERSION]: tlsDefaultValues[ConfigKeys.TLS_VERSION],
|
||||
[ConfigKeys.ZIP_URL_TLS_CERTIFICATE_AUTHORITIES]: undefined,
|
||||
[ConfigKeys.ZIP_URL_TLS_CERTIFICATE]: undefined,
|
||||
[ConfigKeys.ZIP_URL_TLS_KEY]: undefined,
|
||||
[ConfigKeys.ZIP_URL_TLS_KEY_PASSPHRASE]: undefined,
|
||||
[ConfigKeys.ZIP_URL_TLS_VERIFICATION_MODE]: undefined,
|
||||
[ConfigKeys.ZIP_URL_TLS_VERSION]: undefined,
|
||||
};
|
||||
|
||||
const defaultContext: IBrowserSimpleFieldsContext = {
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
export {
|
||||
PolicyConfigContext,
|
||||
PolicyConfigContextProvider,
|
||||
initialValue as defaultMonitorType,
|
||||
initialValue as defaultPolicyConfig,
|
||||
usePolicyConfigContext,
|
||||
} from './policy_config_context';
|
||||
export {
|
||||
|
|
|
@ -18,6 +18,7 @@ interface IPolicyConfigContext {
|
|||
isZipUrlTLSEnabled?: boolean;
|
||||
defaultIsTLSEnabled?: boolean;
|
||||
defaultIsZipUrlTLSEnabled?: boolean;
|
||||
isEditable?: boolean;
|
||||
}
|
||||
|
||||
interface IPolicyConfigContextProvider {
|
||||
|
@ -25,6 +26,7 @@ interface IPolicyConfigContextProvider {
|
|||
defaultMonitorType?: DataStream;
|
||||
defaultIsTLSEnabled?: boolean;
|
||||
defaultIsZipUrlTLSEnabled?: boolean;
|
||||
isEditable?: boolean;
|
||||
}
|
||||
|
||||
export const initialValue = DataStream.HTTP;
|
||||
|
@ -45,6 +47,7 @@ const defaultContext: IPolicyConfigContext = {
|
|||
defaultMonitorType: initialValue, // immutable,
|
||||
defaultIsTLSEnabled: false,
|
||||
defaultIsZipUrlTLSEnabled: false,
|
||||
isEditable: false,
|
||||
};
|
||||
|
||||
export const PolicyConfigContext = createContext(defaultContext);
|
||||
|
@ -54,6 +57,7 @@ export const PolicyConfigContextProvider = ({
|
|||
defaultMonitorType = initialValue,
|
||||
defaultIsTLSEnabled = false,
|
||||
defaultIsZipUrlTLSEnabled = false,
|
||||
isEditable = false,
|
||||
}: IPolicyConfigContextProvider) => {
|
||||
const [monitorType, setMonitorType] = useState<DataStream>(defaultMonitorType);
|
||||
const [isTLSEnabled, setIsTLSEnabled] = useState<boolean>(defaultIsTLSEnabled);
|
||||
|
@ -70,6 +74,7 @@ export const PolicyConfigContextProvider = ({
|
|||
setIsZipUrlTLSEnabled,
|
||||
defaultIsTLSEnabled,
|
||||
defaultIsZipUrlTLSEnabled,
|
||||
isEditable,
|
||||
};
|
||||
}, [
|
||||
monitorType,
|
||||
|
@ -78,6 +83,7 @@ export const PolicyConfigContextProvider = ({
|
|||
isZipUrlTLSEnabled,
|
||||
defaultIsTLSEnabled,
|
||||
defaultIsZipUrlTLSEnabled,
|
||||
isEditable,
|
||||
]);
|
||||
|
||||
return <PolicyConfigContext.Provider value={value} children={children} />;
|
||||
|
|
|
@ -54,21 +54,17 @@ const defaultTCPConfig = defaultConfig[DataStream.TCP];
|
|||
describe.skip('<CustomFields />', () => {
|
||||
const WrappedComponent = ({
|
||||
validate = defaultValidation,
|
||||
typeEditable = false,
|
||||
isEditable = false,
|
||||
dataStreams = [DataStream.HTTP, DataStream.TCP, DataStream.ICMP, DataStream.BROWSER],
|
||||
}) => {
|
||||
return (
|
||||
<HTTPContextProvider>
|
||||
<PolicyConfigContextProvider>
|
||||
<PolicyConfigContextProvider isEditable={isEditable}>
|
||||
<TCPContextProvider>
|
||||
<BrowserContextProvider>
|
||||
<ICMPSimpleFieldsContextProvider>
|
||||
<TLSFieldsContextProvider>
|
||||
<CustomFields
|
||||
validate={validate}
|
||||
typeEditable={typeEditable}
|
||||
dataStreams={dataStreams}
|
||||
/>
|
||||
<CustomFields validate={validate} dataStreams={dataStreams} />
|
||||
</TLSFieldsContextProvider>
|
||||
</ICMPSimpleFieldsContextProvider>
|
||||
</BrowserContextProvider>
|
||||
|
@ -80,7 +76,7 @@ describe.skip('<CustomFields />', () => {
|
|||
|
||||
it('renders CustomFields', async () => {
|
||||
const { getByText, getByLabelText, queryByLabelText } = render(<WrappedComponent />);
|
||||
const monitorType = queryByLabelText('Monitor Type') as HTMLInputElement;
|
||||
const monitorType = getByLabelText('Monitor Type') as HTMLInputElement;
|
||||
const url = getByLabelText('URL') as HTMLInputElement;
|
||||
const proxyUrl = getByLabelText('Proxy URL') as HTMLInputElement;
|
||||
const monitorIntervalNumber = getByLabelText('Number') as HTMLInputElement;
|
||||
|
@ -88,7 +84,7 @@ describe.skip('<CustomFields />', () => {
|
|||
const apmServiceName = getByLabelText('APM service name') as HTMLInputElement;
|
||||
const maxRedirects = getByLabelText('Max redirects') as HTMLInputElement;
|
||||
const timeout = getByLabelText('Timeout in seconds') as HTMLInputElement;
|
||||
expect(monitorType).not.toBeInTheDocument();
|
||||
expect(monitorType).toBeInTheDocument();
|
||||
expect(url).toBeInTheDocument();
|
||||
expect(url.value).toEqual(defaultHTTPConfig[ConfigKeys.URLS]);
|
||||
expect(proxyUrl).toBeInTheDocument();
|
||||
|
@ -117,6 +113,13 @@ describe.skip('<CustomFields />', () => {
|
|||
});
|
||||
});
|
||||
|
||||
it('does not show monitor type dropdown when isEditable is true', async () => {
|
||||
const { queryByLabelText } = render(<WrappedComponent isEditable />);
|
||||
const monitorType = queryByLabelText('Monitor Type') as HTMLInputElement;
|
||||
|
||||
expect(monitorType).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('shows SSL fields when Enable SSL Fields is checked', async () => {
|
||||
const { findByLabelText, queryByLabelText } = render(<WrappedComponent />);
|
||||
const enableSSL = queryByLabelText('Enable TLS configuration') as HTMLInputElement;
|
||||
|
@ -180,7 +183,7 @@ describe.skip('<CustomFields />', () => {
|
|||
|
||||
it('handles switching monitor type', () => {
|
||||
const { getByText, getByLabelText, queryByLabelText, getAllByLabelText } = render(
|
||||
<WrappedComponent typeEditable />
|
||||
<WrappedComponent />
|
||||
);
|
||||
const monitorType = getByLabelText('Monitor Type') as HTMLInputElement;
|
||||
expect(monitorType).toBeInTheDocument();
|
||||
|
@ -244,7 +247,7 @@ describe.skip('<CustomFields />', () => {
|
|||
});
|
||||
|
||||
it('shows resolve hostnames locally field when proxy url is filled for tcp monitors', () => {
|
||||
const { getByLabelText, queryByLabelText } = render(<WrappedComponent typeEditable />);
|
||||
const { getByLabelText, queryByLabelText } = render(<WrappedComponent />);
|
||||
const monitorType = getByLabelText('Monitor Type') as HTMLInputElement;
|
||||
fireEvent.change(monitorType, { target: { value: DataStream.TCP } });
|
||||
|
||||
|
@ -302,10 +305,7 @@ describe.skip('<CustomFields />', () => {
|
|||
|
||||
it('does not show monitor options that are not contained in datastreams', async () => {
|
||||
const { getByText, queryByText, queryByLabelText } = render(
|
||||
<WrappedComponent
|
||||
dataStreams={[DataStream.HTTP, DataStream.TCP, DataStream.ICMP]}
|
||||
typeEditable
|
||||
/>
|
||||
<WrappedComponent dataStreams={[DataStream.HTTP, DataStream.TCP, DataStream.ICMP]} />
|
||||
);
|
||||
|
||||
const monitorType = queryByLabelText('Monitor Type') as HTMLInputElement;
|
||||
|
|
|
@ -30,13 +30,13 @@ import { BrowserSimpleFields } from './browser/simple_fields';
|
|||
import { BrowserAdvancedFields } from './browser/advanced_fields';
|
||||
|
||||
interface Props {
|
||||
typeEditable?: boolean;
|
||||
validate: Validation;
|
||||
dataStreams?: DataStream[];
|
||||
}
|
||||
|
||||
export const CustomFields = memo<Props>(({ typeEditable = false, validate, dataStreams = [] }) => {
|
||||
const { monitorType, setMonitorType, isTLSEnabled, setIsTLSEnabled } = usePolicyConfigContext();
|
||||
export const CustomFields = memo<Props>(({ validate, dataStreams = [] }) => {
|
||||
const { monitorType, setMonitorType, isTLSEnabled, setIsTLSEnabled, isEditable } =
|
||||
usePolicyConfigContext();
|
||||
|
||||
const isHTTP = monitorType === DataStream.HTTP;
|
||||
const isTCP = monitorType === DataStream.TCP;
|
||||
|
@ -88,7 +88,7 @@ export const CustomFields = memo<Props>(({ typeEditable = false, validate, dataS
|
|||
>
|
||||
<EuiFlexGroup>
|
||||
<EuiFlexItem>
|
||||
{typeEditable && (
|
||||
{!isEditable && (
|
||||
<EuiFormRow
|
||||
label={
|
||||
<FormattedMessage
|
||||
|
|
|
@ -0,0 +1,131 @@
|
|||
/*
|
||||
* 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 { useMemo } from 'react';
|
||||
import {
|
||||
PolicyConfig,
|
||||
DataStream,
|
||||
ConfigKeys,
|
||||
HTTPFields,
|
||||
TCPFields,
|
||||
ICMPFields,
|
||||
BrowserFields,
|
||||
} from '../types';
|
||||
import {
|
||||
usePolicyConfigContext,
|
||||
useTCPSimpleFieldsContext,
|
||||
useTCPAdvancedFieldsContext,
|
||||
useICMPSimpleFieldsContext,
|
||||
useHTTPSimpleFieldsContext,
|
||||
useHTTPAdvancedFieldsContext,
|
||||
useTLSFieldsContext,
|
||||
useBrowserSimpleFieldsContext,
|
||||
useBrowserAdvancedFieldsContext,
|
||||
defaultHTTPAdvancedFields,
|
||||
defaultHTTPSimpleFields,
|
||||
defaultICMPSimpleFields,
|
||||
defaultTCPSimpleFields,
|
||||
defaultTCPAdvancedFields,
|
||||
defaultBrowserSimpleFields,
|
||||
defaultBrowserAdvancedFields,
|
||||
defaultTLSFields,
|
||||
} from '../contexts';
|
||||
|
||||
export const defaultConfig: PolicyConfig = {
|
||||
[DataStream.HTTP]: {
|
||||
...defaultHTTPSimpleFields,
|
||||
...defaultHTTPAdvancedFields,
|
||||
...defaultTLSFields,
|
||||
},
|
||||
[DataStream.TCP]: {
|
||||
...defaultTCPSimpleFields,
|
||||
...defaultTCPAdvancedFields,
|
||||
...defaultTLSFields,
|
||||
},
|
||||
[DataStream.ICMP]: defaultICMPSimpleFields,
|
||||
[DataStream.BROWSER]: {
|
||||
...defaultBrowserSimpleFields,
|
||||
...defaultBrowserAdvancedFields,
|
||||
...defaultTLSFields,
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* Exports Synthetics-specific package policy instructions
|
||||
* for use in the Ingest app create / edit package policy
|
||||
*/
|
||||
export const usePolicy = (name: string) => {
|
||||
const { isTLSEnabled, isZipUrlTLSEnabled } = usePolicyConfigContext();
|
||||
const { fields: httpSimpleFields } = useHTTPSimpleFieldsContext();
|
||||
const { fields: tcpSimpleFields } = useTCPSimpleFieldsContext();
|
||||
const { fields: icmpSimpleFields } = useICMPSimpleFieldsContext();
|
||||
const { fields: browserSimpleFields } = useBrowserSimpleFieldsContext();
|
||||
const { fields: httpAdvancedFields } = useHTTPAdvancedFieldsContext();
|
||||
const { fields: tcpAdvancedFields } = useTCPAdvancedFieldsContext();
|
||||
const { fields: browserAdvancedFields } = useBrowserAdvancedFieldsContext();
|
||||
const { fields: tlsFields } = useTLSFieldsContext();
|
||||
|
||||
const metadata = useMemo(
|
||||
() => ({
|
||||
is_tls_enabled: isTLSEnabled,
|
||||
is_zip_url_tls_enabled: isZipUrlTLSEnabled,
|
||||
}),
|
||||
[isTLSEnabled, isZipUrlTLSEnabled]
|
||||
);
|
||||
|
||||
const policyConfig: PolicyConfig = useMemo(
|
||||
() => ({
|
||||
[DataStream.HTTP]: {
|
||||
...httpSimpleFields,
|
||||
...httpAdvancedFields,
|
||||
...tlsFields,
|
||||
[ConfigKeys.METADATA]: {
|
||||
...httpSimpleFields[ConfigKeys.METADATA],
|
||||
...metadata,
|
||||
},
|
||||
[ConfigKeys.NAME]: name,
|
||||
} as HTTPFields,
|
||||
[DataStream.TCP]: {
|
||||
...tcpSimpleFields,
|
||||
...tcpAdvancedFields,
|
||||
...tlsFields,
|
||||
[ConfigKeys.METADATA]: {
|
||||
...tcpSimpleFields[ConfigKeys.METADATA],
|
||||
...metadata,
|
||||
},
|
||||
[ConfigKeys.NAME]: name,
|
||||
} as TCPFields,
|
||||
[DataStream.ICMP]: {
|
||||
...icmpSimpleFields,
|
||||
[ConfigKeys.NAME]: name,
|
||||
} as ICMPFields,
|
||||
[DataStream.BROWSER]: {
|
||||
...browserSimpleFields,
|
||||
...browserAdvancedFields,
|
||||
[ConfigKeys.METADATA]: {
|
||||
...browserSimpleFields[ConfigKeys.METADATA],
|
||||
...metadata,
|
||||
},
|
||||
[ConfigKeys.NAME]: name,
|
||||
} as BrowserFields,
|
||||
}),
|
||||
[
|
||||
metadata,
|
||||
httpSimpleFields,
|
||||
httpAdvancedFields,
|
||||
tcpSimpleFields,
|
||||
tcpAdvancedFields,
|
||||
icmpSimpleFields,
|
||||
browserSimpleFields,
|
||||
browserAdvancedFields,
|
||||
tlsFields,
|
||||
name,
|
||||
]
|
||||
);
|
||||
|
||||
return policyConfig;
|
||||
};
|
|
@ -4,11 +4,10 @@
|
|||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import { useUpdatePolicy } from './use_update_policy';
|
||||
import { renderHook } from '@testing-library/react-hooks';
|
||||
import { NewPackagePolicy } from '../../../../fleet/public';
|
||||
import { validate } from './validation';
|
||||
import { useUpdatePolicy } from './use_update_policy';
|
||||
import { NewPackagePolicy } from '../../../../../fleet/public';
|
||||
import { validate } from '../validation';
|
||||
import {
|
||||
ConfigKeys,
|
||||
DataStream,
|
||||
|
@ -20,8 +19,8 @@ import {
|
|||
ITLSFields,
|
||||
HTTPFields,
|
||||
BrowserFields,
|
||||
} from './types';
|
||||
import { defaultConfig } from './synthetics_policy_create_extension';
|
||||
} from '../types';
|
||||
import { defaultConfig } from '../synthetics_policy_create_extension';
|
||||
|
||||
describe('useBarChartsHooks', () => {
|
||||
const newPolicy: NewPackagePolicy = {
|
|
@ -5,9 +5,9 @@
|
|||
* 2.0.
|
||||
*/
|
||||
import { useEffect, useRef, useState } from 'react';
|
||||
import { NewPackagePolicy } from '../../../../fleet/public';
|
||||
import { ConfigKeys, DataStream, Validation, ICustomFields } from './types';
|
||||
import { formatters } from './helpers/formatters';
|
||||
import { NewPackagePolicy } from '../../../../../fleet/public';
|
||||
import { ConfigKeys, DataStream, Validation, ICustomFields } from '../types';
|
||||
import { formatters } from '../helpers/formatters';
|
||||
|
||||
interface Props {
|
||||
monitorType: DataStream;
|
|
@ -8,36 +8,21 @@
|
|||
import React, { memo, useEffect, useMemo } from 'react';
|
||||
import { PackagePolicyCreateExtensionComponentProps } from '../../../../fleet/public';
|
||||
import { useTrackPageview } from '../../../../observability/public';
|
||||
import {
|
||||
PolicyConfig,
|
||||
DataStream,
|
||||
ConfigKeys,
|
||||
HTTPFields,
|
||||
TCPFields,
|
||||
ICMPFields,
|
||||
BrowserFields,
|
||||
} from './types';
|
||||
import { PolicyConfig, DataStream } from './types';
|
||||
import {
|
||||
usePolicyConfigContext,
|
||||
useTCPSimpleFieldsContext,
|
||||
useTCPAdvancedFieldsContext,
|
||||
useICMPSimpleFieldsContext,
|
||||
useHTTPSimpleFieldsContext,
|
||||
useHTTPAdvancedFieldsContext,
|
||||
useTLSFieldsContext,
|
||||
useBrowserSimpleFieldsContext,
|
||||
useBrowserAdvancedFieldsContext,
|
||||
defaultHTTPAdvancedFields,
|
||||
defaultHTTPSimpleFields,
|
||||
defaultICMPSimpleFields,
|
||||
defaultHTTPAdvancedFields,
|
||||
defaultTCPSimpleFields,
|
||||
defaultTCPAdvancedFields,
|
||||
defaultICMPSimpleFields,
|
||||
defaultBrowserSimpleFields,
|
||||
defaultBrowserAdvancedFields,
|
||||
defaultTLSFields,
|
||||
} from './contexts';
|
||||
import { CustomFields } from './custom_fields';
|
||||
import { useUpdatePolicy } from './use_update_policy';
|
||||
import { useUpdatePolicy } from './hooks/use_update_policy';
|
||||
import { usePolicy } from './hooks/use_policy';
|
||||
import { validate } from './validation';
|
||||
|
||||
export const defaultConfig: PolicyConfig = {
|
||||
|
@ -65,55 +50,12 @@ export const defaultConfig: PolicyConfig = {
|
|||
*/
|
||||
export const SyntheticsPolicyCreateExtension = memo<PackagePolicyCreateExtensionComponentProps>(
|
||||
({ newPolicy, onChange }) => {
|
||||
const { monitorType, isTLSEnabled, isZipUrlTLSEnabled } = usePolicyConfigContext();
|
||||
const { fields: httpSimpleFields } = useHTTPSimpleFieldsContext();
|
||||
const { fields: tcpSimpleFields } = useTCPSimpleFieldsContext();
|
||||
const { fields: icmpSimpleFields } = useICMPSimpleFieldsContext();
|
||||
const { fields: browserSimpleFields } = useBrowserSimpleFieldsContext();
|
||||
const { fields: httpAdvancedFields } = useHTTPAdvancedFieldsContext();
|
||||
const { fields: tcpAdvancedFields } = useTCPAdvancedFieldsContext();
|
||||
const { fields: browserAdvancedFields } = useBrowserAdvancedFieldsContext();
|
||||
const { fields: tlsFields } = useTLSFieldsContext();
|
||||
|
||||
const metaData = useMemo(
|
||||
() => ({
|
||||
is_tls_enabled: isTLSEnabled,
|
||||
is_zip_url_tls_enabled: isZipUrlTLSEnabled,
|
||||
}),
|
||||
[isTLSEnabled, isZipUrlTLSEnabled]
|
||||
);
|
||||
|
||||
const policyConfig: PolicyConfig = {
|
||||
[DataStream.HTTP]: {
|
||||
...httpSimpleFields,
|
||||
...httpAdvancedFields,
|
||||
...tlsFields,
|
||||
[ConfigKeys.METADATA]: metaData,
|
||||
[ConfigKeys.NAME]: newPolicy.name,
|
||||
} as HTTPFields,
|
||||
[DataStream.TCP]: {
|
||||
...tcpSimpleFields,
|
||||
...tcpAdvancedFields,
|
||||
...tlsFields,
|
||||
[ConfigKeys.METADATA]: metaData,
|
||||
[ConfigKeys.NAME]: newPolicy.name,
|
||||
} as TCPFields,
|
||||
[DataStream.ICMP]: {
|
||||
...icmpSimpleFields,
|
||||
[ConfigKeys.NAME]: newPolicy.name,
|
||||
} as ICMPFields,
|
||||
[DataStream.BROWSER]: {
|
||||
...browserSimpleFields,
|
||||
...browserAdvancedFields,
|
||||
...tlsFields,
|
||||
[ConfigKeys.METADATA]: metaData,
|
||||
[ConfigKeys.NAME]: newPolicy.name,
|
||||
} as BrowserFields,
|
||||
};
|
||||
|
||||
useTrackPageview({ app: 'fleet', path: 'syntheticsCreate' });
|
||||
useTrackPageview({ app: 'fleet', path: 'syntheticsCreate', delay: 15000 });
|
||||
|
||||
const { monitorType } = usePolicyConfigContext();
|
||||
const policyConfig: PolicyConfig = usePolicy(newPolicy.name);
|
||||
|
||||
const dataStreams: DataStream[] = useMemo(() => {
|
||||
return newPolicy.inputs.map((input) => {
|
||||
return input.type.replace(/synthetics\//g, '') as DataStream;
|
||||
|
@ -143,7 +85,7 @@ export const SyntheticsPolicyCreateExtension = memo<PackagePolicyCreateExtension
|
|||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, []);
|
||||
|
||||
return <CustomFields typeEditable validate={validate[monitorType]} dataStreams={dataStreams} />;
|
||||
return <CustomFields validate={validate[monitorType]} dataStreams={dataStreams} />;
|
||||
}
|
||||
);
|
||||
SyntheticsPolicyCreateExtension.displayName = 'SyntheticsPolicyCreateExtension';
|
||||
|
|
|
@ -5,32 +5,14 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import React, { memo, useMemo } from 'react';
|
||||
import React, { memo } from 'react';
|
||||
import { PackagePolicyEditExtensionComponentProps } from '../../../../fleet/public';
|
||||
import { useTrackPageview } from '../../../../observability/public';
|
||||
import {
|
||||
usePolicyConfigContext,
|
||||
useTCPSimpleFieldsContext,
|
||||
useTCPAdvancedFieldsContext,
|
||||
useICMPSimpleFieldsContext,
|
||||
useHTTPSimpleFieldsContext,
|
||||
useHTTPAdvancedFieldsContext,
|
||||
useTLSFieldsContext,
|
||||
useBrowserSimpleFieldsContext,
|
||||
useBrowserAdvancedFieldsContext,
|
||||
} from './contexts';
|
||||
import {
|
||||
ICustomFields,
|
||||
DataStream,
|
||||
HTTPFields,
|
||||
TCPFields,
|
||||
ICMPFields,
|
||||
BrowserFields,
|
||||
ConfigKeys,
|
||||
PolicyConfig,
|
||||
} from './types';
|
||||
import { usePolicyConfigContext } from './contexts';
|
||||
import { ICustomFields, PolicyConfig } from './types';
|
||||
import { CustomFields } from './custom_fields';
|
||||
import { useUpdatePolicy } from './use_update_policy';
|
||||
import { useUpdatePolicy } from './hooks/use_update_policy';
|
||||
import { usePolicy } from './hooks/use_policy';
|
||||
import { validate } from './validation';
|
||||
|
||||
interface SyntheticsPolicyEditExtensionProps {
|
||||
|
@ -47,50 +29,9 @@ export const SyntheticsPolicyEditExtension = memo<SyntheticsPolicyEditExtensionP
|
|||
({ newPolicy, onChange, defaultConfig }) => {
|
||||
useTrackPageview({ app: 'fleet', path: 'syntheticsEdit' });
|
||||
useTrackPageview({ app: 'fleet', path: 'syntheticsEdit', delay: 15000 });
|
||||
const { monitorType, isTLSEnabled, isZipUrlTLSEnabled } = usePolicyConfigContext();
|
||||
const { fields: httpSimpleFields } = useHTTPSimpleFieldsContext();
|
||||
const { fields: tcpSimpleFields } = useTCPSimpleFieldsContext();
|
||||
const { fields: icmpSimpleFields } = useICMPSimpleFieldsContext();
|
||||
const { fields: httpAdvancedFields } = useHTTPAdvancedFieldsContext();
|
||||
const { fields: tcpAdvancedFields } = useTCPAdvancedFieldsContext();
|
||||
const { fields: tlsFields } = useTLSFieldsContext();
|
||||
const { fields: browserSimpleFields } = useBrowserSimpleFieldsContext();
|
||||
const { fields: browserAdvancedFields } = useBrowserAdvancedFieldsContext();
|
||||
|
||||
const metadata = useMemo(
|
||||
() => ({
|
||||
is_tls_enabled: isTLSEnabled,
|
||||
is_zip_url_tls_enabled: isZipUrlTLSEnabled,
|
||||
}),
|
||||
[isTLSEnabled, isZipUrlTLSEnabled]
|
||||
);
|
||||
|
||||
const policyConfig: PolicyConfig = {
|
||||
[DataStream.HTTP]: {
|
||||
...httpSimpleFields,
|
||||
...httpAdvancedFields,
|
||||
...tlsFields,
|
||||
[ConfigKeys.METADATA]: metadata,
|
||||
[ConfigKeys.NAME]: newPolicy.name,
|
||||
} as HTTPFields,
|
||||
[DataStream.TCP]: {
|
||||
...tcpSimpleFields,
|
||||
...tcpAdvancedFields,
|
||||
...tlsFields,
|
||||
[ConfigKeys.METADATA]: metadata,
|
||||
[ConfigKeys.NAME]: newPolicy.name,
|
||||
} as TCPFields,
|
||||
[DataStream.ICMP]: {
|
||||
...icmpSimpleFields,
|
||||
[ConfigKeys.NAME]: newPolicy.name,
|
||||
} as ICMPFields,
|
||||
[DataStream.BROWSER]: {
|
||||
...browserSimpleFields,
|
||||
...browserAdvancedFields,
|
||||
[ConfigKeys.METADATA]: metadata,
|
||||
[ConfigKeys.NAME]: newPolicy.name,
|
||||
} as BrowserFields,
|
||||
};
|
||||
const { monitorType } = usePolicyConfigContext();
|
||||
const policyConfig: PolicyConfig = usePolicy(newPolicy.name);
|
||||
|
||||
useUpdatePolicy({
|
||||
defaultConfig,
|
||||
|
|
|
@ -1075,6 +1075,59 @@ describe('<SyntheticsPolicyEditExtension />', () => {
|
|||
expect(queryByLabelText('Host')).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it.each([
|
||||
[true, 'Testing script'],
|
||||
[false, 'Inline script'],
|
||||
])(
|
||||
'browser monitors - auto selects the right tab depending on source metadata',
|
||||
async (isGeneratedScript, text) => {
|
||||
const currentPolicy = {
|
||||
...defaultCurrentPolicy,
|
||||
inputs: [
|
||||
{
|
||||
...defaultNewPolicy.inputs[0],
|
||||
enabled: false,
|
||||
},
|
||||
{
|
||||
...defaultNewPolicy.inputs[1],
|
||||
enabled: false,
|
||||
},
|
||||
{
|
||||
...defaultNewPolicy.inputs[2],
|
||||
enabled: false,
|
||||
},
|
||||
{
|
||||
...defaultNewPolicy.inputs[3],
|
||||
enabled: true,
|
||||
streams: [
|
||||
{
|
||||
...defaultNewPolicy.inputs[3].streams[0],
|
||||
vars: {
|
||||
...defaultNewPolicy.inputs[3].streams[0].vars,
|
||||
'source.inline.script': {
|
||||
type: 'yaml',
|
||||
value: JSON.stringify('step(() => {})'),
|
||||
},
|
||||
__ui: {
|
||||
type: 'yaml',
|
||||
value: JSON.stringify({
|
||||
script_source: {
|
||||
is_generated_script: isGeneratedScript,
|
||||
},
|
||||
}),
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
const { getByText } = render(<WrappedComponent policy={currentPolicy} />);
|
||||
|
||||
expect(getByText(text)).toBeInTheDocument();
|
||||
}
|
||||
);
|
||||
it('hides tls fields when metadata.is_tls_enabled is false', async () => {
|
||||
const { getByLabelText, queryByLabelText } = render(
|
||||
<WrappedComponent
|
||||
|
|
|
@ -97,6 +97,7 @@ export const SyntheticsPolicyEditExtensionWrapper = memo<PackagePolicyEditExtens
|
|||
defaultMonitorType={monitorType}
|
||||
defaultIsTLSEnabled={isTLSEnabled}
|
||||
defaultIsZipUrlTLSEnabled={isZipUrlTLSEnabled}
|
||||
isEditable={true}
|
||||
>
|
||||
<TLSFieldsContextProvider defaultValues={isTLSEnabled ? defaultTLSConfig : undefined}>
|
||||
<HTTPContextProvider defaultValues={fullDefaultConfig?.[DataStream.HTTP]}>
|
||||
|
|
|
@ -129,6 +129,10 @@ export enum ConfigKeys {
|
|||
export interface Metadata {
|
||||
is_tls_enabled?: boolean;
|
||||
is_zip_url_tls_enabled?: boolean;
|
||||
script_source?: {
|
||||
is_generated_script: boolean;
|
||||
file_name: string;
|
||||
};
|
||||
}
|
||||
|
||||
export interface ICommonFields {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue