diff --git a/.buildkite/ftr_configs.yml b/.buildkite/ftr_configs.yml index c0205e8af28f1..67976c2b1e198 100644 --- a/.buildkite/ftr_configs.yml +++ b/.buildkite/ftr_configs.yml @@ -155,7 +155,6 @@ enabled: - x-pack/test/functional_embedded/config.ts - x-pack/test/functional_enterprise_search/without_host_configured.config.ts - x-pack/test/functional_execution_context/config.ts - - x-pack/test/functional_synthetics/config.js - x-pack/test/functional_with_es_ssl/config.ts - x-pack/test/functional/apps/advanced_settings/config.ts - x-pack/test/functional/apps/aiops/config.ts diff --git a/x-pack/plugins/fleet/README.md b/x-pack/plugins/fleet/README.md index 5b7a7fcb00039..9d9c6c9720de4 100644 --- a/x-pack/plugins/fleet/README.md +++ b/x-pack/plugins/fleet/README.md @@ -181,7 +181,6 @@ As part of the bundled package update process, we'll likely also need to update - `x-pack/test/fleet_api_integration/config.ts` - `x-pack/plugins/fleet/server/integration_tests/helpers/docker_registry_helper.ts` - `x-pack/test/functional/config.base.js` -- `x-pack/test/functional_synthetics/config.js` To update this registry image, pull the digest SHA from the package storage Jenkins pipeline at https://beats-ci.elastic.co/blue/organizations/jenkins/Ingest-manager%2Fpackage-storage/activity and update the files above. The digest value should appear in the "publish Docker image" step as part of the `docker push` command in the logs. diff --git a/x-pack/plugins/synthetics/public/legacy_uptime/components/common/header/manage_monitors_btn.tsx b/x-pack/plugins/synthetics/public/legacy_uptime/components/common/header/manage_monitors_btn.tsx index 365ea6ccdd446..f8447d1cb2741 100644 --- a/x-pack/plugins/synthetics/public/legacy_uptime/components/common/header/manage_monitors_btn.tsx +++ b/x-pack/plugins/synthetics/public/legacy_uptime/components/common/header/manage_monitors_btn.tsx @@ -20,11 +20,6 @@ export const ManageMonitorsBtn = () => { const history = useHistory(); - const handleOnClick = () => { - setIsOpen(false); - history.push(MONITOR_MANAGEMENT_ROUTE + '/all'); - }; - return ( {

{PUBLIC_BETA_DESCRIPTION}

