diff --git a/x-pack/solutions/observability/plugins/observability_onboarding/public/application/onboarding_flow_form/onboarding_flow_form.test.tsx b/x-pack/solutions/observability/plugins/observability_onboarding/public/application/onboarding_flow_form/onboarding_flow_form.test.tsx
index 51a49db433dde..3844a9688e3a7 100644
--- a/x-pack/solutions/observability/plugins/observability_onboarding/public/application/onboarding_flow_form/onboarding_flow_form.test.tsx
+++ b/x-pack/solutions/observability/plugins/observability_onboarding/public/application/onboarding_flow_form/onboarding_flow_form.test.tsx
@@ -40,16 +40,19 @@ jest.mock('../package_list/package_list', () => ({
),
}));
-jest.mock('../package_list_search_form/package_list_search_form', () => ({
- PackageListSearchForm: () =>
Search Form
,
-}));
-
const mockUseKibana = useKibana as jest.MockedFunction;
const mockUsePricingFeature = usePricingFeature as jest.MockedFunction;
+const mockPackageListSearchForm = jest.fn(({ searchQuery }: { searchQuery: string }) => (
+ Search Form: {searchQuery}
+));
+
+jest.mock('../package_list_search_form/package_list_search_form', () => ({
+ PackageListSearchForm: (props: { searchQuery: string }) => mockPackageListSearchForm(props),
+}));
-const renderWithProviders = (children: React.ReactNode) => {
+const renderWithProviders = (children: React.ReactNode, initialEntries: string[] = ['/']) => {
return render(
-
+
{children}
);
@@ -177,5 +180,15 @@ describe('OnboardingFlowForm', () => {
expect(screen.getByText(/Search through other ways of ingesting data/)).toBeInTheDocument();
expect(screen.getByTestId('package-search-form')).toBeInTheDocument();
});
+
+ it('should pass empty searchQuery to search form when URL search is invalid KQL', () => {
+ mockUsePricingFeature.mockReturnValue(true);
+
+ renderWithProviders(, ['/?search=host:(']);
+
+ expect(mockPackageListSearchForm).toHaveBeenCalledWith(
+ expect.objectContaining({ searchQuery: '' })
+ );
+ });
});
});
diff --git a/x-pack/solutions/observability/plugins/observability_onboarding/public/application/onboarding_flow_form/onboarding_flow_form.tsx b/x-pack/solutions/observability/plugins/observability_onboarding/public/application/onboarding_flow_form/onboarding_flow_form.tsx
index e575d13a475c5..feec48f953058 100644
--- a/x-pack/solutions/observability/plugins/observability_onboarding/public/application/onboarding_flow_form/onboarding_flow_form.tsx
+++ b/x-pack/solutions/observability/plugins/observability_onboarding/public/application/onboarding_flow_form/onboarding_flow_form.tsx
@@ -21,6 +21,7 @@ import {
useEuiTheme,
EuiBadge,
EuiFlexGrid,
+ EuiSearchBar,
} from '@elastic/eui';
import { css } from '@emotion/react';
@@ -143,11 +144,13 @@ export const OnboardingFlowForm: FunctionComponent = () => {
const suggestedPackagesRef = useRef(null);
const searchResultsRef = useRef(null);
- const [integrationSearch, setIntegrationSearch] = useState(searchParams.get('search') ?? '');
+ const [integrationSearch, setIntegrationSearch] = useState(
+ parseSearchQuery(searchParams.get('search'))
+ );
const { euiTheme } = useEuiTheme();
useEffect(() => {
- const searchParam = searchParams.get('search') ?? '';
+ const searchParam = parseSearchQuery(searchParams.get('search'));
if (integrationSearch === searchParam) return;
const entries: Record = Object.fromEntries(searchParams.entries());
if (integrationSearch) {
@@ -400,3 +403,16 @@ function scrollIntoViewWithOffset(element: HTMLElement, offset = 0) {
top: element.getBoundingClientRect().top - document.body.getBoundingClientRect().top - offset,
});
}
+
+function parseSearchQuery(searchQuery: string | null) {
+ if (searchQuery === null) {
+ return '';
+ }
+
+ try {
+ EuiSearchBar.Query.parse(searchQuery ?? '');
+ return searchQuery;
+ } catch {
+ return '';
+ }
+}