diff --git a/x-pack/plugins/uptime/e2e/page_objects/monitor_management.tsx b/x-pack/plugins/uptime/e2e/page_objects/monitor_management.tsx index fd877708f2bce..384242bc9af70 100644 --- a/x-pack/plugins/uptime/e2e/page_objects/monitor_management.tsx +++ b/x-pack/plugins/uptime/e2e/page_objects/monitor_management.tsx @@ -96,9 +96,8 @@ export function monitorManagementPageProvider({ }, async selectLocations({ locations }: { locations: string[] }) { - await this.clickByTestSubj('syntheticsServiceLocationsComboBox'); for (let i = 0; i < locations.length; i++) { - await page.click(`text=${locations[i]}`); + await page.check(`text=${locations[i]}`); } }, diff --git a/x-pack/plugins/uptime/e2e/page_objects/utils.tsx b/x-pack/plugins/uptime/e2e/page_objects/utils.tsx index 072d4497e856d..024609e2f69ef 100644 --- a/x-pack/plugins/uptime/e2e/page_objects/utils.tsx +++ b/x-pack/plugins/uptime/e2e/page_objects/utils.tsx @@ -38,6 +38,10 @@ export function utilsPageProvider({ page }: { page: Page }) { await page.selectOption(`[data-test-subj=${dataTestSubj}]`, value); }, + async checkByTestSubj(dataTestSubj: string, value: string) { + await page.check(`[data-test-subj=${dataTestSubj}]`); + }, + async clickByTestSubj(dataTestSubj: string) { await page.click(`[data-test-subj=${dataTestSubj}]`); }, diff --git a/x-pack/plugins/uptime/public/components/monitor_management/monitor_config/locations.test.tsx b/x-pack/plugins/uptime/public/components/monitor_management/monitor_config/locations.test.tsx index 11caf092c93c7..ccc3e7b619c68 100644 --- a/x-pack/plugins/uptime/public/components/monitor_management/monitor_config/locations.test.tsx +++ b/x-pack/plugins/uptime/public/components/monitor_management/monitor_config/locations.test.tsx @@ -8,8 +8,7 @@ import React from 'react'; import { screen } from '@testing-library/react'; import { render } from '../../../lib/helper/rtl_helpers'; -import { ServiceLocations, LOCATIONS_LABEL } from './locations'; -import userEvent from '@testing-library/user-event'; +import { ServiceLocations } from './locations'; describe('', () => { const setLocations = jest.fn(); @@ -52,47 +51,7 @@ describe('', () => { { state } ); - expect(screen.getByText(LOCATIONS_LABEL)).toBeInTheDocument(); - expect(screen.queryByText('US Central')).not.toBeInTheDocument(); - }); - - it('shows location options when clicked', async () => { - render( - , - { state } - ); - - userEvent.click(screen.getByRole('button')); - - expect(screen.getByText('US Central')).toBeInTheDocument(); - }); - - it('prevents bad inputs', async () => { - render( - , - { state } - ); - - userEvent.click(screen.getByRole('button')); - userEvent.type(screen.getByRole('textbox'), 'fake location'); - - expect(screen.getByText("doesn't match any options")).toBeInTheDocument(); - - userEvent.keyboard(`{enter}`); - - expect(screen.getByText('"fake location" is not a valid option')).toBeInTheDocument(); - }); - - it('calls setLocations', async () => { - render( - , - { state } - ); - - userEvent.click(screen.getByRole('button')); - userEvent.click(screen.getByText('US Central')); - - expect(setLocations).toBeCalledWith([location]); + expect(screen.queryByText('US Central')).toBeInTheDocument(); }); it('shows invalid error', async () => { diff --git a/x-pack/plugins/uptime/public/components/monitor_management/monitor_config/locations.tsx b/x-pack/plugins/uptime/public/components/monitor_management/monitor_config/locations.tsx index 2d261e169299a..1877cc4ade126 100644 --- a/x-pack/plugins/uptime/public/components/monitor_management/monitor_config/locations.tsx +++ b/x-pack/plugins/uptime/public/components/monitor_management/monitor_config/locations.tsx @@ -5,10 +5,10 @@ * 2.0. */ -import React, { useState } from 'react'; +import React, { useState, useEffect } from 'react'; import { useSelector } from 'react-redux'; import { i18n } from '@kbn/i18n'; -import { EuiComboBox, EuiComboBoxOptionOption, EuiFormRow } from '@elastic/eui'; +import { EuiCheckboxGroup, EuiFormRow } from '@elastic/eui'; import { monitorManagementListSelector } from '../../../state/selectors'; import { ServiceLocation } from '../../../../common/runtime_types'; @@ -20,51 +20,49 @@ interface Props { export const ServiceLocations = ({ selectedLocations, setLocations, isInvalid }: Props) => { const [error, setError] = useState(null); + const [checkboxIdToSelectedMap, setCheckboxIdToSelectedMap] = useState>( + {} + ); const { locations } = useSelector(monitorManagementListSelector); - const onLocationChange = ( - selectedLocationOptions: Array> - ) => { - setLocations(selectedLocationOptions as ServiceLocation[]); - setError(null); - }; - - const onSearchChange = (value: string, hasMatchingOptions?: boolean) => { - setError(value.length === 0 || hasMatchingOptions ? null : getInvalidOptionError(value)); - }; - - const onBlur = (event: unknown) => { - const inputElement = (event as FocusEvent)?.target as HTMLInputElement; - if (inputElement) { - const { value } = inputElement; - setError(value.length === 0 ? null : getInvalidOptionError(value)); + const onLocationChange = (optionId: string) => { + const isSelected = !checkboxIdToSelectedMap[optionId]; + const location = locations.find((loc) => loc.id === optionId); + if (isSelected) { + setLocations((prevLocations) => (location ? [...prevLocations, location] : prevLocations)); + } else { + setLocations((prevLocations) => [...prevLocations].filter((loc) => loc.id !== optionId)); } + setError(null); }; const errorMessage = error ?? (isInvalid ? VALIDATION_ERROR : null); + useEffect(() => { + const newCheckboxIdToSelectedMap = selectedLocations.reduce>( + (acc, location) => { + acc[location.id] = true; + return acc; + }, + {} + ); + setCheckboxIdToSelectedMap(newCheckboxIdToSelectedMap); + }, [selectedLocations]); + return ( - ({ + ...location, + 'data-test-subj': `syntheticsServiceLocation--${location.id}`, + }))} + idToSelectedMap={checkboxIdToSelectedMap} + onChange={(id) => onLocationChange(id)} /> ); }; -const PLACEHOLDER_LABEL = i18n.translate( - 'xpack.uptime.monitorManagement.serviceLocationsPlaceholderLabel', - { - defaultMessage: 'Select one or more locations to run your monitor.', - } -); - const VALIDATION_ERROR = i18n.translate( 'xpack.uptime.monitorManagement.serviceLocationsValidationError', { @@ -72,14 +70,6 @@ const VALIDATION_ERROR = i18n.translate( } ); -const getInvalidOptionError = (value: string) => - i18n.translate('xpack.uptime.monitorManagement.serviceLocationsOptionError', { - defaultMessage: '"{value}" is not a valid option', - values: { - value, - }, - }); - export const LOCATIONS_LABEL = i18n.translate( 'xpack.uptime.monitorManagement.monitorLocationsLabel', {