- + {MONITOR_MANAGEMENT_LABEL} @@ -56,7 +57,9 @@ export const ManageMonitorsBtn = () => { aria-label={NAVIGATE_LABEL} color="text" data-test-subj="syntheticsManagementPageLink" - onClick={handleOnClick} + href={history.createHref({ + pathname: MONITOR_MANAGEMENT_ROUTE, + })} > void }) => { + const { application } = useKibana().services; + + return ( + + {HEADER_TEXT} + + } + onCancel={onCancel} + onConfirm={() => { + application?.navigateToApp('uptime', { path: '/manage-monitors' }); + }} + confirmButtonText={GO_MONITOR_MANAGEMENT_TEXT} + cancelButtonText={GO_BACK_TEXT} + > +

+ +

+

+

  • + +
  • +
  • + +
  • +
  • + +
  • +
  • + +
  • +

    +

    + + {READ_DOCS_TEXT} + + ), + }} + /> +

    +
    + ); +}; + +const HEADER_TEXT = i18n.translate('xpack.synthetics.deprecateNoticeModal.headerText', { + defaultMessage: 'Synthetic Monitoring is now available out of the box in Uptime', +}); + +const GO_BACK_TEXT = i18n.translate('xpack.synthetics.deprecateNoticeModal.goBack', { + defaultMessage: 'Go back', +}); + +const READ_DOCS_TEXT = i18n.translate('xpack.synthetics.deprecateNoticeModal.readDocs', { + defaultMessage: 'read docs.', +}); + +const GO_MONITOR_MANAGEMENT_TEXT = i18n.translate( + 'xpack.synthetics.deprecateNoticeModal.goToMonitorManagement', + { + defaultMessage: 'Go to Monitor Management', + } +); diff --git a/x-pack/plugins/synthetics/public/legacy_uptime/components/fleet_package/synthetics_policy_create_extension.tsx b/x-pack/plugins/synthetics/public/legacy_uptime/components/fleet_package/synthetics_policy_create_extension.tsx index d84420f155798..d699fcb203ede 100644 --- a/x-pack/plugins/synthetics/public/legacy_uptime/components/fleet_package/synthetics_policy_create_extension.tsx +++ b/x-pack/plugins/synthetics/public/legacy_uptime/components/fleet_package/synthetics_policy_create_extension.tsx @@ -5,16 +5,13 @@ * 2.0. */ -import React, { memo, useEffect, useMemo } from 'react'; +import React, { memo, useCallback } from 'react'; import { PackagePolicyCreateExtensionComponentProps } from '@kbn/fleet-plugin/public'; import { useTrackPageview } from '@kbn/observability-plugin/public'; -import { DataStream, PolicyConfig, MonitorFields } from './types'; -import { usePolicyConfigContext } from './contexts'; +import { useKibana } from '@kbn/kibana-react-plugin/public'; +import { DeprecateNoticeModal } from './deprecate_notice_modal'; +import { PolicyConfig } from './types'; import { DEFAULT_FIELDS } from '../../../../common/constants/monitor_defaults'; -import { CustomFields } from './custom_fields'; -import { useUpdatePolicy } from './hooks/use_update_policy'; -import { usePolicy } from './hooks/use_policy'; -import { validate } from './validation'; export const defaultConfig: PolicyConfig = DEFAULT_FIELDS; @@ -27,39 +24,16 @@ export const SyntheticsPolicyCreateExtension = memo { - return newPolicy.inputs.map((input) => { - return input.type.replace(/synthetics\//g, '') as DataStream; - }); - }, [newPolicy]); - - useUpdatePolicy({ - monitorType, - defaultConfig: defaultConfig[monitorType] as Partial, - config: policyConfig[monitorType] as Partial, - newPolicy, - onChange, - validate, - }); + const { package: pkg } = newPolicy; - // Fleet will initialize the create form with a default name for the integratin policy, however, - // for synthetics, we want the user to explicitely type in a name to use as the monitor name, - // so we blank it out only during 1st component render (thus why the eslint disabled rule below). - useEffect(() => { - onChange({ - isValid: false, - updatedPolicy: { - ...newPolicy, - name: '', - }, + const onCancel = useCallback(() => { + application?.navigateToApp('integrations', { + path: `/detail/${pkg?.name}-${pkg?.version}/overview`, }); - // eslint-disable-next-line react-hooks/exhaustive-deps - }, []); - - return ; + }, [application, pkg?.name, pkg?.version]); + return ; } ); SyntheticsPolicyCreateExtension.displayName = 'SyntheticsPolicyCreateExtension'; diff --git a/x-pack/plugins/synthetics/public/legacy_uptime/components/fleet_package/synthetics_policy_create_extension_wrapper.test.tsx b/x-pack/plugins/synthetics/public/legacy_uptime/components/fleet_package/synthetics_policy_create_extension_wrapper.test.tsx deleted file mode 100644 index 9c1ff4fc16126..0000000000000 --- a/x-pack/plugins/synthetics/public/legacy_uptime/components/fleet_package/synthetics_policy_create_extension_wrapper.test.tsx +++ /dev/null @@ -1,837 +0,0 @@ -/* - * 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 'jest-canvas-mock'; - -import React from 'react'; -import { fireEvent, waitFor } from '@testing-library/react'; -import { render } from '../../lib/helper/rtl_helpers'; -import { NewPackagePolicy } from '@kbn/fleet-plugin/public'; -import { SyntheticsPolicyCreateExtensionWrapper } from './synthetics_policy_create_extension_wrapper'; -import { defaultConfig } from './synthetics_policy_create_extension'; -import { ConfigKey, DataStream, ScheduleUnit, VerificationMode } from './types'; - -// ensures that fields appropriately match to their label -jest.mock('@elastic/eui/lib/services/accessibility/html_id_generator', () => ({ - ...jest.requireActual('@elastic/eui/lib/services/accessibility/html_id_generator'), - htmlIdGenerator: () => () => `id-${Math.random()}`, -})); - -// ensures that fields appropriately match to their label -jest.mock('@elastic/eui/lib/services/accessibility', () => ({ - ...jest.requireActual('@elastic/eui/lib/services/accessibility'), - useGeneratedHtmlId: () => `id-${Math.random()}`, -})); - -jest.mock('@kbn/kibana-react-plugin/public', () => { - const original = jest.requireActual('@kbn/kibana-react-plugin/public'); - return { - ...original, - // Mocking CodeEditor, which uses React Monaco under the hood - CodeEditor: (props: any) => ( - { - props.onChange(e.jsonContent); - }} - /> - ), - }; -}); - -const defaultNewPolicy: NewPackagePolicy = { - name: 'samplePolicyName', - description: '', - namespace: 'default', - policy_id: 'ae774160-8e49-11eb-aba5-99269d21ba6e', - enabled: true, - inputs: [ - { - type: 'synthetics/http', - enabled: true, - streams: [ - { - enabled: true, - data_stream: { - type: 'synthetics', - dataset: 'http', - }, - vars: { - __ui: { - value: JSON.stringify({ is_tls_enabled: true }), - type: 'yaml', - }, - type: { - value: 'http', - type: 'text', - }, - name: { - value: 'Sample name', - type: 'text', - }, - schedule: { - value: '"@every 5s"', - type: 'text', - }, - urls: { - value: '', - type: 'text', - }, - 'service.name': { - value: '', - type: 'text', - }, - timeout: { - value: '16s', - type: 'text', - }, - max_redirects: { - value: 0, - type: 'integer', - }, - proxy_url: { - value: '', - type: 'text', - }, - tags: { - value: '[]', - type: 'yaml', - }, - 'response.include_headers': { - value: true, - type: 'bool', - }, - 'response.include_body': { - value: 'on_error', - type: 'text', - }, - 'check.request.method': { - value: 'GET', - type: 'text', - }, - 'check.request.headers': { - value: '{}', - type: 'yaml', - }, - 'check.request.body': { - value: '""', - type: 'yaml', - }, - 'check.response.status': { - value: '[]', - type: 'yaml', - }, - 'check.response.headers': { - value: '{}', - type: 'yaml', - }, - 'check.response.body.positive': { - value: '[]', - type: 'yaml', - }, - 'check.response.body.negative': { - value: '[]', - type: 'yaml', - }, - 'ssl.certificate_authorities': { - value: '', - type: 'yaml', - }, - 'ssl.certificate': { - value: '', - type: 'yaml', - }, - 'ssl.key': { - value: '', - type: 'yaml', - }, - 'ssl.key_passphrase': { - type: 'text', - }, - 'ssl.verification_mode': { - value: 'full', - type: 'text', - }, - }, - }, - ], - }, - { - type: 'synthetics/tcp', - enabled: false, - streams: [ - { - enabled: false, - data_stream: { - type: 'synthetics', - dataset: 'tcp', - }, - vars: { - type: { - value: 'tcp', - type: 'text', - }, - name: { - value: 'Sample name', - type: 'text', - }, - schedule: { - value: '10s', - type: 'text', - }, - hosts: { - type: 'text', - }, - 'service.name': { - type: 'text', - }, - timeout: { - type: 'text', - }, - max_redirects: { - type: 'integer', - }, - proxy_url: { - type: 'text', - }, - proxy_use_local_resolver: { - value: false, - type: 'bool', - }, - tags: { - type: 'yaml', - }, - 'check.send': { - type: 'text', - }, - 'check.receive': { - type: 'yaml', - }, - 'ssl.certificate_authorities': { - type: 'yaml', - }, - 'ssl.certificate': { - type: 'yaml', - }, - 'ssl.key': { - type: 'yaml', - }, - 'ssl.key_passphrase': { - type: 'text', - }, - 'ssl.verification_mode': { - type: 'text', - }, - }, - }, - ], - }, - { - type: 'synthetics/icmp', - enabled: false, - streams: [ - { - enabled: false, - data_stream: { - type: 'synthetics', - dataset: 'icmp', - }, - vars: { - type: { - value: 'icmp', - type: 'text', - }, - name: { - value: 'Sample name', - type: 'text', - }, - schedule: { - value: '10s', - type: 'text', - }, - wait: { - value: '1s', - type: 'text', - }, - hosts: { - type: 'text', - }, - 'service.name': { - type: 'text', - }, - timeout: { - type: 'text', - }, - tags: { - type: 'yaml', - }, - }, - }, - ], - }, - { - type: 'synthetics/browser', - enabled: false, - streams: [ - { - enabled: false, - data_stream: { - type: 'synthetics', - dataset: 'browser', - }, - vars: { - type: { - value: 'browser', - type: 'text', - }, - name: { - value: 'Sample name', - type: 'text', - }, - schedule: { - value: '10s', - type: 'text', - }, - 'source.zip_url.url': { - type: 'text', - }, - 'source.zip_url.username': { - type: 'text', - }, - 'source.zip_url.password': { - type: 'password', - }, - 'source.zip_url.folder': { - type: 'text', - }, - 'source.inline.script': { - type: 'yaml', - }, - timeout: { - type: 'text', - }, - tags: { - type: 'yaml', - }, - }, - }, - ], - }, - ], - package: { - name: 'synthetics', - title: 'Elastic Synthetics', - version: '0.66.0', - }, -}; - -const defaultHTTPConfig = defaultConfig[DataStream.HTTP]; -const defaultTCPConfig = defaultConfig[DataStream.TCP]; - -describe('', () => { - const onChange = jest.fn(); - const WrappedComponent = ({ newPolicy = defaultNewPolicy }) => { - return ; - }; - - beforeEach(() => { - onChange.mockClear(); - }); - - it('renders SyntheticsPolicyCreateExtension', async () => { - const { getByText, getByLabelText, queryByLabelText } = render(); - const monitorType = queryByLabelText('Monitor Type') as HTMLInputElement; - const url = getByLabelText('URL') as HTMLInputElement; - const proxyUrl = getByLabelText('Proxy URL') as HTMLInputElement; - const monitorIntervalNumber = getByLabelText('Number') as HTMLInputElement; - const monitorIntervalUnit = getByLabelText('Unit') as HTMLInputElement; - 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).toBeInTheDocument(); - expect(monitorType.value).toEqual(DataStream.HTTP); - expect(url).toBeInTheDocument(); - expect(url.value).toEqual(defaultHTTPConfig[ConfigKey.URLS]); - expect(proxyUrl).toBeInTheDocument(); - expect(proxyUrl.value).toEqual(defaultHTTPConfig[ConfigKey.PROXY_URL]); - expect(monitorIntervalNumber).toBeInTheDocument(); - expect(monitorIntervalNumber.value).toEqual(defaultHTTPConfig[ConfigKey.SCHEDULE].number); - expect(monitorIntervalUnit).toBeInTheDocument(); - expect(monitorIntervalUnit.value).toEqual(defaultHTTPConfig[ConfigKey.SCHEDULE].unit); - expect(apmServiceName).toBeInTheDocument(); - expect(apmServiceName.value).toEqual(defaultHTTPConfig[ConfigKey.APM_SERVICE_NAME]); - expect(maxRedirects).toBeInTheDocument(); - expect(maxRedirects.value).toEqual(`${defaultHTTPConfig[ConfigKey.MAX_REDIRECTS]}`); - expect(timeout).toBeInTheDocument(); - expect(timeout.value).toEqual(`${defaultHTTPConfig[ConfigKey.TIMEOUT]}`); - - // ensure other monitor type options are not in the DOM - expect(queryByLabelText('Host')).not.toBeInTheDocument(); - expect(queryByLabelText('Wait in seconds')).not.toBeInTheDocument(); - - // ensure at least one http advanced option is present - const advancedOptionsButton = getByText('Advanced HTTP options'); - fireEvent.click(advancedOptionsButton); - await waitFor(() => { - expect(getByLabelText('Request method')).toBeInTheDocument(); - }); - }); - - it('handles updating fields', async () => { - const { getByLabelText } = render(); - const url = getByLabelText('URL') as HTMLInputElement; - const proxyUrl = getByLabelText('Proxy URL') as HTMLInputElement; - const monitorIntervalNumber = getByLabelText('Number') as HTMLInputElement; - const monitorIntervalUnit = getByLabelText('Unit') as HTMLInputElement; - const apmServiceName = getByLabelText('APM service name') as HTMLInputElement; - const maxRedirects = getByLabelText('Max redirects') as HTMLInputElement; - const timeout = getByLabelText('Timeout in seconds') as HTMLInputElement; - - fireEvent.change(url, { target: { value: 'http://elastic.co' } }); - fireEvent.change(proxyUrl, { target: { value: 'http://proxy.co' } }); - fireEvent.change(monitorIntervalNumber, { target: { value: '1' } }); - fireEvent.change(monitorIntervalUnit, { target: { value: ScheduleUnit.MINUTES } }); - fireEvent.change(apmServiceName, { target: { value: 'APM Service' } }); - fireEvent.change(maxRedirects, { target: { value: '2' } }); - fireEvent.change(timeout, { target: { value: '3' } }); - - expect(url.value).toEqual('http://elastic.co'); - expect(proxyUrl.value).toEqual('http://proxy.co'); - expect(monitorIntervalNumber.value).toEqual('1'); - expect(monitorIntervalUnit.value).toEqual(ScheduleUnit.MINUTES); - expect(apmServiceName.value).toEqual('APM Service'); - expect(maxRedirects.value).toEqual('2'); - expect(timeout.value).toEqual('3'); - - await waitFor(() => { - expect(onChange).toBeCalledWith({ - isValid: true, - updatedPolicy: { - ...defaultNewPolicy, - inputs: [ - { - ...defaultNewPolicy.inputs[0], - streams: [ - { - ...defaultNewPolicy.inputs[0].streams[0], - vars: { - ...defaultNewPolicy.inputs[0].streams[0].vars, - urls: { - value: 'http://elastic.co', - type: 'text', - }, - proxy_url: { - value: 'http://proxy.co', - type: 'text', - }, - schedule: { - value: '"@every 1m"', - type: 'text', - }, - 'service.name': { - value: 'APM Service', - type: 'text', - }, - max_redirects: { - value: '2', - type: 'integer', - }, - timeout: { - value: '3s', - type: 'text', - }, - }, - }, - ], - }, - defaultNewPolicy.inputs[1], - defaultNewPolicy.inputs[2], - defaultNewPolicy.inputs[3], - ], - }, - }); - }); - }); - - it('handles calling onChange', async () => { - const { getByLabelText } = render(); - const url = getByLabelText('URL') as HTMLInputElement; - - fireEvent.change(url, { target: { value: 'http://elastic.co' } }); - - await waitFor(() => { - expect(onChange).toBeCalledWith({ - isValid: true, - updatedPolicy: { - ...defaultNewPolicy, - inputs: [ - { - ...defaultNewPolicy.inputs[0], - streams: [ - { - ...defaultNewPolicy.inputs[0].streams[0], - vars: { - ...defaultNewPolicy.inputs[0].streams[0].vars, - urls: { - value: 'http://elastic.co', - type: 'text', - }, - }, - }, - ], - }, - defaultNewPolicy.inputs[1], - defaultNewPolicy.inputs[2], - defaultNewPolicy.inputs[3], - ], - }, - }); - }); - }); - - it('handles switching monitor type', async () => { - const { getByText, getByLabelText, queryByLabelText } = render(); - const monitorType = getByLabelText('Monitor Type') as HTMLInputElement; - expect(monitorType).toBeInTheDocument(); - expect(monitorType.value).toEqual(DataStream.HTTP); - fireEvent.change(monitorType, { target: { value: DataStream.TCP } }); - - await waitFor(() => { - expect(onChange).toBeCalledWith({ - isValid: false, - updatedPolicy: { - ...defaultNewPolicy, - inputs: [ - { - ...defaultNewPolicy.inputs[0], - enabled: false, - }, - { - ...defaultNewPolicy.inputs[1], - enabled: true, - }, - defaultNewPolicy.inputs[2], - defaultNewPolicy.inputs[3], - ], - }, - }); - }); - - // expect tcp fields to be in the DOM - const host = getByLabelText('Host:Port') as HTMLInputElement; - - expect(host).toBeInTheDocument(); - expect(host.value).toEqual(defaultTCPConfig[ConfigKey.HOSTS]); - - // expect HTTP fields not to be in the DOM - expect(queryByLabelText('URL')).not.toBeInTheDocument(); - expect(queryByLabelText('Max redirects')).not.toBeInTheDocument(); - - // ensure at least one tcp advanced option is present - const advancedOptionsButton = getByText('Advanced TCP options'); - fireEvent.click(advancedOptionsButton); - - expect(queryByLabelText('Request method')).not.toBeInTheDocument(); - expect(getByLabelText('Request payload')).toBeInTheDocument(); - - fireEvent.change(monitorType, { target: { value: DataStream.ICMP } }); - - // expect ICMP fields to be in the DOM - expect(getByLabelText('Wait in seconds')).toBeInTheDocument(); - - // expect TCP fields not to be in the DOM - expect(queryByLabelText('Proxy URL')).not.toBeInTheDocument(); - }); - - it('handles http validation', async () => { - const { getByText, getByLabelText, queryByText } = render(); - - const url = getByLabelText('URL') as HTMLInputElement; - const monitorIntervalNumber = getByLabelText('Number') as HTMLInputElement; - const maxRedirects = getByLabelText('Max redirects') as HTMLInputElement; - const timeout = getByLabelText('Timeout in seconds') as HTMLInputElement; - - // create errors - fireEvent.change(monitorIntervalNumber, { target: { value: '-1' } }); - fireEvent.change(maxRedirects, { target: { value: '-1' } }); - fireEvent.change(timeout, { target: { value: '-1' } }); - - const urlError = getByText('URL is required'); - const monitorIntervalError = getByText('Monitor frequency is required'); - const maxRedirectsError = getByText('Max redirects must be 0 or greater'); - const timeoutError = getByText('Timeout must be greater than or equal to 0'); - - expect(urlError).toBeInTheDocument(); - expect(monitorIntervalError).toBeInTheDocument(); - expect(maxRedirectsError).toBeInTheDocument(); - expect(timeoutError).toBeInTheDocument(); - - // expect onChange to be called with isValid false - await waitFor(() => { - expect(onChange).toBeCalledWith( - expect.objectContaining({ - isValid: false, - }) - ); - }); - - // resolve errors - fireEvent.change(url, { target: { value: 'http://elastic.co' } }); - fireEvent.change(monitorIntervalNumber, { target: { value: '1' } }); - fireEvent.change(maxRedirects, { target: { value: '1' } }); - fireEvent.change(timeout, { target: { value: '1' } }); - - // expect onChange to be called with isValid true - await waitFor(() => { - expect(queryByText('URL is required')).not.toBeInTheDocument(); - expect(queryByText('Monitor frequency is required')).not.toBeInTheDocument(); - expect(queryByText('Max redirects must be 0 or greater')).not.toBeInTheDocument(); - expect(queryByText('Timeout must be greater than or equal to 0')).not.toBeInTheDocument(); - expect(onChange).toBeCalledWith( - expect.objectContaining({ - isValid: true, - }) - ); - }); - }); - - it('handles tcp validation', async () => { - const { getByText, getByLabelText, queryByText } = render(); - - const monitorType = getByLabelText('Monitor Type') as HTMLInputElement; - fireEvent.change(monitorType, { target: { value: DataStream.TCP } }); - - const host = getByLabelText('Host:Port') as HTMLInputElement; - const monitorIntervalNumber = getByLabelText('Number') as HTMLInputElement; - const timeout = getByLabelText('Timeout in seconds') as HTMLInputElement; - - // create errors - fireEvent.change(host, { target: { value: 'localhost' } }); // host without port - fireEvent.change(monitorIntervalNumber, { target: { value: '-1' } }); - fireEvent.change(timeout, { target: { value: '-1' } }); - - await waitFor(() => { - const hostError = getByText('Host and port are required'); - const monitorIntervalError = getByText('Monitor frequency 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, - }) - ); - }); - - // resolve errors - fireEvent.change(host, { target: { value: 'smtp.gmail.com:587' } }); - fireEvent.change(monitorIntervalNumber, { target: { value: '1' } }); - fireEvent.change(timeout, { target: { value: '1' } }); - - await waitFor(() => { - expect(queryByText('Host and port are required')).not.toBeInTheDocument(); - expect(queryByText('Monitor frequency is required')).not.toBeInTheDocument(); - expect(queryByText('Max redirects must be 0 or greater')).not.toBeInTheDocument(); - expect(queryByText('Timeout must be greater than or equal to 0')).not.toBeInTheDocument(); - expect(onChange).toBeCalledWith( - expect.objectContaining({ - isValid: true, - }) - ); - }); - }); - - it('handles icmp validation', async () => { - const { getByText, getByLabelText, queryByText } = render(); - - const monitorType = getByLabelText('Monitor Type') as HTMLInputElement; - fireEvent.change(monitorType, { target: { value: DataStream.ICMP } }); - - const host = getByLabelText('Host') as HTMLInputElement; - const monitorIntervalNumber = getByLabelText('Number') as HTMLInputElement; - const timeout = getByLabelText('Timeout in seconds') as HTMLInputElement; - const wait = getByLabelText('Wait in seconds') as HTMLInputElement; - - // create errors - fireEvent.change(host, { target: { value: '' } }); - fireEvent.change(monitorIntervalNumber, { target: { value: '-1' } }); - fireEvent.change(timeout, { target: { value: '-1' } }); - fireEvent.change(wait, { target: { value: '-1' } }); - - await waitFor(() => { - const hostError = getByText('Host is required'); - const monitorIntervalError = getByText('Monitor frequency is required'); - const timeoutError = getByText('Timeout must be greater than or equal to 0'); - const waitError = getByText('Wait must be 0 or greater'); - - expect(hostError).toBeInTheDocument(); - expect(monitorIntervalError).toBeInTheDocument(); - expect(timeoutError).toBeInTheDocument(); - expect(waitError).toBeInTheDocument(); - expect(onChange).toBeCalledWith( - expect.objectContaining({ - isValid: false, - }) - ); - }); - - // resolve errors - fireEvent.change(host, { target: { value: '1.1.1.1' } }); - fireEvent.change(monitorIntervalNumber, { target: { value: '1' } }); - fireEvent.change(timeout, { target: { value: '1' } }); - fireEvent.change(wait, { target: { value: '1' } }); - - await waitFor(() => { - expect(queryByText('Host is required')).not.toBeInTheDocument(); - expect(queryByText('Monitor frequency is required')).not.toBeInTheDocument(); - expect(queryByText('Timeout must be greater than or equal to 0')).not.toBeInTheDocument(); - expect(queryByText('Wait must be 0 or greater')).not.toBeInTheDocument(); - expect(onChange).toBeCalledWith( - expect.objectContaining({ - isValid: true, - }) - ); - }); - }); - - it('handles browser validation', async () => { - const { getByText, getByLabelText, queryByText, getByRole, getByTestId } = render( - - ); - - const monitorType = getByLabelText('Monitor Type') as HTMLInputElement; - fireEvent.change(monitorType, { target: { value: DataStream.BROWSER } }); - - const zip = getByTestId('syntheticsSourceTab__zipUrl'); - fireEvent.click(zip); - const zipUrl = getByRole('textbox', { name: 'Zip URL' }) as HTMLInputElement; - const monitorIntervalNumber = getByLabelText('Number') as HTMLInputElement; - - // create errors - fireEvent.change(zipUrl, { target: { value: '' } }); - fireEvent.change(monitorIntervalNumber, { target: { value: '-1' } }); - - await waitFor(() => { - const hostError = getByText('Zip URL is required'); - const monitorIntervalError = getByText('Monitor frequency is required'); - - expect(hostError).toBeInTheDocument(); - expect(monitorIntervalError).toBeInTheDocument(); - expect(onChange).toBeCalledWith( - expect.objectContaining({ - isValid: false, - }) - ); - }); - - // resolve errors - fireEvent.change(zipUrl, { target: { value: 'http://github.com/tests.zip' } }); - fireEvent.change(monitorIntervalNumber, { target: { value: '1' } }); - - await waitFor(() => { - expect(queryByText('Zip URL is required')).not.toBeInTheDocument(); - expect(queryByText('Monitor frequency is required')).not.toBeInTheDocument(); - expect(onChange).toBeCalledWith( - expect.objectContaining({ - isValid: true, - }) - ); - }); - - // test inline script validation - fireEvent.click(getByText('Inline script')); - - await waitFor(() => { - expect(getByText('Script is required')).toBeInTheDocument(); - }); - }); - - it('handles changing TLS fields', async () => { - const { findByLabelText, queryByLabelText } = render(); - const enableSSL = queryByLabelText('Enable TLS configuration') as HTMLInputElement; - - // ensure at least one http advanced option is present - fireEvent.click(enableSSL); - - const ca = (await findByLabelText('Certificate authorities')) as HTMLInputElement; - const clientKey = (await findByLabelText('Client key')) as HTMLInputElement; - const clientKeyPassphrase = (await findByLabelText( - 'Client key passphrase' - )) as HTMLInputElement; - const clientCertificate = (await findByLabelText('Client certificate')) as HTMLInputElement; - const verificationMode = (await findByLabelText('Verification mode')) as HTMLInputElement; - - await waitFor(() => { - fireEvent.change(ca, { target: { value: 'certificateAuthorities' } }); - expect(ca.value).toEqual(defaultHTTPConfig[ConfigKey.TLS_CERTIFICATE_AUTHORITIES]); - }); - await waitFor(() => { - fireEvent.change(clientCertificate, { target: { value: 'clientCertificate' } }); - expect(clientCertificate.value).toEqual(defaultHTTPConfig[ConfigKey.TLS_KEY]); - }); - await waitFor(() => { - fireEvent.change(clientKey, { target: { value: 'clientKey' } }); - expect(clientKey.value).toEqual(defaultHTTPConfig[ConfigKey.TLS_KEY]); - }); - await waitFor(() => { - fireEvent.change(clientKeyPassphrase, { target: { value: 'clientKeyPassphrase' } }); - expect(clientKeyPassphrase.value).toEqual(defaultHTTPConfig[ConfigKey.TLS_KEY_PASSPHRASE]); - }); - await waitFor(() => { - fireEvent.change(verificationMode, { target: { value: VerificationMode.NONE } }); - expect(verificationMode.value).toEqual(defaultHTTPConfig[ConfigKey.TLS_VERIFICATION_MODE]); - }); - - await waitFor(() => { - expect(onChange).toBeCalledWith({ - isValid: false, - updatedPolicy: { - ...defaultNewPolicy, - inputs: [ - { - ...defaultNewPolicy.inputs[0], - streams: [ - { - ...defaultNewPolicy.inputs[0].streams[0], - vars: { - ...defaultNewPolicy.inputs[0].streams[0].vars, - [ConfigKey.TLS_CERTIFICATE_AUTHORITIES]: { - value: '"certificateAuthorities"', - type: 'yaml', - }, - [ConfigKey.TLS_CERTIFICATE]: { - value: '"clientCertificate"', - type: 'yaml', - }, - [ConfigKey.TLS_KEY]: { - value: '"clientKey"', - type: 'yaml', - }, - [ConfigKey.TLS_KEY_PASSPHRASE]: { - value: 'clientKeyPassphrase', - type: 'text', - }, - [ConfigKey.TLS_VERIFICATION_MODE]: { - value: VerificationMode.NONE, - type: 'text', - }, - }, - }, - ], - }, - defaultNewPolicy.inputs[1], - defaultNewPolicy.inputs[2], - defaultNewPolicy.inputs[3], - ], - }, - }); - }); - }); -}); diff --git a/x-pack/plugins/synthetics/public/legacy_uptime/components/monitor_management/hooks/use_monitor_list.ts b/x-pack/plugins/synthetics/public/legacy_uptime/components/monitor_management/hooks/use_monitor_list.ts index e0899571f38b8..cf6361bee0e37 100644 --- a/x-pack/plugins/synthetics/public/legacy_uptime/components/monitor_management/hooks/use_monitor_list.ts +++ b/x-pack/plugins/synthetics/public/legacy_uptime/components/monitor_management/hooks/use_monitor_list.ts @@ -27,7 +27,7 @@ export function useMonitorList() { const { pageIndex, pageSize, sortField, sortOrder } = pageState as MonitorManagementListPageState; - const { type: viewType } = useParams<{ type: 'all' | 'invalid' }>(); + const { type: viewType = 'all' } = useParams<{ type: 'all' | 'invalid' }>(); useEffect(() => { if (viewType === 'all') { diff --git a/x-pack/plugins/synthetics/public/legacy_uptime/components/monitor_management/manage_locations/empty_locations.tsx b/x-pack/plugins/synthetics/public/legacy_uptime/components/monitor_management/manage_locations/empty_locations.tsx index d30dcb2d7db42..6f203d1ab8891 100644 --- a/x-pack/plugins/synthetics/public/legacy_uptime/components/monitor_management/manage_locations/empty_locations.tsx +++ b/x-pack/plugins/synthetics/public/legacy_uptime/components/monitor_management/manage_locations/empty_locations.tsx @@ -48,19 +48,22 @@ export const EmptyLocations = ({ } footer={ - {LEARN_MORE}{' '} - - {READ_DOCS} - + {LEARN_MORE} } /> ); }; +export const PrivateLocationDocsLink = ({ label }: { label?: string }) => ( + + {label ?? READ_DOCS} + +); + const FIRST_MONITOR = i18n.translate('xpack.synthetics.monitorManagement.firstLocationMonitor', { defaultMessage: 'In order to create a monitor, you will need to add a location first.', }); diff --git a/x-pack/plugins/synthetics/public/legacy_uptime/components/monitor_management/monitor_list/list_tabs.tsx b/x-pack/plugins/synthetics/public/legacy_uptime/components/monitor_management/monitor_list/list_tabs.tsx index e2da72effa560..82d79ff48231f 100644 --- a/x-pack/plugins/synthetics/public/legacy_uptime/components/monitor_management/monitor_list/list_tabs.tsx +++ b/x-pack/plugins/synthetics/public/legacy_uptime/components/monitor_management/monitor_list/list_tabs.tsx @@ -35,7 +35,7 @@ export const MonitorListTabs = ({ const history = useHistory(); - const { type: viewType } = useParams<{ type: 'all' | 'invalid' }>(); + const { type: viewType = 'all' } = useParams<{ type: 'all' | 'invalid' }>(); useEffect(() => { setSelectedTabId(viewType); @@ -52,7 +52,7 @@ export const MonitorListTabs = ({ id: 'all', name: ALL_MONITORS_LABEL, content: , - href: history.createHref({ pathname: '/manage-monitors/all' }), + href: history.createHref({ pathname: '/manage-monitors' }), disabled: false, }, { diff --git a/x-pack/plugins/synthetics/public/legacy_uptime/components/monitor_management/monitor_list/monitor_list_container.tsx b/x-pack/plugins/synthetics/public/legacy_uptime/components/monitor_management/monitor_list/monitor_list_container.tsx index 272d971d27cc9..fee3cd84ab120 100644 --- a/x-pack/plugins/synthetics/public/legacy_uptime/components/monitor_management/monitor_list/monitor_list_container.tsx +++ b/x-pack/plugins/synthetics/public/legacy_uptime/components/monitor_management/monitor_list/monitor_list_container.tsx @@ -46,7 +46,7 @@ export const MonitorListContainer = ({ const monitorList = useSelector(monitorManagementListSelector); - const { type: viewType } = useParams<{ type: 'all' | 'invalid' }>(); + const { type: viewType = 'all' } = useParams<{ type: 'all' | 'invalid' }>(); const { errorSummaries, loading, count } = useInlineErrors({ onlyInvalidMonitors: viewType === 'invalid', sortField: pageState.sortField, diff --git a/x-pack/plugins/synthetics/public/legacy_uptime/routes.tsx b/x-pack/plugins/synthetics/public/legacy_uptime/routes.tsx index ea60368f92a5a..b0700c8220782 100644 --- a/x-pack/plugins/synthetics/public/legacy_uptime/routes.tsx +++ b/x-pack/plugins/synthetics/public/legacy_uptime/routes.tsx @@ -240,7 +240,7 @@ const getRoutes = (): RouteProps[] => { defaultMessage: 'Monitor Management | {baseTitle}', values: { baseTitle }, }), - path: MONITOR_MANAGEMENT_ROUTE + '/:type', + path: MONITOR_MANAGEMENT_ROUTE + '/:type?', component: () => ( diff --git a/x-pack/test/functional_synthetics/README.md b/x-pack/test/functional_synthetics/README.md deleted file mode 100644 index 35324397ac3fc..0000000000000 --- a/x-pack/test/functional_synthetics/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# Kibana Functional Testing - -See our [Functional Testing Guide](https://www.elastic.co/guide/en/kibana/current/development-tests.html#development-functional-tests) diff --git a/x-pack/test/functional_synthetics/apps/uptime/index.ts b/x-pack/test/functional_synthetics/apps/uptime/index.ts deleted file mode 100644 index 64a9da5c30ea3..0000000000000 --- a/x-pack/test/functional_synthetics/apps/uptime/index.ts +++ /dev/null @@ -1,16 +0,0 @@ -/* - * 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 { FtrProviderContext } from '../../ftr_provider_context'; - -export default ({ loadTestFile, getService }: FtrProviderContext) => { - describe('Uptime app', function () { - describe('with generated data', () => { - loadTestFile(require.resolve('./synthetics_integration')); - }); - }); -}; diff --git a/x-pack/test/functional_synthetics/apps/uptime/synthetics_integration.ts b/x-pack/test/functional_synthetics/apps/uptime/synthetics_integration.ts deleted file mode 100644 index b19d4fcb7668e..0000000000000 --- a/x-pack/test/functional_synthetics/apps/uptime/synthetics_integration.ts +++ /dev/null @@ -1,772 +0,0 @@ -/* - * 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 expect from '@kbn/expect'; -import { FullAgentPolicy } from '@kbn/fleet-plugin/common'; -import { FtrProviderContext } from '../../ftr_provider_context'; -import { skipIfNoDockerRegistry } from '../../helpers'; - -export default function (providerContext: FtrProviderContext) { - const { getPageObjects, getService } = providerContext; - const monitorName = 'Sample Synthetics integration'; - - const uptimePage = getPageObjects(['syntheticsIntegration']); - const testSubjects = getService('testSubjects'); - const uptimeService = getService('uptime'); - - const getSyntheticsPolicy = (agentFullPolicy: FullAgentPolicy) => - agentFullPolicy.inputs.find((input) => input.meta?.package?.name === 'synthetics'); - - const generatePolicy = ({ - agentFullPolicy, - version, - monitorType, - name, - config, - }: { - agentFullPolicy: FullAgentPolicy; - version: string; - monitorType: string; - name: string; - config: Record; - }) => ({ - data_stream: { - namespace: 'default', - }, - id: getSyntheticsPolicy(agentFullPolicy)?.id, - meta: { - package: { - name: 'synthetics', - version, - }, - }, - name, - package_policy_id: getSyntheticsPolicy(agentFullPolicy)?.package_policy_id, - revision: 1, - streams: [ - { - data_stream: { - dataset: monitorType, - elasticsearch: { - privileges: { - indices: ['auto_configure', 'create_doc', 'read'], - }, - }, - type: 'synthetics', - }, - id: `${getSyntheticsPolicy(agentFullPolicy)?.streams?.[0]?.id}`, - name, - type: monitorType, - enabled: true, - processors: [ - { - add_observer_metadata: { - geo: { - name: 'Fleet managed', - }, - }, - }, - { - add_fields: { - fields: { - 'monitor.fleet_managed': true, - }, - target: '', - }, - }, - ], - ...config, - }, - ...(monitorType === 'browser' - ? [ - { - data_stream: { - dataset: 'browser.network', - elasticsearch: { - privileges: { - indices: ['auto_configure', 'create_doc', 'read'], - }, - }, - type: 'synthetics', - }, - id: `${getSyntheticsPolicy(agentFullPolicy)?.streams?.[1]?.id}`, - processors: [ - { - add_observer_metadata: { - geo: { - name: 'Fleet managed', - }, - }, - }, - { - add_fields: { - fields: { - 'monitor.fleet_managed': true, - }, - target: '', - }, - }, - ], - }, - { - data_stream: { - dataset: 'browser.screenshot', - elasticsearch: { - privileges: { - indices: ['auto_configure', 'create_doc', 'read'], - }, - }, - type: 'synthetics', - }, - id: `${getSyntheticsPolicy(agentFullPolicy)?.streams?.[2]?.id}`, - processors: [ - { - add_observer_metadata: { - geo: { - name: 'Fleet managed', - }, - }, - }, - { - add_fields: { - fields: { - 'monitor.fleet_managed': true, - }, - target: '', - }, - }, - ], - }, - ] - : []), - ], - type: `synthetics/${monitorType}`, - use_output: 'default', - }); - - describe('When on the Synthetics Integration Policy Create Page', function () { - skipIfNoDockerRegistry(providerContext); - const basicConfig = { - name: monitorName, - apmServiceName: 'Sample APM Service', - tags: 'sample tag', - }; - - const generateHTTPConfig = (url: string) => ({ - ...basicConfig, - url, - }); - - const generateTCPorICMPConfig = (host: string) => ({ - ...basicConfig, - host, - }); - - const generateBrowserConfig = (config: Record): Record => ({ - ...basicConfig, - ...config, - }); - - describe('displays custom UI', () => { - before(async () => { - const version = await uptimeService.syntheticsPackage.getSyntheticsPackageVersion(); - await uptimePage.syntheticsIntegration.navigateToPackagePage(version!); - }); - - it('should display policy view', async () => { - await uptimePage.syntheticsIntegration.ensureIsOnPackagePage(); - }); - - it('prevent saving when integration name, url/host, or schedule is missing', async () => { - const saveButton = await uptimePage.syntheticsIntegration.findSaveButton(); - await saveButton.click(); - - await testSubjects.missingOrFail('postInstallAddAgentModal'); - }); - }); - - describe('create new policy', () => { - let version: string; - - beforeEach(async () => { - version = (await uptimeService.syntheticsPackage.getSyntheticsPackageVersion())!; - await uptimePage.syntheticsIntegration.navigateToPackagePage(version!); - await uptimeService.syntheticsPackage.deletePolicyByName(monitorName); - }); - - afterEach(async () => { - await uptimeService.syntheticsPackage.deletePolicyByName(monitorName); - }); - - it('allows saving when user enters a valid integration name and url/host', async () => { - // This test ensures that updates made to the Synthetics Policy are carried all the way through - // to the generated Agent Policy that is dispatch down to the Elastic Agent. - const config = generateHTTPConfig('http://elastic.co'); - await uptimePage.syntheticsIntegration.createBasicHTTPMonitorDetails(config); - await uptimePage.syntheticsIntegration.confirmAndSave(); - - await uptimePage.syntheticsIntegration.isPolicyCreatedSuccessfully(); - - const [agentPolicy] = await uptimeService.syntheticsPackage.getAgentPolicyList(); - const agentPolicyId = agentPolicy.id; - const agentFullPolicy = await uptimeService.syntheticsPackage.getFullAgentPolicy( - agentPolicyId - ); - - expect(getSyntheticsPolicy(agentFullPolicy)).to.eql( - generatePolicy({ - agentFullPolicy, - version, - name: monitorName, - monitorType: 'http', - config: { - max_redirects: 0, - 'response.include_body': 'on_error', - 'response.include_headers': true, - schedule: '@every 3m', - timeout: '16s', - urls: config.url, - 'service.name': config.apmServiceName, - tags: [config.tags], - 'check.request.method': 'GET', - __ui: { - is_tls_enabled: false, - is_zip_url_tls_enabled: false, - }, - }, - }) - ); - }); - - it('allows enabling tls with defaults', async () => { - // This test ensures that updates made to the Synthetics Policy are carried all the way through - // to the generated Agent Policy that is dispatch down to the Elastic Agent. - const config = generateHTTPConfig('http://elastic.co'); - - await uptimePage.syntheticsIntegration.createBasicHTTPMonitorDetails(config); - await uptimePage.syntheticsIntegration.enableTLS(); - await uptimePage.syntheticsIntegration.confirmAndSave(); - - await uptimePage.syntheticsIntegration.isPolicyCreatedSuccessfully(); - - const [agentPolicy] = await uptimeService.syntheticsPackage.getAgentPolicyList(); - const agentPolicyId = agentPolicy.id; - const agentFullPolicy = await uptimeService.syntheticsPackage.getFullAgentPolicy( - agentPolicyId - ); - - expect( - agentFullPolicy.inputs.find((input) => input.meta?.package?.name === 'synthetics') - ).to.eql( - generatePolicy({ - agentFullPolicy, - version, - name: monitorName, - monitorType: 'http', - config: { - max_redirects: 0, - 'check.request.method': 'GET', - 'response.include_body': 'on_error', - 'response.include_headers': true, - schedule: '@every 3m', - 'ssl.supported_protocols': ['TLSv1.1', 'TLSv1.2', 'TLSv1.3'], - 'ssl.verification_mode': 'full', - timeout: '16s', - urls: config.url, - 'service.name': config.apmServiceName, - tags: [config.tags], - __ui: { - is_tls_enabled: true, - is_zip_url_tls_enabled: false, - }, - }, - }) - ); - }); - - it('allows configuring tls', async () => { - // This test ensures that updates made to the Synthetics Policy are carried all the way through - // to the generated Agent Policy that is dispatch down to the Elastic Agent. - const config = generateHTTPConfig('http://elastic.co'); - - const tlsConfig = { - verificationMode: 'strict', - ca: 'ca', - cert: 'cert', - certKey: 'certKey', - certKeyPassphrase: 'certKeyPassphrase', - }; - await uptimePage.syntheticsIntegration.createBasicHTTPMonitorDetails(config); - await uptimePage.syntheticsIntegration.configureTLSOptions(tlsConfig); - await uptimePage.syntheticsIntegration.confirmAndSave(); - - await uptimePage.syntheticsIntegration.isPolicyCreatedSuccessfully(); - - const [agentPolicy] = await uptimeService.syntheticsPackage.getAgentPolicyList(); - const agentPolicyId = agentPolicy.id; - const agentFullPolicy = await uptimeService.syntheticsPackage.getFullAgentPolicy( - agentPolicyId - ); - - expect(getSyntheticsPolicy(agentFullPolicy)).to.eql( - generatePolicy({ - agentFullPolicy, - version, - name: monitorName, - monitorType: 'http', - config: { - max_redirects: 0, - 'check.request.method': 'GET', - 'response.include_body': 'on_error', - 'response.include_headers': true, - schedule: '@every 3m', - 'ssl.supported_protocols': ['TLSv1.1', 'TLSv1.2', 'TLSv1.3'], - 'ssl.verification_mode': tlsConfig.verificationMode, - 'ssl.certificate': tlsConfig.cert, - 'ssl.certificate_authorities': tlsConfig.ca, - 'ssl.key': tlsConfig.certKey, - 'ssl.key_passphrase': tlsConfig.certKeyPassphrase, - timeout: '16s', - urls: config.url, - 'service.name': config.apmServiceName, - tags: [config.tags], - __ui: { - is_tls_enabled: true, - is_zip_url_tls_enabled: false, - }, - }, - }) - ); - }); - - it('allows configuring http advanced options', async () => { - // This test ensures that updates made to the Synthetics Policy are carried all the way through - // to the generated Agent Policy that is dispatch down to the Elastic Agent. - const config = generateHTTPConfig('http://elastic.co'); - - await uptimePage.syntheticsIntegration.createBasicHTTPMonitorDetails(config); - const advancedConfig = { - username: 'username', - password: 'password', - proxyUrl: 'proxyUrl', - requestMethod: 'POST', - responseStatusCheck: '204', - responseBodyCheckPositive: 'success', - responseBodyCheckNegative: 'failure', - requestHeaders: { - sampleRequestHeader1: 'sampleRequestKey1', - sampleRequestHeader2: 'sampleRequestKey2', - }, - responseHeaders: { - sampleResponseHeader1: 'sampleResponseKey1', - sampleResponseHeader2: 'sampleResponseKey2', - }, - requestBody: { - type: 'xml', - value: 'samplexml', - }, - indexResponseBody: false, - indexResponseHeaders: false, - }; - await uptimePage.syntheticsIntegration.configureHTTPAdvancedOptions(advancedConfig); - await uptimePage.syntheticsIntegration.confirmAndSave(); - - await uptimePage.syntheticsIntegration.isPolicyCreatedSuccessfully(); - - const [agentPolicy] = await uptimeService.syntheticsPackage.getAgentPolicyList(); - const agentPolicyId = agentPolicy.id; - const agentFullPolicy = await uptimeService.syntheticsPackage.getFullAgentPolicy( - agentPolicyId - ); - - expect(getSyntheticsPolicy(agentFullPolicy)).to.eql( - generatePolicy({ - agentFullPolicy, - version, - name: monitorName, - monitorType: 'http', - config: { - max_redirects: 0, - 'check.request.method': advancedConfig.requestMethod, - 'check.request.headers': { - 'Content-Type': 'application/xml', - ...advancedConfig.requestHeaders, - }, - 'check.response.headers': advancedConfig.responseHeaders, - 'check.response.status': [advancedConfig.responseStatusCheck], - 'check.request.body': advancedConfig.requestBody.value, - 'check.response.body.positive': [advancedConfig.responseBodyCheckPositive], - 'check.response.body.negative': [advancedConfig.responseBodyCheckNegative], - 'response.include_body': advancedConfig.indexResponseBody ? 'on_error' : 'never', - 'response.include_headers': advancedConfig.indexResponseHeaders, - schedule: '@every 3m', - timeout: '16s', - urls: config.url, - proxy_url: advancedConfig.proxyUrl, - username: advancedConfig.username, - password: advancedConfig.password, - 'service.name': config.apmServiceName, - tags: [config.tags], - __ui: { - is_tls_enabled: false, - is_zip_url_tls_enabled: false, - }, - }, - }) - ); - }); - - it('allows saving tcp monitor when user enters a valid integration name and host+port', async () => { - // This test ensures that updates made to the Synthetics Policy are carried all the way through - // to the generated Agent Policy that is dispatch down to the Elastic Agent. - const config = generateTCPorICMPConfig('smtp.gmail.com:587'); - - await uptimePage.syntheticsIntegration.createBasicTCPMonitorDetails(config); - await uptimePage.syntheticsIntegration.confirmAndSave(); - - await uptimePage.syntheticsIntegration.isPolicyCreatedSuccessfully(); - - const [agentPolicy] = await uptimeService.syntheticsPackage.getAgentPolicyList(); - const agentPolicyId = agentPolicy.id; - const agentFullPolicy = await uptimeService.syntheticsPackage.getFullAgentPolicy( - agentPolicyId - ); - - expect(getSyntheticsPolicy(agentFullPolicy)).to.eql( - generatePolicy({ - agentFullPolicy, - version, - name: monitorName, - monitorType: 'tcp', - config: { - proxy_use_local_resolver: false, - schedule: '@every 3m', - timeout: '16s', - hosts: config.host, - tags: [config.tags], - 'service.name': config.apmServiceName, - __ui: { - is_tls_enabled: false, - is_zip_url_tls_enabled: false, - }, - }, - }) - ); - }); - - it('allows configuring tcp advanced options', async () => { - // This test ensures that updates made to the Synthetics Policy are carried all the way through - // to the generated Agent Policy that is dispatch down to the Elastic Agent. - const config = generateTCPorICMPConfig('smtp.gmail.com:587'); - - await uptimePage.syntheticsIntegration.createBasicTCPMonitorDetails(config); - const advancedConfig = { - proxyUrl: 'proxyUrl', - requestSendCheck: 'body', - responseReceiveCheck: 'success', - proxyUseLocalResolver: true, - }; - await uptimePage.syntheticsIntegration.configureTCPAdvancedOptions(advancedConfig); - await uptimePage.syntheticsIntegration.confirmAndSave(); - - await uptimePage.syntheticsIntegration.isPolicyCreatedSuccessfully(); - - const [agentPolicy] = await uptimeService.syntheticsPackage.getAgentPolicyList(); - const agentPolicyId = agentPolicy.id; - const agentFullPolicy = await uptimeService.syntheticsPackage.getFullAgentPolicy( - agentPolicyId - ); - - expect(getSyntheticsPolicy(agentFullPolicy)).to.eql( - generatePolicy({ - agentFullPolicy, - version, - name: monitorName, - monitorType: 'tcp', - config: { - schedule: '@every 3m', - timeout: '16s', - hosts: config.host, - proxy_url: advancedConfig.proxyUrl, - proxy_use_local_resolver: advancedConfig.proxyUseLocalResolver, - 'check.receive': advancedConfig.responseReceiveCheck, - 'check.send': advancedConfig.requestSendCheck, - 'service.name': config.apmServiceName, - tags: [config.tags], - __ui: { - is_tls_enabled: false, - is_zip_url_tls_enabled: false, - }, - }, - }) - ); - }); - - it('allows saving icmp monitor when user enters a valid integration name and host', async () => { - // This test ensures that updates made to the Synthetics Policy are carried all the way through - // to the generated Agent Policy that is dispatch down to the Elastic Agent. - const config = generateTCPorICMPConfig('1.1.1.1'); - - await uptimePage.syntheticsIntegration.createBasicICMPMonitorDetails(config); - await uptimePage.syntheticsIntegration.confirmAndSave(); - - await uptimePage.syntheticsIntegration.isPolicyCreatedSuccessfully(); - - const [agentPolicy] = await uptimeService.syntheticsPackage.getAgentPolicyList(); - const agentPolicyId = agentPolicy.id; - const agentFullPolicy = await uptimeService.syntheticsPackage.getFullAgentPolicy( - agentPolicyId - ); - - expect(getSyntheticsPolicy(agentFullPolicy)).to.eql( - generatePolicy({ - agentFullPolicy, - version, - name: monitorName, - monitorType: 'icmp', - config: { - schedule: '@every 3m', - timeout: '16s', - wait: '1s', - hosts: config.host, - 'service.name': config.apmServiceName, - tags: [config.tags], - __ui: null, - }, - }) - ); - }); - - it('allows saving browser monitor', async () => { - // This test ensures that updates made to the Synthetics Policy are carried all the way through - // to the generated Agent Policy that is dispatch down to the Elastic Agent. - const config = generateBrowserConfig({ - zipUrl: 'http://test.zip', - params: JSON.stringify({ url: 'http://localhost:8080' }), - folder: 'folder', - username: 'username', - password: 'password', - }); - - await uptimePage.syntheticsIntegration.createBasicBrowserMonitorDetails(config); - await uptimePage.syntheticsIntegration.confirmAndSave(); - - await uptimePage.syntheticsIntegration.isPolicyCreatedSuccessfully(); - - const [agentPolicy] = await uptimeService.syntheticsPackage.getAgentPolicyList(); - const agentPolicyId = agentPolicy.id; - const agentFullPolicy = await uptimeService.syntheticsPackage.getFullAgentPolicy( - agentPolicyId - ); - - expect(getSyntheticsPolicy(agentFullPolicy)).to.eql( - generatePolicy({ - agentFullPolicy, - version, - name: monitorName, - monitorType: 'browser', - config: { - screenshots: 'on', - schedule: '@every 10m', - timeout: null, - tags: [config.tags], - throttling: '5d/3u/20l', - 'service.name': config.apmServiceName, - 'source.zip_url.url': config.zipUrl, - 'source.zip_url.folder': config.folder, - 'source.zip_url.username': config.username, - 'source.zip_url.password': config.password, - params: JSON.parse(config.params), - __ui: { - is_tls_enabled: false, - is_zip_url_tls_enabled: false, - script_source: { - file_name: '', - is_generated_script: false, - }, - }, - }, - }) - ); - }); - - it('allows saving browser monitor with inline script', async () => { - // This test ensures that updates made to the Synthetics Policy are carried all the way through - // to the generated Agent Policy that is dispatch down to the Elastic Agent. - const config = generateBrowserConfig({ - inlineScript: - 'step("load homepage", async () => { await page.goto(\'https://www.elastic.co\'); });', - }); - - await uptimePage.syntheticsIntegration.createBasicBrowserMonitorDetails(config, true); - await uptimePage.syntheticsIntegration.confirmAndSave(); - - await uptimePage.syntheticsIntegration.isPolicyCreatedSuccessfully(); - - const [agentPolicy] = await uptimeService.syntheticsPackage.getAgentPolicyList(); - const agentPolicyId = agentPolicy.id; - const agentFullPolicy = await uptimeService.syntheticsPackage.getFullAgentPolicy( - agentPolicyId - ); - - expect(getSyntheticsPolicy(agentFullPolicy)).to.eql( - generatePolicy({ - agentFullPolicy, - version, - name: monitorName, - monitorType: 'browser', - config: { - screenshots: 'on', - schedule: '@every 10m', - timeout: null, - tags: [config.tags], - throttling: '5d/3u/20l', - 'service.name': config.apmServiceName, - 'source.inline.script': config.inlineScript, - __ui: { - is_tls_enabled: false, - is_zip_url_tls_enabled: false, - script_source: { - file_name: '', - is_generated_script: false, - }, - }, - }, - }) - ); - }); - - it('allows saving browser monitor advanced options', async () => { - // This test ensures that updates made to the Synthetics Policy are carried all the way through - // to the generated Agent Policy that is dispatch down to the Elastic Agent. - const config = generateBrowserConfig({ - zipUrl: 'http://test.zip', - params: JSON.stringify({ url: 'http://localhost:8080' }), - folder: 'folder', - username: 'username', - password: 'password', - }); - - const advancedConfig = { - screenshots: 'off', - syntheticsArgs: '-ssBlocks', - isThrottlingEnabled: true, - downloadSpeed: '1337', - uploadSpeed: '1338', - latency: '1339', - }; - - await uptimePage.syntheticsIntegration.createBasicBrowserMonitorDetails(config); - await uptimePage.syntheticsIntegration.configureBrowserAdvancedOptions(advancedConfig); - await uptimePage.syntheticsIntegration.confirmAndSave(); - - await uptimePage.syntheticsIntegration.isPolicyCreatedSuccessfully(); - - const [agentPolicy] = await uptimeService.syntheticsPackage.getAgentPolicyList(); - const agentPolicyId = agentPolicy.id; - const agentFullPolicy = await uptimeService.syntheticsPackage.getFullAgentPolicy( - agentPolicyId - ); - - expect(getSyntheticsPolicy(agentFullPolicy)).to.eql( - generatePolicy({ - agentFullPolicy, - version, - name: monitorName, - monitorType: 'browser', - config: { - screenshots: advancedConfig.screenshots, - schedule: '@every 10m', - timeout: null, - tags: [config.tags], - throttling: '1337d/1338u/1339l', - 'service.name': config.apmServiceName, - 'source.zip_url.url': config.zipUrl, - 'source.zip_url.folder': config.folder, - 'source.zip_url.username': config.username, - 'source.zip_url.password': config.password, - params: JSON.parse(config.params), - synthetics_args: [advancedConfig.syntheticsArgs], - __ui: { - is_tls_enabled: false, - is_zip_url_tls_enabled: false, - script_source: { - file_name: '', - is_generated_script: false, - }, - }, - }, - }) - ); - }); - - it('allows saving disabling throttling', async () => { - // This test ensures that updates made to the Synthetics Policy are carried all the way through - // to the generated Agent Policy that is dispatch down to the Elastic Agent. - const config = generateBrowserConfig({ - zipUrl: 'http://test.zip', - params: JSON.stringify({ url: 'http://localhost:8080' }), - folder: 'folder', - username: 'username', - password: 'password', - }); - - const advancedConfig = { - screenshots: 'off', - syntheticsArgs: '-ssBlocks', - isThrottlingEnabled: false, - downloadSpeed: '1337', - uploadSpeed: '1338', - latency: '1339', - }; - - await uptimePage.syntheticsIntegration.createBasicBrowserMonitorDetails(config); - await uptimePage.syntheticsIntegration.configureBrowserAdvancedOptions(advancedConfig); - await uptimePage.syntheticsIntegration.confirmAndSave(); - - await uptimePage.syntheticsIntegration.isPolicyCreatedSuccessfully(); - - const [agentPolicy] = await uptimeService.syntheticsPackage.getAgentPolicyList(); - const agentPolicyId = agentPolicy.id; - const agentFullPolicy = await uptimeService.syntheticsPackage.getFullAgentPolicy( - agentPolicyId - ); - - expect(getSyntheticsPolicy(agentFullPolicy)).to.eql( - generatePolicy({ - agentFullPolicy, - version, - name: monitorName, - monitorType: 'browser', - config: { - screenshots: advancedConfig.screenshots, - schedule: '@every 10m', - timeout: null, - tags: [config.tags], - 'service.name': config.apmServiceName, - 'source.zip_url.url': config.zipUrl, - 'source.zip_url.folder': config.folder, - 'source.zip_url.username': config.username, - 'source.zip_url.password': config.password, - params: JSON.parse(config.params), - synthetics_args: [advancedConfig.syntheticsArgs], - throttling: false, - __ui: { - is_tls_enabled: false, - is_zip_url_tls_enabled: false, - script_source: { - file_name: '', - is_generated_script: false, - }, - }, - }, - }) - ); - }); - }); - }); -} diff --git a/x-pack/test/functional_synthetics/config.js b/x-pack/test/functional_synthetics/config.js deleted file mode 100644 index d563911a9bebc..0000000000000 --- a/x-pack/test/functional_synthetics/config.js +++ /dev/null @@ -1,104 +0,0 @@ -/* - * 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 path, { resolve } from 'path'; - -import { defineDockerServersConfig } from '@kbn/test'; -import { dockerImage as fleetDockerImage } from '../fleet_api_integration/config'; - -import { services } from './services'; -import { pageObjects } from './page_objects'; - -// the default export of config files must be a config provider -// that returns an object with the projects config values -export default async function ({ readConfigFile }) { - const registryPort = process.env.FLEET_PACKAGE_REGISTRY_PORT; - - const kibanaCommonConfig = await readConfigFile( - require.resolve('../../../test/common/config.js') - ); - const kibanaFunctionalConfig = await readConfigFile( - require.resolve('../../../test/functional/config.base.js') - ); - - // mount the config file for the package registry as well as - // the directory containing additional packages into the container - const dockerArgs = [ - '-v', - `${path.join( - path.dirname(__filename), - './fixtures/package_registry_config.yml' - )}:/package-registry/config.yml`, - ]; - - return { - // list paths to the files that contain your plugins tests - testFiles: [resolve(__dirname, './apps/uptime')], - - services, - pageObjects, - - servers: kibanaFunctionalConfig.get('servers'), - - esTestCluster: { - license: 'trial', - from: 'snapshot', - serverArgs: ['path.repo=/tmp/', 'xpack.security.authc.api_key.enabled=true'], - }, - - kbnTestServer: { - ...kibanaCommonConfig.get('kbnTestServer'), - serverArgs: [ - ...kibanaCommonConfig.get('kbnTestServer.serverArgs'), - '--status.allowAnonymous=true', - '--server.uuid=5b2de169-2785-441b-ae8c-186a1936b17d', - '--xpack.maps.showMapsInspectorAdapter=true', - '--xpack.maps.preserveDrawingBuffer=true', - '--xpack.security.encryptionKey="wuGNaIhoMpk5sO4UBxgr3NyW1sFcLgIf"', // server restarts should not invalidate active sessions - '--xpack.encryptedSavedObjects.encryptionKey="DkdXazszSCYexXqz4YktBGHCRkV6hyNK"', - '--xpack.discoverEnhanced.actions.exploreDataInContextMenu.enabled=true', - '--savedObjects.maxImportPayloadBytes=10485760', // for OSS test management/_import_objects, - ...(registryPort ? [`--xpack.fleet.registryUrl=http://localhost:${registryPort}`] : []), - ], - }, - uiSettings: { - defaults: { - 'accessibility:disableAnimations': true, - 'dateFormat:tz': 'UTC', - }, - }, - // the apps section defines the urls that - // `PageObjects.common.navigateTo(appKey)` will use. - // Merge urls for your plugin with the urls defined in - // Kibana's config in order to use this helper - apps: { - ...kibanaFunctionalConfig.get('apps'), - fleet: { - pathname: '/app/fleet', - }, - }, - - // choose where screenshots should be saved - screenshots: { - directory: resolve(__dirname, 'screenshots'), - }, - - junit: { - reportName: 'Chrome Elastic Synthetics Integration UI Functional Tests', - }, - dockerServers: defineDockerServersConfig({ - registry: { - enabled: !!registryPort, - image: fleetDockerImage, - portInContainer: 8080, - port: registryPort, - args: dockerArgs, - waitForLogLine: 'package manifests loaded', - }, - }), - }; -} diff --git a/x-pack/test/functional_synthetics/fixtures/package_registry_config.yml b/x-pack/test/functional_synthetics/fixtures/package_registry_config.yml deleted file mode 100644 index a6c51976af986..0000000000000 --- a/x-pack/test/functional_synthetics/fixtures/package_registry_config.yml +++ /dev/null @@ -1,2 +0,0 @@ -package_paths: - - /packages/package-storage \ No newline at end of file diff --git a/x-pack/test/functional_synthetics/ftr_provider_context.ts b/x-pack/test/functional_synthetics/ftr_provider_context.ts deleted file mode 100644 index e757164fa1de9..0000000000000 --- a/x-pack/test/functional_synthetics/ftr_provider_context.ts +++ /dev/null @@ -1,14 +0,0 @@ -/* - * 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 { GenericFtrProviderContext, GenericFtrService } from '@kbn/test'; - -import { pageObjects } from './page_objects'; -import { services } from './services'; - -export type FtrProviderContext = GenericFtrProviderContext; -export class FtrService extends GenericFtrService {} diff --git a/x-pack/test/functional_synthetics/helpers.ts b/x-pack/test/functional_synthetics/helpers.ts deleted file mode 100644 index 8635609cf35d9..0000000000000 --- a/x-pack/test/functional_synthetics/helpers.ts +++ /dev/null @@ -1,31 +0,0 @@ -/* - * 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 { Context } from 'mocha'; -import { ToolingLog } from '@kbn/tooling-log'; -import { FtrProviderContext } from './ftr_provider_context'; - -export function warnAndSkipTest(mochaContext: Context, log: ToolingLog) { - log.warning( - 'disabling tests because DockerServers service is not enabled, set FLEET_PACKAGE_REGISTRY_PORT to run them' - ); - mochaContext.skip(); -} - -export function skipIfNoDockerRegistry(providerContext: FtrProviderContext) { - const { getService } = providerContext; - const dockerServers = getService('dockerServers'); - - const server = dockerServers.get('registry'); - const log = getService('log'); - - beforeEach(function beforeSetupWithDockerRegistry() { - if (!server.enabled) { - warnAndSkipTest(this, log); - } - }); -} diff --git a/x-pack/test/functional_synthetics/page_objects/index.ts b/x-pack/test/functional_synthetics/page_objects/index.ts deleted file mode 100644 index 253157297713b..0000000000000 --- a/x-pack/test/functional_synthetics/page_objects/index.ts +++ /dev/null @@ -1,17 +0,0 @@ -/* - * 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 { pageObjects as kibanaFunctionalPageObjects } from '../../../../test/functional/page_objects'; - -import { SyntheticsIntegrationPageProvider } from './synthetics_integration_page'; - -// just like services, PageObjects are defined as a map of -// names to Providers. Merge in Kibana's or pick specific ones -export const pageObjects = { - ...kibanaFunctionalPageObjects, - syntheticsIntegration: SyntheticsIntegrationPageProvider, -}; diff --git a/x-pack/test/functional_synthetics/page_objects/synthetics_integration_page.ts b/x-pack/test/functional_synthetics/page_objects/synthetics_integration_page.ts deleted file mode 100644 index 8650a2b352e78..0000000000000 --- a/x-pack/test/functional_synthetics/page_objects/synthetics_integration_page.ts +++ /dev/null @@ -1,483 +0,0 @@ -/* - * 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 { WebElementWrapper } from '../../../../test/functional/services/lib/web_element_wrapper'; -import { FtrProviderContext } from '../ftr_provider_context'; - -export function SyntheticsIntegrationPageProvider({ - getService, - getPageObjects, -}: FtrProviderContext) { - const pageObjects = getPageObjects(['common', 'header']); - const testSubjects = getService('testSubjects'); - const comboBox = getService('comboBox'); - - const fixedFooterHeight = 72; // Size of EuiBottomBar more or less - - return { - /** - * Navigates to the Synthetics Integration page - * - */ - async navigateToPackagePage(packageVersion: string) { - await pageObjects.common.navigateToUrlWithBrowserHistory( - 'fleet', - `/integrations/synthetics-${packageVersion}/add-integration` - ); - await pageObjects.header.waitUntilLoadingHasFinished(); - }, - - async navigateToPackageEditPage(packageId: string, agentId: string) { - await pageObjects.common.navigateToUrlWithBrowserHistory( - 'fleet', - `/policies/${agentId}/edit-integration/${packageId}` - ); - await pageObjects.header.waitUntilLoadingHasFinished(); - }, - - /** - * Finds and returns the Policy Details Page Save button - */ - async findSaveButton(isEditPage?: boolean) { - await this.ensureIsOnPackagePage(); - return await testSubjects.find( - isEditPage ? 'saveIntegration' : 'createPackagePolicySaveButton' - ); - }, - - /** - * Finds and returns the Policy Details Page Cancel Button - */ - async findCancelButton() { - await this.ensureIsOnPackagePage(); - return await testSubjects.find('policyDetailsCancelButton'); - }, - - /** - * Determines if the policy was created successfully by looking for the creation success toast - */ - async isPolicyCreatedSuccessfully() { - await testSubjects.existOrFail('postInstallAddAgentModal'); - }, - - /** - * Selects the monitor type - * @params {monitorType} the type of monitor, tcp, http, or icmp - */ - async selectMonitorType(monitorType: string) { - await testSubjects.selectValue('syntheticsMonitorTypeField', monitorType); - }, - - /** - * Fills a text input - * @params {testSubj} the testSubj of the input to fill - * @params {value} the value of the input - */ - async fillTextInputByTestSubj(testSubj: string, value: string) { - const field = await testSubjects.find(testSubj); - await field.scrollIntoViewIfNecessary({ bottomOffset: fixedFooterHeight }); - await field.click(); - await field.clearValue(); - await field.type(value); - }, - - /** - * Fills a text input - * @params {testSubj} the testSubj of the input to fill - * @params {value} the value of the input - */ - async fillTextInput(field: WebElementWrapper, value: string) { - await field.scrollIntoViewIfNecessary({ bottomOffset: fixedFooterHeight }); - await field.click(); - await field.clearValue(); - await field.type(value); - }, - - /** - * Fills a text input - * @params {testSubj} the testSubj of the comboBox - */ - async setComboBox(testSubj: string, value: string) { - await comboBox.setCustom(`${testSubj} > comboBoxInput`, value); - }, - - /** - * Finds and returns the HTTP advanced options accordion trigger - */ - async findHTTPAdvancedOptionsAccordion() { - await this.ensureIsOnPackagePage(); - const accordion = await testSubjects.find('syntheticsHTTPAdvancedFieldsAccordion'); - return accordion; - }, - - /** - * Finds and returns the enable throttling checkbox - */ - async findThrottleSwitch() { - await this.ensureIsOnPackagePage(); - return await testSubjects.find('syntheticsBrowserIsThrottlingEnabled'); - }, - - /** - * Finds and returns the enable TLS checkbox - */ - async findEnableTLSSwitch() { - await this.ensureIsOnPackagePage(); - return await testSubjects.find('syntheticsIsTLSEnabled'); - }, - - /** - * ensures that the package page is the currently display view - */ - async ensureIsOnPackagePage() { - await testSubjects.existOrFail('monitorSettingsSection'); - }, - - /** - * Clicks save button and confirms update on the Policy Details page - */ - async confirmAndSave(isEditPage?: boolean) { - await this.ensureIsOnPackagePage(); - const saveButton = await this.findSaveButton(isEditPage); - await saveButton.click(); - await this.maybeForceInstall(); - }, - - /** - * If the force install modal opens, click force install - */ - async maybeForceInstall() { - const confirmForceInstallModalOpen = await testSubjects.exists('confirmForceInstallModal'); - - if (confirmForceInstallModalOpen) { - const forceInstallBtn = await testSubjects.find('confirmModalConfirmButton'); - return forceInstallBtn.click(); - } - }, - - /** - * Fills in the username and password field - * @params username {string} the value of the username - * @params password {string} the value of the password - */ - async configureUsernameAndPassword({ username, password }: Record) { - await this.fillTextInputByTestSubj('syntheticsUsername', username); - await this.fillTextInputByTestSubj('syntheticsPassword', password); - }, - - /** - * - * Configures request headers - * @params headers {string} an object containing desired headers - * - */ - async configureRequestHeaders(headers: Record) { - await this.configureHeaders('syntheticsRequestHeaders', headers); - }, - - /** - * - * Configures response headers - * @params headers {string} an object containing desired headers - * - */ - async configureResponseHeaders(headers: Record) { - await this.configureHeaders('syntheticsResponseHeaders', headers); - }, - - /** - * - * Configures headers - * @params testSubj {string} test subj - * @params headers {string} an object containing desired headers - * - */ - async configureHeaders(testSubj: string, headers: Record) { - const headersContainer = await testSubjects.find(testSubj); - const addHeaderButton = await testSubjects.find(`${testSubj}__button`); - const keys = Object.keys(headers); - - await Promise.all( - keys.map(async (key, index) => { - await addHeaderButton.click(); - const keyField = await headersContainer.findByCssSelector( - `[data-test-subj="keyValuePairsKey${index}"]` - ); - const valueField = await headersContainer.findByCssSelector( - `[data-test-subj="keyValuePairsValue${index}"]` - ); - await this.fillTextInput(keyField, key); - await this.fillTextInput(valueField, headers[key]); - }) - ); - }, - - /** - * - * Configures request body - * @params contentType {string} contentType of the request body - * @params value {string} value of the request body - * - */ - async configureRequestBody(testSubj: string, value: string) { - await testSubjects.click(`syntheticsRequestBodyTab__${testSubj}`); - await this.fillCodeEditor(value); - }, - - /** - * - * Fills the monaco code editor - * @params value {string} value of code input - * - */ - async fillCodeEditor(value: string) { - const codeEditorContainer = await testSubjects.find('codeEditorContainer'); - const textArea = await codeEditorContainer.findByCssSelector('textarea'); - await textArea.clearValue(); - await textArea.type(value); - }, - - /** - * Creates basic common monitor details - * @params name {string} the name of the monitor - * @params url {string} the url of the monitor - * - */ - async createBasicMonitorDetails({ name, apmServiceName, tags }: Record) { - await this.fillTextInputByTestSubj('packagePolicyNameInput', name); - await this.fillTextInputByTestSubj('syntheticsAPMServiceName', apmServiceName); - await this.setComboBox('syntheticsTags', tags); - }, - - /** - * Fills in the fields to create a basic HTTP monitor - * @params name {string} the name of the monitor - * @params url {string} the url of the monitor - * - */ - async createBasicHTTPMonitorDetails({ - name, - url, - apmServiceName, - tags, - }: Record) { - await this.createBasicMonitorDetails({ name, apmServiceName, tags }); - await this.fillTextInputByTestSubj('syntheticsUrlField', url); - }, - - /** - * Fills in the fields to create a basic TCP monitor - * @params name {string} the name of the monitor - * @params host {string} the host (and port) of the monitor - * - */ - async createBasicTCPMonitorDetails({ - name, - host, - apmServiceName, - tags, - }: Record) { - await this.selectMonitorType('tcp'); - await this.createBasicMonitorDetails({ name, apmServiceName, tags }); - await this.fillTextInputByTestSubj('syntheticsTCPHostField', host); - }, - - /** - * Creates a basic ICMP monitor - * @params name {string} the name of the monitor - * @params host {string} the host of the monitor - */ - async createBasicICMPMonitorDetails({ - name, - host, - apmServiceName, - tags, - }: Record) { - await this.selectMonitorType('icmp'); - await this.fillTextInputByTestSubj('packagePolicyNameInput', name); - await this.createBasicMonitorDetails({ name, apmServiceName, tags }); - await this.fillTextInputByTestSubj('syntheticsICMPHostField', host); - }, - - /** - * Creates a basic browser monitor - * @params name {string} the name of the monitor - * @params zipUrl {string} the zip url of the synthetics suites - */ - async createBasicBrowserMonitorDetails( - { - name, - inlineScript, - zipUrl, - folder, - params, - username, - password, - apmServiceName, - tags, - }: Record, - isInline: boolean = false - ) { - await this.selectMonitorType('browser'); - await this.fillTextInputByTestSubj('packagePolicyNameInput', name); - await this.createBasicMonitorDetails({ name, apmServiceName, tags }); - if (isInline) { - await testSubjects.click('syntheticsSourceTab__inline'); - await this.fillCodeEditor(inlineScript); - return; - } else { - await testSubjects.click('syntheticsSourceTab__zipUrl'); - } - await this.fillTextInputByTestSubj('syntheticsBrowserZipUrl', zipUrl); - await this.fillTextInputByTestSubj('syntheticsBrowserZipUrlFolder', folder); - await this.fillTextInputByTestSubj('syntheticsBrowserZipUrlUsername', username); - await this.fillTextInputByTestSubj('syntheticsBrowserZipUrlPassword', password); - await this.fillCodeEditor(params); - }, - - /** - * Enables TLS - */ - async enableTLS() { - const tlsSwitch = await this.findEnableTLSSwitch(); - await tlsSwitch.click(); - }, - - /** - * Configures TLS settings - * @params verificationMode {string} the name of the monitor - */ - async configureTLSOptions({ - verificationMode, - ca, - cert, - certKey, - certKeyPassphrase, - }: Record) { - await this.enableTLS(); - await testSubjects.selectValue('syntheticsTLSVerificationMode', verificationMode); - await this.fillTextInputByTestSubj('syntheticsTLSCA', ca); - await this.fillTextInputByTestSubj('syntheticsTLSCert', cert); - await this.fillTextInputByTestSubj('syntheticsTLSCertKey', certKey); - await this.fillTextInputByTestSubj('syntheticsTLSCertKeyPassphrase', certKeyPassphrase); - }, - - /** - * Configure http advanced settings - */ - async configureHTTPAdvancedOptions({ - username, - password, - proxyUrl, - requestMethod, - requestHeaders, - responseStatusCheck, - responseBodyCheckPositive, - responseBodyCheckNegative, - requestBody, - responseHeaders, - indexResponseBody, - indexResponseHeaders, - }: { - username: string; - password: string; - proxyUrl: string; - requestMethod: string; - responseStatusCheck: string; - responseBodyCheckPositive: string; - responseBodyCheckNegative: string; - requestBody: { value: string; type: string }; - requestHeaders: Record; - responseHeaders: Record; - indexResponseBody: boolean; - indexResponseHeaders: boolean; - }) { - await testSubjects.click('syntheticsHTTPAdvancedFieldsAccordion'); - await this.configureResponseHeaders(responseHeaders); - await this.configureRequestHeaders(requestHeaders); - await this.configureRequestBody(requestBody.type, requestBody.value); - await this.configureUsernameAndPassword({ username, password }); - await this.setComboBox('syntheticsResponseStatusCheck', responseStatusCheck); - await this.setComboBox('syntheticsResponseBodyCheckPositive', responseBodyCheckPositive); - await this.setComboBox('syntheticsResponseBodyCheckNegative', responseBodyCheckNegative); - await this.fillTextInputByTestSubj('syntheticsProxyUrl', proxyUrl); - await testSubjects.selectValue('syntheticsRequestMethod', requestMethod); - if (!indexResponseBody) { - const field = await testSubjects.find('syntheticsIndexResponseBody'); - const label = await field.findByCssSelector('label'); - await label.click(); - } - if (!indexResponseHeaders) { - const field = await testSubjects.find('syntheticsIndexResponseHeaders'); - const label = await field.findByCssSelector('label'); - await label.click(); - } - }, - - /** - * Configure tcp advanced settings - */ - async configureTCPAdvancedOptions({ - proxyUrl, - requestSendCheck, - responseReceiveCheck, - proxyUseLocalResolver, - }: { - proxyUrl: string; - requestSendCheck: string; - responseReceiveCheck: string; - proxyUseLocalResolver: boolean; - }) { - await testSubjects.click('syntheticsTCPAdvancedFieldsAccordion'); - await this.fillTextInputByTestSubj('syntheticsProxyUrl', proxyUrl); - await this.fillTextInputByTestSubj('syntheticsTCPRequestSendCheck', requestSendCheck); - await this.fillTextInputByTestSubj('syntheticsTCPResponseReceiveCheck', responseReceiveCheck); - if (proxyUseLocalResolver) { - const field = await testSubjects.find('syntheticsUseLocalResolver'); - const label = await field.findByCssSelector('label'); - await label.click(); - } - }, - - /** - * Configure browser advanced settings - * @params name {string} the name of the monitor - * @params zipUrl {string} the zip url of the synthetics suites - */ - async configureBrowserAdvancedOptions({ - screenshots, - syntheticsArgs, - isThrottlingEnabled, - downloadSpeed, - uploadSpeed, - latency, - }: { - screenshots: string; - syntheticsArgs: string; - isThrottlingEnabled: boolean; - downloadSpeed: string; - uploadSpeed: string; - latency: string; - }) { - await testSubjects.click('syntheticsBrowserAdvancedFieldsAccordion'); - - const throttleSwitch = await this.findThrottleSwitch(); - if (!isThrottlingEnabled) { - await throttleSwitch.click(); - } - - await testSubjects.selectValue('syntheticsBrowserScreenshots', screenshots); - await this.setComboBox('syntheticsBrowserSyntheticsArgs', syntheticsArgs); - - if (isThrottlingEnabled) { - await this.fillTextInputByTestSubj('syntheticsBrowserDownloadSpeed', downloadSpeed); - await this.fillTextInputByTestSubj('syntheticsBrowserUploadSpeed', uploadSpeed); - await this.fillTextInputByTestSubj('syntheticsBrowserLatency', latency); - } - }, - }; -} diff --git a/x-pack/test/functional_synthetics/services/index.ts b/x-pack/test/functional_synthetics/services/index.ts deleted file mode 100644 index b8340acccb512..0000000000000 --- a/x-pack/test/functional_synthetics/services/index.ts +++ /dev/null @@ -1,19 +0,0 @@ -/* - * 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 { services as kibanaFunctionalServices } from '../../../../test/functional/services'; -import { services as commonServices } from '../../common/services'; -import { UptimeProvider } from './uptime'; - -// define the name and providers for services that should be -// available to your tests. If you don't specify anything here -// only the built-in services will be available -export const services = { - ...kibanaFunctionalServices, - ...commonServices, - uptime: UptimeProvider, -}; diff --git a/x-pack/test/functional_synthetics/services/uptime/index.ts b/x-pack/test/functional_synthetics/services/uptime/index.ts deleted file mode 100644 index 649408c03284d..0000000000000 --- a/x-pack/test/functional_synthetics/services/uptime/index.ts +++ /dev/null @@ -1,8 +0,0 @@ -/* - * 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. - */ - -export { UptimeProvider } from './uptime'; diff --git a/x-pack/test/functional_synthetics/services/uptime/synthetics_package.ts b/x-pack/test/functional_synthetics/services/uptime/synthetics_package.ts deleted file mode 100644 index 5b9525bf2060b..0000000000000 --- a/x-pack/test/functional_synthetics/services/uptime/synthetics_package.ts +++ /dev/null @@ -1,176 +0,0 @@ -/* - * 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 { - PACKAGE_POLICY_SAVED_OBJECT_TYPE, - DeletePackagePoliciesRequest, - GetPackagePoliciesResponse, - GetFullAgentPolicyResponse, - GetPackagesResponse, - GetAgentPoliciesResponse, -} from '@kbn/fleet-plugin/common'; -import { FtrProviderContext } from '../../ftr_provider_context'; - -const INGEST_API_ROOT = '/api/fleet'; -const INGEST_API_AGENT_POLICIES = `${INGEST_API_ROOT}/agent_policies`; -const INGEST_API_PACKAGE_POLICIES = `${INGEST_API_ROOT}/package_policies`; -const INGEST_API_PACKAGE_POLICIES_DELETE = `${INGEST_API_PACKAGE_POLICIES}/delete`; -const INGEST_API_EPM_PACKAGES = `${INGEST_API_ROOT}/epm/packages`; - -export function SyntheticsPackageProvider({ getService }: FtrProviderContext) { - const supertest = getService('supertest'); - const log = getService('log'); - const retry = getService('retry'); - - const logSupertestApiErrorAndThrow = (message: string, error: any): never => { - const responseBody = error?.response?.body; - const responseText = error?.response?.text; - log.error(`Error occurred at ${Date.now()} | ${new Date().toISOString()}`); - log.error(JSON.stringify(responseBody || responseText, null, 2)); - log.error(error); - throw new Error(message); - }; - const retrieveSyntheticsPackageInfo = (() => { - // Retrieve information about the Synthetics package - // EPM does not currently have an API to get the "lastest" information for a page given its name, - // so we'll retrieve a list of packages and then find the package info in the list. - let apiRequest: Promise; - - return () => { - if (!apiRequest) { - log.info(`Setting up call to retrieve Synthetics package`); - - // Currently (as of 2020-june) the package registry used in CI is the public one and - // at times it encounters network connection issues. We use `retry.try` below to see if - // subsequent requests get through. - apiRequest = retry.try(() => { - return supertest - .get(INGEST_API_EPM_PACKAGES) - .query({ prerelease: true }) - .set('kbn-xsrf', 'xxx') - .expect(200) - .catch((error) => { - return logSupertestApiErrorAndThrow(`Unable to retrieve packages via Ingest!`, error); - }) - .then((response: { body: GetPackagesResponse }) => { - const { body } = response; - const syntheticsPackageInfo = body.items.find( - (epmPackage) => epmPackage.name === 'synthetics' - ); - if (!syntheticsPackageInfo) { - throw new Error( - `Synthetics package was not in response from ${INGEST_API_EPM_PACKAGES}` - ); - } - return Promise.resolve(syntheticsPackageInfo); - }); - }); - } else { - log.info('Using cached retrieval of synthetics package'); - } - return apiRequest; - }; - })(); - - return { - /** - * Returns the synthetics package version for the currently installed package. This version can then - * be used to build URLs for Fleet pages or APIs - */ - async getSyntheticsPackageVersion() { - const syntheticsPackage = await retrieveSyntheticsPackageInfo()!; - - return syntheticsPackage?.version; - }, - - /** - * Retrieves the full Agent policy by id, which mirrors what the Elastic Agent would get - * once they checkin. - */ - async getFullAgentPolicy(agentPolicyId: string): Promise { - let fullAgentPolicy: GetFullAgentPolicyResponse['item']; - try { - const apiResponse: { body: GetFullAgentPolicyResponse } = await supertest - .get(`${INGEST_API_AGENT_POLICIES}/${agentPolicyId}/full`) - .expect(200); - - fullAgentPolicy = apiResponse.body.item; - } catch (error) { - return logSupertestApiErrorAndThrow('Unable to get full Agent policy', error); - } - - return fullAgentPolicy!; - }, - - /** - * Retrieves all the agent policies. - */ - async getAgentPolicyList(): Promise { - let agentPolicyList: GetAgentPoliciesResponse['items']; - try { - const apiResponse: { body: GetAgentPoliciesResponse } = await supertest - .get(INGEST_API_AGENT_POLICIES) - .expect(200); - - agentPolicyList = apiResponse.body.items; - } catch (error) { - return logSupertestApiErrorAndThrow('Unable to get full Agent policy list', error); - } - - return agentPolicyList!; - }, - - /** - * Deletes a policy (Package Policy) by using the policy name - * @param name - */ - async deletePolicyByName(name: string) { - const id = await this.getPackagePolicyIdByName(name); - - if (id) { - try { - const deletePackagePolicyData: DeletePackagePoliciesRequest['body'] = { - packagePolicyIds: [id], - }; - await supertest - .post(INGEST_API_PACKAGE_POLICIES_DELETE) - .set('kbn-xsrf', 'xxx') - .send(deletePackagePolicyData) - .expect(200); - } catch (error) { - logSupertestApiErrorAndThrow( - `Unable to delete Package Policy via Ingest! ${name}`, - error - ); - } - } - }, - - /** - * Gets the policy id (Package Policy) by using the policy name - * @param name - */ - async getPackagePolicyIdByName(name: string) { - const { body: packagePoliciesResponse }: { body: GetPackagePoliciesResponse } = - await supertest - .get(INGEST_API_PACKAGE_POLICIES) - .set('kbn-xsrf', 'xxx') - .query({ kuery: `${PACKAGE_POLICY_SAVED_OBJECT_TYPE}.name: ${name}` }) - .send() - .expect(200); - const packagePolicyList: GetPackagePoliciesResponse['items'] = packagePoliciesResponse.items; - - if (packagePolicyList.length > 1) { - throw new Error(`Found ${packagePolicyList.length} Policies - was expecting only one!`); - } - - if (packagePolicyList.length) { - return packagePolicyList[0].id; - } - }, - }; -} diff --git a/x-pack/test/functional_synthetics/services/uptime/uptime.ts b/x-pack/test/functional_synthetics/services/uptime/uptime.ts deleted file mode 100644 index 24354f4ddae0d..0000000000000 --- a/x-pack/test/functional_synthetics/services/uptime/uptime.ts +++ /dev/null @@ -1,18 +0,0 @@ -/* - * 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 { FtrProviderContext } from '../../ftr_provider_context'; - -import { SyntheticsPackageProvider } from './synthetics_package'; - -export function UptimeProvider(context: FtrProviderContext) { - const syntheticsPackage = SyntheticsPackageProvider(context); - - return { - syntheticsPackage, - }; -}