From 3bcfc37da1afadf404cca3f2418a8a730fee0856 Mon Sep 17 00:00:00 2001 From: Karen Grigoryan Date: Sun, 22 Mar 2026 17:01:38 +0100 Subject: [PATCH 1/4] [Upgrade Assistant] Migrate Kibana deprecations flaky integration tests to unit tests Co-authored-by: Cursor --- .../deprecation_details_flyout.test.ts | 151 -------- .../deprecations_table.test.ts | 142 -------- .../deprecations_table/error_handling.test.ts | 103 ------ .../kibana_deprecations.helpers.tsx | 43 --- .../deprecation_details_flyout.test.tsx | 265 ++++++++++++++ .../kibana_deprecations.test.tsx | 342 ++++++++++++++++++ .../kibana_deprecations.tsx | 8 +- .../kibana_deprecations_table.test.tsx | 207 +++++++++++ 8 files changed, 820 insertions(+), 441 deletions(-) delete mode 100644 x-pack/platform/plugins/private/upgrade_assistant/__jest__/client_integration/kibana_deprecations/deprecation_details_flyout/deprecation_details_flyout.test.ts delete mode 100644 x-pack/platform/plugins/private/upgrade_assistant/__jest__/client_integration/kibana_deprecations/deprecations_table/deprecations_table.test.ts delete mode 100644 x-pack/platform/plugins/private/upgrade_assistant/__jest__/client_integration/kibana_deprecations/deprecations_table/error_handling.test.ts delete mode 100644 x-pack/platform/plugins/private/upgrade_assistant/__jest__/client_integration/kibana_deprecations/kibana_deprecations.helpers.tsx create mode 100644 x-pack/platform/plugins/private/upgrade_assistant/public/application/components/kibana_deprecations/deprecation_details_flyout.test.tsx create mode 100644 x-pack/platform/plugins/private/upgrade_assistant/public/application/components/kibana_deprecations/kibana_deprecations.test.tsx create mode 100644 x-pack/platform/plugins/private/upgrade_assistant/public/application/components/kibana_deprecations/kibana_deprecations_table.test.tsx diff --git a/x-pack/platform/plugins/private/upgrade_assistant/__jest__/client_integration/kibana_deprecations/deprecation_details_flyout/deprecation_details_flyout.test.ts b/x-pack/platform/plugins/private/upgrade_assistant/__jest__/client_integration/kibana_deprecations/deprecation_details_flyout/deprecation_details_flyout.test.ts deleted file mode 100644 index 876d284a610d2..0000000000000 --- a/x-pack/platform/plugins/private/upgrade_assistant/__jest__/client_integration/kibana_deprecations/deprecation_details_flyout/deprecation_details_flyout.test.ts +++ /dev/null @@ -1,151 +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 { deprecationsServiceMock } from '@kbn/core/public/mocks'; -import { fireEvent, screen, waitFor, within } from '@testing-library/react'; -import '@testing-library/jest-dom'; - -import { setupEnvironment } from '../../helpers/setup_environment'; -import { kibanaDeprecationsServiceHelpers } from '../service.mock'; -import { setupKibanaPage } from '../kibana_deprecations.helpers'; - -describe('Kibana deprecations - Deprecation details flyout', () => { - const { - defaultMockedResponses: { mockedKibanaDeprecations }, - } = kibanaDeprecationsServiceHelpers; - const deprecationService = deprecationsServiceMock.createStartContract(); - let httpSetup: ReturnType['httpSetup']; - - beforeEach(async () => { - const mockEnvironment = setupEnvironment(); - httpSetup = mockEnvironment.httpSetup; - - kibanaDeprecationsServiceHelpers.setLoadDeprecations({ deprecationService }); - - await setupKibanaPage(httpSetup, { - services: { - core: { - deprecations: deprecationService, - }, - }, - }); - - await screen.findByTestId('kibanaDeprecationsTable'); - }); - - const openDeprecationAt = async (index: number) => { - const table = screen.getByTestId('kibanaDeprecationsTable'); - const rows = within(table).getAllByTestId('row'); - const row = rows[index]; - fireEvent.click(within(row).getByTestId('deprecationDetailsLink')); - return await screen.findByTestId('kibanaDeprecationDetails'); - }; - - describe('Deprecation with manual steps', () => { - test('renders flyout with single manual step as a standalone paragraph', async () => { - const manualDeprecation = mockedKibanaDeprecations[1]; - - const flyout = await openDeprecationAt(0); - - expect(flyout).toBeInTheDocument(); - expect(screen.getByTestId('flyoutTitle')).toHaveTextContent(manualDeprecation.title); - expect(screen.getAllByTestId('manualStep')).toHaveLength(1); - }); - - test('renders flyout with multiple manual steps as a list', async () => { - const manualDeprecation = mockedKibanaDeprecations[1]; - - const flyout = await openDeprecationAt(1); - - expect(flyout).toBeInTheDocument(); - expect(screen.getByTestId('flyoutTitle')).toHaveTextContent(manualDeprecation.title); - expect(screen.getAllByTestId('manualStepsListItem')).toHaveLength(3); - }); - - test(`doesn't show corrective actions title and steps if there aren't any`, async () => { - const manualDeprecation = mockedKibanaDeprecations[2]; - - const flyout = await openDeprecationAt(2); - - expect(flyout).toBeInTheDocument(); - expect(screen.queryByTestId('manualStepsTitle')).not.toBeInTheDocument(); - expect(screen.queryByTestId('manualStepsListItem')).not.toBeInTheDocument(); - expect(screen.getByTestId('flyoutTitle')).toHaveTextContent(manualDeprecation.title); - }); - }); - - test('Shows documentationUrl when present', async () => { - const deprecation = mockedKibanaDeprecations[1]; - - const flyout = await openDeprecationAt(1); - const docLink = within(flyout).getByTestId('documentationLink') as HTMLAnchorElement; - expect(docLink.getAttribute('href')).toBe(deprecation.documentationUrl); - }); - - describe('Deprecation with automatic resolution', () => { - test('resolves deprecation successfully', async () => { - const quickResolveDeprecation = mockedKibanaDeprecations[0]; - - const flyout = await openDeprecationAt(0); - expect(within(flyout).getByTestId('criticalDeprecationBadge')).toBeInTheDocument(); - expect(within(flyout).getByTestId('flyoutTitle')).toHaveTextContent( - quickResolveDeprecation.title - ); - - // Quick resolve callout and button should display - expect(within(flyout).getByTestId('quickResolveCallout')).toBeInTheDocument(); - expect(within(flyout).getByTestId('resolveButton')).toBeInTheDocument(); - - fireEvent.click(within(flyout).getByTestId('resolveButton')); - - await waitFor(() => { - expect(screen.queryByTestId('kibanaDeprecationDetails')).not.toBeInTheDocument(); - }); - - // Reopen the flyout - const reopenedFlyout = await openDeprecationAt(0); - - // Resolve information should not display and Quick resolve button should be disabled - expect(within(reopenedFlyout).queryByTestId('resolveSection')).not.toBeInTheDocument(); - expect(within(reopenedFlyout).queryByTestId('resolveButton')).not.toBeInTheDocument(); - expect(within(reopenedFlyout).getByTestId('resolvedDeprecationBadge')).toBeInTheDocument(); - }); - - test('handles resolve failure', async () => { - const quickResolveDeprecation = mockedKibanaDeprecations[0]; - - kibanaDeprecationsServiceHelpers.setResolveDeprecations({ - deprecationService, - status: 'fail', - }); - - const flyout = await openDeprecationAt(0); - expect(within(flyout).getByTestId('criticalDeprecationBadge')).toBeInTheDocument(); - expect(within(flyout).getByTestId('flyoutTitle')).toHaveTextContent( - quickResolveDeprecation.title - ); - - // Quick resolve callout and button should display - expect(within(flyout).getByTestId('quickResolveCallout')).toBeInTheDocument(); - expect(within(flyout).getByTestId('resolveButton')).toBeInTheDocument(); - - fireEvent.click(within(flyout).getByTestId('resolveButton')); - await waitFor(() => { - expect(screen.queryByTestId('kibanaDeprecationDetails')).not.toBeInTheDocument(); - }); - - // Reopen the flyout - const reopenedFlyout = await openDeprecationAt(0); - - expect(within(reopenedFlyout).getByTestId('quickResolveError')).toBeInTheDocument(); - expect(within(reopenedFlyout).getByTestId('resolveSection')).toBeInTheDocument(); - expect(within(reopenedFlyout).getByTestId('criticalDeprecationBadge')).toBeInTheDocument(); - expect(within(reopenedFlyout).getByTestId('resolveButton')).toBeEnabled(); - expect(within(reopenedFlyout).getByTestId('resolveButton')).toHaveTextContent('Try again'); - }); - }); -}); diff --git a/x-pack/platform/plugins/private/upgrade_assistant/__jest__/client_integration/kibana_deprecations/deprecations_table/deprecations_table.test.ts b/x-pack/platform/plugins/private/upgrade_assistant/__jest__/client_integration/kibana_deprecations/deprecations_table/deprecations_table.test.ts deleted file mode 100644 index 9dff838f021a8..0000000000000 --- a/x-pack/platform/plugins/private/upgrade_assistant/__jest__/client_integration/kibana_deprecations/deprecations_table/deprecations_table.test.ts +++ /dev/null @@ -1,142 +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 { deprecationsServiceMock } from '@kbn/core/public/mocks'; -import type { DeprecationsServiceStart } from '@kbn/core/public'; -import { fireEvent, screen, waitFor, within } from '@testing-library/react'; -import '@testing-library/jest-dom'; - -import { kibanaDeprecationsServiceHelpers } from '../service.mock'; -import { setupEnvironment } from '../../helpers/setup_environment'; -import { setupKibanaPage } from '../kibana_deprecations.helpers'; - -// Failing: See https://github.com/elastic/kibana/issues/253915 -describe.skip('Kibana deprecations - Deprecations table', () => { - let deprecationService: jest.Mocked; - - const { - mockedKibanaDeprecations, - mockedCriticalKibanaDeprecations, - mockedWarningKibanaDeprecations, - mockedConfigKibanaDeprecations, - } = kibanaDeprecationsServiceHelpers.defaultMockedResponses; - - let httpSetup: ReturnType['httpSetup']; - beforeEach(() => { - const mockEnvironment = setupEnvironment(); - httpSetup = mockEnvironment.httpSetup; - deprecationService = deprecationsServiceMock.createStartContract(); - }); - - const setup = async (overrides?: Record) => { - kibanaDeprecationsServiceHelpers.setLoadDeprecations({ deprecationService }); - - await setupKibanaPage(httpSetup, { - services: { - core: { - deprecations: deprecationService, - }, - }, - ...overrides, - }); - - await screen.findByTestId('kibanaDeprecationsTable'); - }; - - test('renders deprecations', async () => { - await setup(); - - expect(screen.getByTestId('kibanaDeprecations')).toBeInTheDocument(); - const table = screen.getByTestId('kibanaDeprecationsTable'); - expect(within(table).getAllByTestId('row')).toHaveLength(mockedKibanaDeprecations.length); - }); - - it('refreshes deprecation data', async () => { - await setup(); - - expect(deprecationService.getAllDeprecations).toHaveBeenCalledTimes(1); - - fireEvent.click(screen.getByTestId('refreshButton')); - - await waitFor(() => { - expect(deprecationService.getAllDeprecations).toHaveBeenCalledTimes(2); - }); - }); - - it('shows critical and warning deprecations count', async () => { - await setup(); - - expect(screen.getByTestId('criticalDeprecationsCount')).toHaveTextContent( - String(mockedCriticalKibanaDeprecations.length) - ); - expect(screen.getByTestId('warningDeprecationsCount')).toHaveTextContent( - String(mockedWarningKibanaDeprecations.length) - ); - }); - - describe('Search bar', () => { - const clickFilterByTitle = async (title: string) => { - await waitFor(() => { - const filterButton: HTMLElement | null = document.body.querySelector( - `.euiSelectableListItem[title="${title}"]` - ); - - expect(filterButton).not.toBeNull(); - filterButton!.click(); - }); - }; - - it('filters by "critical" status', async () => { - await setup(); - - // Show only critical deprecations - fireEvent.click(screen.getByRole('button', { name: 'Status Selection' })); - await clickFilterByTitle('Critical'); - await waitFor(() => { - expect(screen.getAllByTestId('row')).toHaveLength(mockedCriticalKibanaDeprecations.length); - }); - - // Show all deprecations (toggle off) - fireEvent.click(screen.getByRole('button', { name: 'Status Selection' })); - await clickFilterByTitle('Critical'); - await waitFor(() => { - expect(screen.getAllByTestId('row')).toHaveLength(mockedKibanaDeprecations.length); - }); - }); - - it('filters by type', async () => { - await setup(); - - fireEvent.click(screen.getByRole('button', { name: 'Type Selection' })); - await clickFilterByTitle('Config'); - - await waitFor(() => { - expect(screen.getAllByTestId('row')).toHaveLength(mockedConfigKibanaDeprecations.length); - }); - }); - }); - - describe('No deprecations', () => { - beforeEach(async () => { - kibanaDeprecationsServiceHelpers.setLoadDeprecations({ deprecationService, response: [] }); - await setupKibanaPage(httpSetup, { - services: { - core: { - deprecations: deprecationService, - }, - }, - }); - }); - - test('renders prompt', () => { - expect(screen.getByTestId('noDeprecationsPrompt')).toBeInTheDocument(); - expect(screen.getByTestId('noDeprecationsPrompt')).toHaveTextContent( - 'Your Kibana configuration is up to date' - ); - }); - }); -}); diff --git a/x-pack/platform/plugins/private/upgrade_assistant/__jest__/client_integration/kibana_deprecations/deprecations_table/error_handling.test.ts b/x-pack/platform/plugins/private/upgrade_assistant/__jest__/client_integration/kibana_deprecations/deprecations_table/error_handling.test.ts deleted file mode 100644 index 0c5d575b6be07..0000000000000 --- a/x-pack/platform/plugins/private/upgrade_assistant/__jest__/client_integration/kibana_deprecations/deprecations_table/error_handling.test.ts +++ /dev/null @@ -1,103 +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 { deprecationsServiceMock } from '@kbn/core/public/mocks'; - -import { APP_LOGS_COUNT_CLUSTER_PRIVILEGES } from '../../../../common/constants'; -import { screen } from '@testing-library/react'; -import '@testing-library/jest-dom'; -import { setupEnvironment } from '../../helpers/setup_environment'; -import { kibanaDeprecationsServiceHelpers } from '../service.mock'; -import { setupKibanaPage } from '../kibana_deprecations.helpers'; - -describe('Kibana deprecations - Deprecations table - Error handling', () => { - const deprecationService = deprecationsServiceMock.createStartContract(); - - let httpSetup: ReturnType['httpSetup']; - beforeEach(() => { - const mockEnvironment = setupEnvironment(); - httpSetup = mockEnvironment.httpSetup; - }); - - test('handles plugin errors', async () => { - kibanaDeprecationsServiceHelpers.setLoadDeprecations({ - deprecationService, - response: [ - ...kibanaDeprecationsServiceHelpers.defaultMockedResponses.mockedKibanaDeprecations, - { - domainId: 'failed_plugin_id_1', - title: 'Failed to fetch deprecations for "failed_plugin_id"', - message: `Failed to get deprecations info for plugin "failed_plugin_id".`, - level: 'fetch_error', - correctiveActions: { - manualSteps: ['Check Kibana server logs for error message.'], - }, - }, - { - domainId: 'failed_plugin_id_1', - title: 'Failed to fetch deprecations for "failed_plugin_id"', - message: `Failed to get deprecations info for plugin "failed_plugin_id".`, - level: 'fetch_error', - correctiveActions: { - manualSteps: ['Check Kibana server logs for error message.'], - }, - }, - { - domainId: 'failed_plugin_id_2', - title: 'Failed to fetch deprecations for "failed_plugin_id"', - message: `Failed to get deprecations info for plugin "failed_plugin_id".`, - level: 'fetch_error', - correctiveActions: { - manualSteps: ['Check Kibana server logs for error message.'], - }, - }, - ], - }); - - await setupKibanaPage(httpSetup, { - services: { - core: { - deprecations: deprecationService, - }, - }, - privileges: { - hasAllPrivileges: true, - missingPrivileges: { - cluster: [...APP_LOGS_COUNT_CLUSTER_PRIVILEGES], - index: [], - }, - }, - }); - - expect(screen.getByTestId('kibanaDeprecationErrors')).toBeInTheDocument(); - expect(screen.getByTestId('kibanaDeprecationErrors')).toHaveTextContent( - 'Failed to get deprecation issues for these plugins: failed_plugin_id_1, failed_plugin_id_2.' - ); - expect(screen.getByTestId('kibanaDeprecationErrors')).toHaveTextContent( - 'Certain issues might be missing due to missing cluster privilege for: manage_security' - ); - }); - - test('handles request error', async () => { - kibanaDeprecationsServiceHelpers.setLoadDeprecations({ - deprecationService, - mockRequestErrorMessage: 'Internal Server Error', - }); - - await setupKibanaPage(httpSetup, { - services: { - core: { - deprecations: deprecationService, - }, - }, - }); - - expect(screen.getByTestId('deprecationsPageLoadingError')).toHaveTextContent( - 'Could not retrieve Kibana deprecation issues' - ); - }); -}); diff --git a/x-pack/platform/plugins/private/upgrade_assistant/__jest__/client_integration/kibana_deprecations/kibana_deprecations.helpers.tsx b/x-pack/platform/plugins/private/upgrade_assistant/__jest__/client_integration/kibana_deprecations/kibana_deprecations.helpers.tsx deleted file mode 100644 index afff5deaf32f2..0000000000000 --- a/x-pack/platform/plugins/private/upgrade_assistant/__jest__/client_integration/kibana_deprecations/kibana_deprecations.helpers.tsx +++ /dev/null @@ -1,43 +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 type { HttpSetup } from '@kbn/core/public'; -import React from 'react'; -import { screen, waitFor } from '@testing-library/react'; -import { renderWithI18n } from '@kbn/test-jest-helpers'; -import { createMemoryHistory } from 'history'; -import { Router, Routes, Route } from '@kbn/shared-ux-router'; -import { KibanaDeprecations } from '../../../public/application/components'; -import { WithAppDependencies } from '../helpers/setup_environment'; - -export const setupKibanaPage = async ( - httpSetup: HttpSetup, - overrides?: Record -): Promise => { - const KibanaDeprecationsWithDependencies = WithAppDependencies( - KibanaDeprecations, - httpSetup, - overrides - ); - const history = createMemoryHistory({ initialEntries: ['/kibana_deprecations'] }); - - renderWithI18n( - - - - - - ); - - // Wait for the initial render baseline (mount-time requests/async state). - await waitFor(() => { - const page = - screen.queryByTestId('kibanaDeprecations') ?? - screen.queryByTestId('noDeprecationsPrompt') ?? - screen.queryByTestId('deprecationsPageLoadingError'); - expect(page).not.toBeNull(); - }); -}; diff --git a/x-pack/platform/plugins/private/upgrade_assistant/public/application/components/kibana_deprecations/deprecation_details_flyout.test.tsx b/x-pack/platform/plugins/private/upgrade_assistant/public/application/components/kibana_deprecations/deprecation_details_flyout.test.tsx new file mode 100644 index 0000000000000..eef3a84a21e30 --- /dev/null +++ b/x-pack/platform/plugins/private/upgrade_assistant/public/application/components/kibana_deprecations/deprecation_details_flyout.test.tsx @@ -0,0 +1,265 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; +import { render, screen, fireEvent } from '@testing-library/react'; +import '@testing-library/jest-dom'; +import { I18nProvider } from '@kbn/i18n-react'; + +import type { KibanaDeprecationDetails } from './kibana_deprecations'; +import type { DeprecationResolutionState } from './kibana_deprecations'; +import { DeprecationDetailsFlyout } from './deprecation_details_flyout'; + +const renderWithProviders = (ui: React.ReactElement) => render({ui}); + +const createFeatureDeprecation = ( + overrides: Partial< + Omit + > = {} +): KibanaDeprecationDetails => ({ + id: 'test-id', + domainId: 'test_domain', + level: 'warning', + title: 'Test deprecation title', + message: 'Test deprecation message', + correctiveActions: { manualSteps: [] }, + ...overrides, + deprecationType: 'feature', + filterType: 'feature', +}); + +const mockCloseFlyout = jest.fn(); +const mockResolveDeprecation = jest.fn().mockResolvedValue(undefined); + +describe('DeprecationDetailsFlyout', () => { + beforeEach(() => { + jest.clearAllMocks(); + }); + + describe('WHEN deprecation has a single manual step', () => { + it('SHOULD render the step as a standalone paragraph', () => { + const deprecation = createFeatureDeprecation({ + id: 'dep-1', + level: 'critical', + title: 'Critical deprecation', + correctiveActions: { + manualSteps: ['Step 1'], + api: { method: 'POST' as const, path: '/test' }, + }, + }); + + renderWithProviders( + + ); + + expect(screen.getByTestId('flyoutTitle')).toHaveTextContent(deprecation.title); + expect(screen.getAllByTestId('manualStep')).toHaveLength(1); + }); + }); + + describe('WHEN deprecation has multiple manual steps', () => { + it('SHOULD render steps as a list', () => { + const deprecation = createFeatureDeprecation({ + id: 'dep-2', + title: 'Multi-step deprecation', + correctiveActions: { + manualSteps: ['Step 1', 'Step 2', 'Step 3'], + }, + }); + + renderWithProviders( + + ); + + expect(screen.getByTestId('flyoutTitle')).toHaveTextContent(deprecation.title); + expect(screen.getAllByTestId('manualStepsListItem')).toHaveLength(3); + }); + }); + + describe('WHEN deprecation has no manual steps', () => { + it('SHOULD not show corrective actions title and steps', () => { + const deprecation = createFeatureDeprecation({ + id: 'dep-3', + title: 'No-steps deprecation', + correctiveActions: { + manualSteps: [], + }, + }); + + renderWithProviders( + + ); + + expect(screen.getByTestId('flyoutTitle')).toHaveTextContent(deprecation.title); + expect(screen.queryByTestId('manualStepsTitle')).not.toBeInTheDocument(); + expect(screen.queryByTestId('manualStepsListItem')).not.toBeInTheDocument(); + }); + }); + + describe('WHEN deprecation has a documentation URL', () => { + it('SHOULD render the documentation link', () => { + const deprecation = createFeatureDeprecation({ + id: 'dep-doc', + documentationUrl: 'https://example.com/docs', + correctiveActions: { manualSteps: ['Step 1', 'Step 2'] }, + }); + + renderWithProviders( + + ); + + const docLink = screen.getByTestId('documentationLink') as HTMLAnchorElement; + expect(docLink.getAttribute('href')).toBe('https://example.com/docs'); + }); + }); + + describe('WHEN deprecation supports automatic resolution', () => { + it('SHOULD show quick resolve callout and button', () => { + const deprecation = createFeatureDeprecation({ + id: 'dep-auto', + level: 'critical', + correctiveActions: { + manualSteps: ['Step 1'], + api: { method: 'POST' as const, path: '/test' }, + }, + }); + + renderWithProviders( + + ); + + expect(screen.getByTestId('criticalDeprecationBadge')).toBeInTheDocument(); + expect(screen.getByTestId('quickResolveCallout')).toBeInTheDocument(); + expect(screen.getByTestId('resolveButton')).toBeInTheDocument(); + }); + + it('SHOULD call resolveDeprecation when resolve button is clicked', () => { + const deprecation = createFeatureDeprecation({ + id: 'dep-resolve', + level: 'critical', + correctiveActions: { + manualSteps: ['Step 1'], + api: { method: 'POST' as const, path: '/test' }, + }, + }); + + renderWithProviders( + + ); + + fireEvent.click(screen.getByTestId('resolveButton')); + expect(mockResolveDeprecation).toHaveBeenCalledTimes(1); + expect(mockResolveDeprecation).toHaveBeenCalledWith(deprecation); + }); + + it('SHOULD show resolved badge and hide resolve controls after successful resolution', () => { + const deprecation = createFeatureDeprecation({ + id: 'dep-resolved', + level: 'critical', + correctiveActions: { + manualSteps: ['Step 1'], + api: { method: 'POST' as const, path: '/test' }, + }, + }); + + const resolutionState: DeprecationResolutionState = { + id: 'dep-resolved', + resolveDeprecationStatus: 'ok', + }; + + renderWithProviders( + + ); + + expect(screen.queryByTestId('resolveSection')).not.toBeInTheDocument(); + expect(screen.queryByTestId('resolveButton')).not.toBeInTheDocument(); + expect(screen.getByTestId('resolvedDeprecationBadge')).toBeInTheDocument(); + }); + + it('SHOULD show error and retry button after failed resolution', () => { + const deprecation = createFeatureDeprecation({ + id: 'dep-failed', + level: 'critical', + correctiveActions: { + manualSteps: ['Step 1'], + api: { method: 'POST' as const, path: '/test' }, + }, + }); + + const resolutionState: DeprecationResolutionState = { + id: 'dep-failed', + resolveDeprecationStatus: 'fail', + resolveDeprecationError: 'resolve failed', + }; + + renderWithProviders( + + ); + + expect(screen.getByTestId('quickResolveError')).toBeInTheDocument(); + expect(screen.getByTestId('resolveSection')).toBeInTheDocument(); + expect(screen.getByTestId('criticalDeprecationBadge')).toBeInTheDocument(); + expect(screen.getByTestId('resolveButton')).toBeEnabled(); + expect(screen.getByTestId('resolveButton')).toHaveTextContent('Try again'); + }); + }); + + describe('WHEN deprecation does not support automatic resolution', () => { + it('SHOULD not show resolve button', () => { + const deprecation = createFeatureDeprecation({ + id: 'dep-manual', + correctiveActions: { + manualSteps: ['Step 1'], + }, + }); + + renderWithProviders( + + ); + + expect(screen.queryByTestId('resolveButton')).not.toBeInTheDocument(); + }); + }); +}); diff --git a/x-pack/platform/plugins/private/upgrade_assistant/public/application/components/kibana_deprecations/kibana_deprecations.test.tsx b/x-pack/platform/plugins/private/upgrade_assistant/public/application/components/kibana_deprecations/kibana_deprecations.test.tsx new file mode 100644 index 0000000000000..c435a70f2bda3 --- /dev/null +++ b/x-pack/platform/plugins/private/upgrade_assistant/public/application/components/kibana_deprecations/kibana_deprecations.test.tsx @@ -0,0 +1,342 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React, { type ReactNode } from 'react'; +import { render, screen, waitFor, fireEvent, act } from '@testing-library/react'; +import '@testing-library/jest-dom'; +import { I18nProvider } from '@kbn/i18n-react'; +import { createMemoryHistory } from 'history'; + +const mockGetAllDeprecations = jest.fn(); +const mockResolveDeprecation = jest.fn(); +const mockSetBreadcrumbs = jest.fn(); +const mockAddContent = jest.fn(); +const mockRemoveContent = jest.fn(); + +interface PrivilegesCheckResult { + hasPrivileges: boolean; + isLoading: boolean; + privilegesMissing: { cluster?: string[] }; +} + +jest.mock('@kbn/es-ui-shared-plugin/public', () => ({ + ...jest.requireActual('@kbn/es-ui-shared-plugin/public'), + SectionLoading: ({ children }: { children: ReactNode }) => ( +
{children}
+ ), + GlobalFlyout: { + useGlobalFlyout: () => ({ + addContent: mockAddContent, + removeContent: mockRemoveContent, + }), + }, + WithPrivileges: ({ children }: { children: (result: PrivilegesCheckResult) => ReactNode }) => + children({ hasPrivileges: true, isLoading: false, privilegesMissing: {} }), +})); + +const mockServices = { + core: { + deprecations: { + getAllDeprecations: mockGetAllDeprecations, + resolveDeprecation: mockResolveDeprecation, + }, + }, + breadcrumbs: { + setBreadcrumbs: mockSetBreadcrumbs, + }, +}; + +jest.mock('../../app_context', () => ({ + ...jest.requireActual('../../app_context'), + useAppContext: () => ({ + services: mockServices, + }), +})); + +import { KibanaDeprecationsList } from './kibana_deprecations'; + +const renderWithProviders = (ui: React.ReactElement) => render({ui}); + +const kibanaDeprecations = [ + { + correctiveActions: { + manualSteps: ['Step 1'], + api: { method: 'POST' as const, path: '/test' }, + }, + domainId: 'test_domain_1', + level: 'critical', + title: 'Test deprecation title 1', + message: 'Test deprecation message 1', + deprecationType: 'config', + configPath: 'test', + }, + { + correctiveActions: { + manualSteps: ['Step 1', 'Step 2', 'Step 3'], + }, + domainId: 'test_domain_2', + level: 'warning', + title: 'Test deprecation title 2', + documentationUrl: 'https://', + message: 'Test deprecation message 2', + deprecationType: 'feature', + }, + { + correctiveActions: { + manualSteps: [], + }, + domainId: 'test_domain_3', + level: 'warning', + title: 'Test deprecation title 3', + message: 'Test deprecation message 3', + deprecationType: 'feature', + }, +]; + +const mockHistory = createMemoryHistory({ initialEntries: ['/kibana_deprecations'] }); + +describe('KibanaDeprecationsList', () => { + beforeEach(() => { + jest.clearAllMocks(); + mockGetAllDeprecations.mockResolvedValue(kibanaDeprecations); + }); + + describe('WHEN deprecations load successfully', () => { + it('SHOULD render deprecations table with correct items', async () => { + renderWithProviders( + + ); + + await waitFor(() => { + expect(screen.getByTestId('kibanaDeprecations')).toBeInTheDocument(); + }); + + expect(screen.getByTestId('kibanaDeprecationsTable')).toBeInTheDocument(); + expect(screen.getAllByTestId('row')).toHaveLength(kibanaDeprecations.length); + }); + + it('SHOULD show critical and warning deprecation counts', async () => { + renderWithProviders( + + ); + + await waitFor(() => { + expect(screen.getByTestId('kibanaDeprecations')).toBeInTheDocument(); + }); + + expect(screen.getByTestId('criticalDeprecationsCount')).toHaveTextContent('Critical: 1'); + expect(screen.getByTestId('warningDeprecationsCount')).toHaveTextContent('Warning: 2'); + }); + }); + + describe('WHEN deprecations service returns an error', () => { + it('SHOULD render the loading error prompt', async () => { + mockGetAllDeprecations.mockRejectedValue(new Error('Internal Server Error')); + + renderWithProviders( + + ); + + await waitFor(() => { + expect(screen.getByTestId('deprecationsPageLoadingError')).toBeInTheDocument(); + }); + + expect(screen.getByTestId('deprecationsPageLoadingError')).toHaveTextContent( + 'Could not retrieve Kibana deprecation issues' + ); + }); + }); + + describe('WHEN there are no deprecations', () => { + it('SHOULD render the no deprecations prompt', async () => { + mockGetAllDeprecations.mockResolvedValue([]); + + renderWithProviders( + + ); + + await waitFor(() => { + expect(screen.getByTestId('noDeprecationsPrompt')).toBeInTheDocument(); + }); + + expect(screen.getByTestId('noDeprecationsPrompt')).toHaveTextContent( + 'Your Kibana configuration is up to date' + ); + }); + }); + + describe('WHEN there are plugin fetch errors', () => { + it('SHOULD show the deprecation errors callout', async () => { + mockGetAllDeprecations.mockResolvedValue([ + ...kibanaDeprecations, + { + domainId: 'failed_plugin_id_1', + title: 'Failed to fetch deprecations for "failed_plugin_id"', + message: 'Failed to get deprecations info for plugin "failed_plugin_id".', + level: 'fetch_error', + correctiveActions: { + manualSteps: ['Check Kibana server logs for error message.'], + }, + }, + { + domainId: 'failed_plugin_id_1', + title: 'Failed to fetch deprecations for "failed_plugin_id"', + message: 'Failed to get deprecations info for plugin "failed_plugin_id".', + level: 'fetch_error', + correctiveActions: { + manualSteps: ['Check Kibana server logs for error message.'], + }, + }, + { + domainId: 'failed_plugin_id_2', + title: 'Failed to fetch deprecations for "failed_plugin_id"', + message: 'Failed to get deprecations info for plugin "failed_plugin_id".', + level: 'fetch_error', + correctiveActions: { + manualSteps: ['Check Kibana server logs for error message.'], + }, + }, + ]); + + renderWithProviders( + + ); + + await waitFor(() => { + expect(screen.getByTestId('kibanaDeprecationErrors')).toBeInTheDocument(); + }); + + expect(screen.getByTestId('kibanaDeprecationErrors')).toHaveTextContent( + 'Failed to get deprecation issues for these plugins: failed_plugin_id_1, failed_plugin_id_2.' + ); + }); + + it('SHOULD show missing privileges warning when hasPrivileges is false', async () => { + mockGetAllDeprecations.mockResolvedValue(kibanaDeprecations); + + renderWithProviders( + + ); + + await waitFor(() => { + expect(screen.getByTestId('kibanaDeprecationErrors')).toBeInTheDocument(); + }); + + expect(screen.getByTestId('kibanaDeprecationErrors')).toHaveTextContent( + 'Certain issues might be missing due to missing cluster privilege for: manage_security' + ); + }); + }); + + describe('WHEN refresh is triggered', () => { + it('SHOULD call getAllDeprecations again', async () => { + renderWithProviders( + + ); + + await waitFor(() => { + expect(screen.getByTestId('kibanaDeprecations')).toBeInTheDocument(); + }); + + expect(mockGetAllDeprecations).toHaveBeenCalledTimes(1); + + fireEvent.click(screen.getByTestId('refreshButton')); + + await waitFor(() => { + expect(mockGetAllDeprecations).toHaveBeenCalledTimes(2); + }); + }); + }); + + describe('WHEN a deprecation is opened and resolved', () => { + it('SHOULD add flyout content and resolve successfully', async () => { + mockResolveDeprecation.mockResolvedValue({ status: 'ok' }); + + renderWithProviders( + + ); + + await waitFor(() => { + expect(screen.getByTestId('kibanaDeprecations')).toBeInTheDocument(); + }); + + fireEvent.click(screen.getAllByTestId('row')[0]); + + await waitFor(() => { + expect(mockAddContent).toHaveBeenCalledTimes(1); + }); + + const flyoutConfig = mockAddContent.mock.calls[0][0]; + await act(async () => { + await flyoutConfig.props.resolveDeprecation(flyoutConfig.props.deprecation); + }); + + expect(mockResolveDeprecation).toHaveBeenCalledTimes(1); + expect(mockResolveDeprecation).toHaveBeenCalledWith(flyoutConfig.props.deprecation); + + await waitFor(() => { + expect(mockRemoveContent).toHaveBeenCalledTimes(1); + }); + + fireEvent.click(screen.getAllByTestId('row')[0]); + + await waitFor(() => { + expect(mockAddContent).toHaveBeenCalledTimes(2); + }); + + const reopenedFlyoutConfig = mockAddContent.mock.calls[1][0]; + expect(reopenedFlyoutConfig.props.deprecationResolutionState).toEqual( + expect.objectContaining({ resolveDeprecationStatus: 'ok' }) + ); + }); + + it('SHOULD store failure state and expose it when reopened', async () => { + mockResolveDeprecation.mockResolvedValue({ status: 'fail', reason: 'resolve failed' }); + + renderWithProviders( + + ); + + await waitFor(() => { + expect(screen.getByTestId('kibanaDeprecations')).toBeInTheDocument(); + }); + + fireEvent.click(screen.getAllByTestId('row')[0]); + + await waitFor(() => { + expect(mockAddContent).toHaveBeenCalledTimes(1); + }); + + const firstFlyoutConfig = mockAddContent.mock.calls[0][0]; + await act(async () => { + await firstFlyoutConfig.props.resolveDeprecation(firstFlyoutConfig.props.deprecation); + }); + + await waitFor(() => { + expect(mockRemoveContent).toHaveBeenCalledTimes(1); + }); + + fireEvent.click(screen.getAllByTestId('row')[0]); + + await waitFor(() => { + expect(mockAddContent).toHaveBeenCalledTimes(2); + }); + + const secondFlyoutConfig = mockAddContent.mock.calls[1][0]; + expect(secondFlyoutConfig.props.deprecationResolutionState).toEqual( + expect.objectContaining({ + resolveDeprecationStatus: 'fail', + resolveDeprecationError: 'resolve failed', + }) + ); + }); + }); +}); diff --git a/x-pack/platform/plugins/private/upgrade_assistant/public/application/components/kibana_deprecations/kibana_deprecations.tsx b/x-pack/platform/plugins/private/upgrade_assistant/public/application/components/kibana_deprecations/kibana_deprecations.tsx index 94e714ec6eacd..9cbb462527509 100644 --- a/x-pack/platform/plugins/private/upgrade_assistant/public/application/components/kibana_deprecations/kibana_deprecations.tsx +++ b/x-pack/platform/plugins/private/upgrade_assistant/public/application/components/kibana_deprecations/kibana_deprecations.tsx @@ -15,8 +15,12 @@ import { METRIC_TYPE } from '@kbn/analytics'; import { FormattedMessage } from '@kbn/i18n-react'; import type { DomainDeprecationDetails } from '@kbn/core/public'; -import type { MissingPrivileges } from '../../../shared_imports'; -import { WithPrivileges, SectionLoading, GlobalFlyout } from '../../../shared_imports'; +import { + type MissingPrivileges, + WithPrivileges, + SectionLoading, + GlobalFlyout, +} from '@kbn/es-ui-shared-plugin/public'; import { APP_LOGS_COUNT_CLUSTER_PRIVILEGES } from '../../../../common/constants'; import { useAppContext } from '../../app_context'; import { uiMetricService, UIM_KIBANA_DEPRECATIONS_PAGE_LOAD } from '../../lib/ui_metric'; diff --git a/x-pack/platform/plugins/private/upgrade_assistant/public/application/components/kibana_deprecations/kibana_deprecations_table.test.tsx b/x-pack/platform/plugins/private/upgrade_assistant/public/application/components/kibana_deprecations/kibana_deprecations_table.test.tsx new file mode 100644 index 0000000000000..d48b6615e5f46 --- /dev/null +++ b/x-pack/platform/plugins/private/upgrade_assistant/public/application/components/kibana_deprecations/kibana_deprecations_table.test.tsx @@ -0,0 +1,207 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; +import { render, screen, fireEvent, waitFor, within } from '@testing-library/react'; +import '@testing-library/jest-dom'; +import { I18nProvider } from '@kbn/i18n-react'; + +import type { KibanaDeprecationDetails } from './kibana_deprecations'; +import { KibanaDeprecationsTable } from './kibana_deprecations_table'; + +const renderWithProviders = (ui: React.ReactElement) => render({ui}); + +interface ConfigDeprecationOverrides + extends Partial> { + configPath: string; +} + +const createFeatureDeprecation = ( + overrides: Partial< + Omit + > = {} +): KibanaDeprecationDetails => ({ + id: 'test-id', + domainId: 'test_domain', + level: 'warning', + title: 'Test deprecation', + message: 'Test message', + correctiveActions: { manualSteps: ['Step 1'] }, + ...overrides, + deprecationType: 'feature', + filterType: 'feature', +}); + +const createConfigDeprecation = ({ + configPath, + ...overrides +}: ConfigDeprecationOverrides): KibanaDeprecationDetails => ({ + id: 'test-id', + domainId: 'test_domain', + level: 'warning', + title: 'Test deprecation', + message: 'Test message', + correctiveActions: { manualSteps: ['Step 1'] }, + ...overrides, + deprecationType: 'config', + filterType: 'config', + configPath, +}); + +const mockDeprecations: KibanaDeprecationDetails[] = [ + createConfigDeprecation({ + id: 'dep-1', + domainId: 'test_domain_1', + level: 'critical', + title: 'Critical config deprecation', + configPath: 'test', + correctiveActions: { + manualSteps: ['Step 1'], + api: { method: 'POST' as const, path: '/test' }, + }, + }), + createFeatureDeprecation({ + id: 'dep-2', + domainId: 'test_domain_2', + level: 'warning', + title: 'Warning feature deprecation', + }), + createFeatureDeprecation({ + id: 'dep-3', + domainId: 'test_domain_3', + level: 'warning', + title: 'Another warning feature deprecation', + }), +]; + +const mockReload = jest.fn(); +const mockToggleFlyout = jest.fn(); + +describe('KibanaDeprecationsTable', () => { + beforeEach(() => { + jest.clearAllMocks(); + }); + + it('SHOULD render all deprecations as rows', () => { + renderWithProviders( + + ); + + expect(screen.getByTestId('kibanaDeprecationsTable')).toBeInTheDocument(); + expect(screen.getAllByTestId('row')).toHaveLength(mockDeprecations.length); + }); + + it('SHOULD call reload when refresh button is clicked', () => { + renderWithProviders( + + ); + + fireEvent.click(screen.getByTestId('refreshButton')); + expect(mockReload).toHaveBeenCalledTimes(1); + }); + + it('SHOULD call toggleFlyout when deprecation link is clicked', () => { + renderWithProviders( + + ); + + fireEvent.click(screen.getAllByTestId('deprecationDetailsLink')[0]); + expect(mockToggleFlyout).toHaveBeenCalledWith(mockDeprecations[0]); + }); + + describe('Search bar', () => { + it('SHOULD filter by "critical" status', async () => { + renderWithProviders( + + ); + + fireEvent.click(screen.getByRole('button', { name: 'Status Selection' })); + await waitFor(() => { + const option = document.body.querySelector( + '.euiSelectableListItem[title="Critical"]' + ); + expect(option).not.toBeNull(); + option!.click(); + }); + + await waitFor(() => { + expect( + within(screen.getByTestId('kibanaDeprecationsTable')).getAllByTestId('row') + ).toHaveLength(1); + }); + + // Clear (restore all rows) + fireEvent.click(screen.getByTestId('clearSearchButton')); + + await waitFor(() => { + expect( + within(screen.getByTestId('kibanaDeprecationsTable')).getAllByTestId('row') + ).toHaveLength(mockDeprecations.length); + }); + }); + + it('SHOULD filter by type', async () => { + renderWithProviders( + + ); + + fireEvent.click(screen.getByRole('button', { name: 'Type Selection' })); + await waitFor(() => { + const option = document.body.querySelector( + '.euiSelectableListItem[title="Config"]' + ); + expect(option).not.toBeNull(); + option!.click(); + }); + + await waitFor(() => { + expect( + within(screen.getByTestId('kibanaDeprecationsTable')).getAllByTestId('row') + ).toHaveLength(1); + }); + }); + }); + + it('SHOULD render empty table when no deprecations', () => { + renderWithProviders( + + ); + + expect(screen.getByTestId('kibanaDeprecationsTable')).toBeInTheDocument(); + expect(screen.queryAllByTestId('row')).toHaveLength(0); + }); +}); From d7db7f68192b845744597a2ea43ab1d223a8e0e1 Mon Sep 17 00:00:00 2001 From: Karen Grigoryan Date: Sun, 22 Mar 2026 17:05:06 +0100 Subject: [PATCH 2/4] [Upgrade Assistant] Speed up Kibana deprecations table filter test Co-authored-by: Cursor --- .../kibana_deprecations_table.test.tsx | 22 +++++++++++-------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/x-pack/platform/plugins/private/upgrade_assistant/public/application/components/kibana_deprecations/kibana_deprecations_table.test.tsx b/x-pack/platform/plugins/private/upgrade_assistant/public/application/components/kibana_deprecations/kibana_deprecations_table.test.tsx index d48b6615e5f46..779a53e9aea06 100644 --- a/x-pack/platform/plugins/private/upgrade_assistant/public/application/components/kibana_deprecations/kibana_deprecations_table.test.tsx +++ b/x-pack/platform/plugins/private/upgrade_assistant/public/application/components/kibana_deprecations/kibana_deprecations_table.test.tsx @@ -70,12 +70,6 @@ const mockDeprecations: KibanaDeprecationDetails[] = [ level: 'warning', title: 'Warning feature deprecation', }), - createFeatureDeprecation({ - id: 'dep-3', - domainId: 'test_domain_3', - level: 'warning', - title: 'Another warning feature deprecation', - }), ]; const mockReload = jest.fn(); @@ -139,7 +133,10 @@ describe('KibanaDeprecationsTable', () => { /> ); - fireEvent.click(screen.getByRole('button', { name: 'Status Selection' })); + const filterButtons = + document.body.querySelectorAll('button.euiFilterButton'); + expect(filterButtons.length).toBeGreaterThanOrEqual(2); + fireEvent.click(filterButtons[0]); await waitFor(() => { const option = document.body.querySelector( '.euiSelectableListItem[title="Critical"]' @@ -155,7 +152,11 @@ describe('KibanaDeprecationsTable', () => { }); // Clear (restore all rows) - fireEvent.click(screen.getByTestId('clearSearchButton')); + const clearButton = document.body.querySelector( + '[data-test-subj="clearSearchButton"]' + ); + expect(clearButton).not.toBeNull(); + fireEvent.click(clearButton!); await waitFor(() => { expect( @@ -174,7 +175,10 @@ describe('KibanaDeprecationsTable', () => { /> ); - fireEvent.click(screen.getByRole('button', { name: 'Type Selection' })); + const filterButtons = + document.body.querySelectorAll('button.euiFilterButton'); + expect(filterButtons.length).toBeGreaterThanOrEqual(2); + fireEvent.click(filterButtons[1]); await waitFor(() => { const option = document.body.querySelector( '.euiSelectableListItem[title="Config"]' From 94172dfae4f40ee2ee8164728e4b51604306d01c Mon Sep 17 00:00:00 2001 From: Karen Grigoryan Date: Thu, 26 Mar 2026 12:53:31 +0100 Subject: [PATCH 3/4] [Upgrade Assistant] Stabilize filter button selectors and cover in-progress resolve Co-authored-by: Cursor --- .../deprecation_details_flyout.test.tsx | 28 +++++++++++++++++++ .../kibana_deprecations_table.test.tsx | 18 ++++++------ 2 files changed, 38 insertions(+), 8 deletions(-) diff --git a/x-pack/platform/plugins/private/upgrade_assistant/public/application/components/kibana_deprecations/deprecation_details_flyout.test.tsx b/x-pack/platform/plugins/private/upgrade_assistant/public/application/components/kibana_deprecations/deprecation_details_flyout.test.tsx index eef3a84a21e30..53d0967a17a93 100644 --- a/x-pack/platform/plugins/private/upgrade_assistant/public/application/components/kibana_deprecations/deprecation_details_flyout.test.tsx +++ b/x-pack/platform/plugins/private/upgrade_assistant/public/application/components/kibana_deprecations/deprecation_details_flyout.test.tsx @@ -157,6 +157,34 @@ describe('DeprecationDetailsFlyout', () => { expect(screen.getByTestId('resolveButton')).toBeInTheDocument(); }); + it('SHOULD show loading/disabled resolve button when resolution is in progress', () => { + const deprecation = createFeatureDeprecation({ + id: 'dep-in-progress', + level: 'critical', + correctiveActions: { + manualSteps: ['Step 1'], + api: { method: 'POST' as const, path: '/test' }, + }, + }); + + const resolutionState: DeprecationResolutionState = { + id: 'dep-in-progress', + resolveDeprecationStatus: 'in_progress', + }; + + renderWithProviders( + + ); + + expect(screen.getByTestId('resolveButton')).toBeDisabled(); + expect(screen.getByTestId('resolveButton')).toHaveTextContent('Resolution in progress'); + }); + it('SHOULD call resolveDeprecation when resolve button is clicked', () => { const deprecation = createFeatureDeprecation({ id: 'dep-resolve', diff --git a/x-pack/platform/plugins/private/upgrade_assistant/public/application/components/kibana_deprecations/kibana_deprecations_table.test.tsx b/x-pack/platform/plugins/private/upgrade_assistant/public/application/components/kibana_deprecations/kibana_deprecations_table.test.tsx index 779a53e9aea06..9f0ab01ac575c 100644 --- a/x-pack/platform/plugins/private/upgrade_assistant/public/application/components/kibana_deprecations/kibana_deprecations_table.test.tsx +++ b/x-pack/platform/plugins/private/upgrade_assistant/public/application/components/kibana_deprecations/kibana_deprecations_table.test.tsx @@ -133,10 +133,11 @@ describe('KibanaDeprecationsTable', () => { /> ); - const filterButtons = - document.body.querySelectorAll('button.euiFilterButton'); - expect(filterButtons.length).toBeGreaterThanOrEqual(2); - fireEvent.click(filterButtons[0]); + const statusButton = document.body.querySelector( + 'button[aria-label="Status Selection"]' + ); + expect(statusButton).not.toBeNull(); + fireEvent.click(statusButton!); await waitFor(() => { const option = document.body.querySelector( '.euiSelectableListItem[title="Critical"]' @@ -175,10 +176,11 @@ describe('KibanaDeprecationsTable', () => { /> ); - const filterButtons = - document.body.querySelectorAll('button.euiFilterButton'); - expect(filterButtons.length).toBeGreaterThanOrEqual(2); - fireEvent.click(filterButtons[1]); + const typeButton = document.body.querySelector( + 'button[aria-label="Type Selection"]' + ); + expect(typeButton).not.toBeNull(); + fireEvent.click(typeButton!); await waitFor(() => { const option = document.body.querySelector( '.euiSelectableListItem[title="Config"]' From 6ea32a470836d4df3df9770b283b69210101b000 Mon Sep 17 00:00:00 2001 From: Karen Grigoryan Date: Thu, 26 Mar 2026 12:56:05 +0100 Subject: [PATCH 4/4] [Upgrade Assistant] Use getByLabelText for deprecations filter buttons Co-authored-by: Cursor --- .../kibana_deprecations_table.test.tsx | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/x-pack/platform/plugins/private/upgrade_assistant/public/application/components/kibana_deprecations/kibana_deprecations_table.test.tsx b/x-pack/platform/plugins/private/upgrade_assistant/public/application/components/kibana_deprecations/kibana_deprecations_table.test.tsx index 9f0ab01ac575c..ce57d9fee010e 100644 --- a/x-pack/platform/plugins/private/upgrade_assistant/public/application/components/kibana_deprecations/kibana_deprecations_table.test.tsx +++ b/x-pack/platform/plugins/private/upgrade_assistant/public/application/components/kibana_deprecations/kibana_deprecations_table.test.tsx @@ -133,11 +133,7 @@ describe('KibanaDeprecationsTable', () => { /> ); - const statusButton = document.body.querySelector( - 'button[aria-label="Status Selection"]' - ); - expect(statusButton).not.toBeNull(); - fireEvent.click(statusButton!); + fireEvent.click(screen.getByLabelText('Status Selection')); await waitFor(() => { const option = document.body.querySelector( '.euiSelectableListItem[title="Critical"]' @@ -176,11 +172,7 @@ describe('KibanaDeprecationsTable', () => { /> ); - const typeButton = document.body.querySelector( - 'button[aria-label="Type Selection"]' - ); - expect(typeButton).not.toBeNull(); - fireEvent.click(typeButton!); + fireEvent.click(screen.getByLabelText('Type Selection')); await waitFor(() => { const option = document.body.querySelector( '.euiSelectableListItem[title="Config"]'