Skip to content

Commit

Permalink
[Security] Remove usage of deprecated React rendering utilities (#180517
Browse files Browse the repository at this point in the history
)

## Summary

Partially addresses elastic/kibana-team#805

Follows #180003

These changes come up from searching in the code and finding where
certain kinds of deprecated AppEx-SharedUX modules are imported.
**Reviewers: Please interact with critical paths through the UI
components touched in this PR, ESPECIALLY in terms of testing dark mode
and i18n.**

This focuses on code within Security.

<img width="1107" alt="image"
src="https://github.com/elastic/kibana/assets/908371/c0d2ce08-ac35-45a7-8192-0b2256fceb0e">

Note: this also makes inclusion of `i18n` and `analytics` dependencies
consistent. Analytics is an optional dependency for the SharedUX
modules, which wrap `KibanaErrorBoundaryProvider` and is designed to
capture telemetry about errors that are caught in the error boundary.

### Checklist

Delete any items that are not applicable to this PR.

- [x] [Unit or functional
tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)
were updated or added to match the most common scenarios
- [ ] This renders correctly on smaller devices using a responsive
layout. (You can test this [in your
browser](https://www.browserstack.com/guide/responsive-testing-on-local-server))
- [ ] This was checked for [cross-browser
compatibility](https://www.elastic.co/support/matrix#matrix_browsers)

---------

Co-authored-by: kibanamachine <[email protected]>
  • Loading branch information
tsullivan and kibanamachine authored Apr 18, 2024
1 parent 4127163 commit ef5af17
Show file tree
Hide file tree
Showing 46 changed files with 435 additions and 450 deletions.
4 changes: 2 additions & 2 deletions packages/kbn-user-profile-components/src/services.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,10 @@ export interface UserProfilesKibanaDependencies {
userProfiles: UserProfileAPIClient;
};
/**
* Handler from the '@kbn/kibana-react-plugin/public' Plugin
* Handler from the '@kbn/react-kibana-mount' Package
*
* ```
* import { toMountPoint } from '@kbn/kibana-react-plugin/public';
* import { toMountPoint } from '@kbn/react-kibana-mount';
* ```
*/
toMountPoint: typeof toMountPoint;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
import { fireEvent, render, waitFor } from '@testing-library/react';
import React from 'react';

import { coreMock, themeServiceMock } from '@kbn/core/public/mocks';
import { coreMock } from '@kbn/core/public/mocks';

import { ClusterAddressForm } from './cluster_address_form';
import { Providers } from './plugin';
Expand All @@ -21,16 +21,14 @@ jest.mock('@elastic/eui/lib/services/accessibility/html_id_generator', () => ({
describe('ClusterAddressForm', () => {
jest.setTimeout(20_000);

const theme$ = themeServiceMock.createTheme$();

it('calls enrollment API when submitting form', async () => {
const coreStart = coreMock.createStart();
coreStart.http.post.mockResolvedValue({});

const onSuccess = jest.fn();

const { findByRole, findByLabelText } = render(
<Providers services={coreStart} theme$={theme$}>
<Providers services={coreStart}>
<ClusterAddressForm onSuccess={onSuccess} />
</Providers>
);
Expand All @@ -54,7 +52,7 @@ describe('ClusterAddressForm', () => {
const onSuccess = jest.fn();

const { findAllByText, findByRole, findByLabelText } = render(
<Providers services={coreStart} theme$={theme$}>
<Providers services={coreStart}>
<ClusterAddressForm onSuccess={onSuccess} />
</Providers>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
import { fireEvent, render, waitFor } from '@testing-library/react';
import React from 'react';

import { coreMock, themeServiceMock } from '@kbn/core/public/mocks';
import { coreMock } from '@kbn/core/public/mocks';

import { ClusterConfigurationForm } from './cluster_configuration_form';
import { Providers } from './plugin';
Expand All @@ -21,16 +21,14 @@ jest.mock('@elastic/eui/lib/services/accessibility/html_id_generator', () => ({
describe('ClusterConfigurationForm', () => {
jest.setTimeout(20_000);

const theme$ = themeServiceMock.createTheme$();

it('calls enrollment API for https addresses when submitting form', async () => {
const coreStart = coreMock.createStart();
coreStart.http.post.mockResolvedValue({});

const onSuccess = jest.fn();

const { findByRole, findByLabelText } = render(
<Providers services={coreStart} theme$={theme$}>
<Providers services={coreStart}>
<ClusterConfigurationForm
host="https://localhost:9200"
authRequired
Expand Down Expand Up @@ -80,7 +78,7 @@ describe('ClusterConfigurationForm', () => {
const onSuccess = jest.fn();

const { findByRole } = render(
<Providers services={coreStart} theme$={theme$}>
<Providers services={coreStart}>
<ClusterConfigurationForm
host="http://localhost:9200"
authRequired={false}
Expand Down Expand Up @@ -109,7 +107,7 @@ describe('ClusterConfigurationForm', () => {
const onSuccess = jest.fn();

const { findAllByText, findByRole, findByLabelText } = render(
<Providers services={coreStart} theme$={theme$}>
<Providers services={coreStart}>
<ClusterConfigurationForm
host="https://localhost:9200"
authRequired
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
import { fireEvent, render, waitFor } from '@testing-library/react';
import React from 'react';

import { coreMock, themeServiceMock } from '@kbn/core/public/mocks';
import { coreMock } from '@kbn/core/public/mocks';

import { decodeEnrollmentToken, EnrollmentTokenForm } from './enrollment_token_form';
import { Providers } from './plugin';
Expand All @@ -29,16 +29,14 @@ const token: EnrollmentToken = {
describe('EnrollmentTokenForm', () => {
jest.setTimeout(20_000);

const theme$ = themeServiceMock.createTheme$();

it('calls enrollment API when submitting form', async () => {
const coreStart = coreMock.createStart();
coreStart.http.post.mockResolvedValue({});

const onSuccess = jest.fn();

const { findByRole, findByLabelText } = render(
<Providers services={coreStart} theme$={theme$}>
<Providers services={coreStart}>
<EnrollmentTokenForm onSuccess={onSuccess} />
</Providers>
);
Expand All @@ -64,7 +62,7 @@ describe('EnrollmentTokenForm', () => {
const onSuccess = jest.fn();

const { findAllByText, findByRole, findByLabelText } = render(
<Providers services={coreStart} theme$={theme$}>
<Providers services={coreStart}>
<EnrollmentTokenForm onSuccess={onSuccess} />
</Providers>
);
Expand Down
26 changes: 10 additions & 16 deletions src/plugins/interactive_setup/public/plugin.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,11 @@
import type { FunctionComponent } from 'react';
import React from 'react';
import ReactDOM from 'react-dom';
import type { Observable } from 'rxjs';

import type { CoreSetup, CoreStart, CoreTheme, Plugin } from '@kbn/core/public';
import { I18nProvider } from '@kbn/i18n-react';
import type { CoreSetup, CoreStart, Plugin } from '@kbn/core/public';
import { KibanaRenderContextProvider } from '@kbn/react-kibana-context-render';

import { App } from './app';
import { KibanaThemeProvider } from './theme'; // TODO: replace this with the one exported from `kibana_react` after https://github.com/elastic/kibana/issues/119204 is implemented.
import { KibanaProvider } from './use_kibana';
import { VerificationProvider } from './use_verification';

Expand All @@ -26,7 +24,7 @@ export class InteractiveSetupPlugin implements Plugin<void, void, {}, {}> {
title: 'Configure Elastic to get started',
appRoute: '/',
chromeless: true,
mount: async ({ element, theme$ }) => {
mount: async ({ element }) => {
const url = new URL(window.location.href);
const defaultCode = url.searchParams.get('code') || undefined;
const onSuccess = () => {
Expand All @@ -36,7 +34,7 @@ export class InteractiveSetupPlugin implements Plugin<void, void, {}, {}> {
const [services] = await core.getStartServices();

ReactDOM.render(
<Providers defaultCode={defaultCode} services={services} theme$={theme$}>
<Providers defaultCode={defaultCode} services={services}>
<App onSuccess={onSuccess} />
</Providers>,
element
Expand All @@ -46,26 +44,22 @@ export class InteractiveSetupPlugin implements Plugin<void, void, {}, {}> {
});
}

public start(core: CoreStart) {}
public start(_core: CoreStart) {}
}

export interface ProvidersProps {
services: CoreStart;
theme$: Observable<CoreTheme>;
defaultCode?: string;
}

export const Providers: FunctionComponent<ProvidersProps> = ({
defaultCode,
services,
theme$,
children,
}) => (
<I18nProvider>
<KibanaThemeProvider theme$={theme$}>
<KibanaProvider services={services}>
<VerificationProvider defaultCode={defaultCode}>{children}</VerificationProvider>
</KibanaProvider>
</KibanaThemeProvider>
</I18nProvider>
<KibanaRenderContextProvider {...services}>
<KibanaProvider services={services}>
<VerificationProvider defaultCode={defaultCode}>{children}</VerificationProvider>
</KibanaProvider>
</KibanaRenderContextProvider>
);
24 changes: 0 additions & 24 deletions src/plugins/interactive_setup/public/theme/index.tsx

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
import { fireEvent, render, waitFor } from '@testing-library/react';
import React from 'react';

import { coreMock, themeServiceMock } from '@kbn/core/public/mocks';
import { coreMock } from '@kbn/core/public/mocks';

import { Providers } from './plugin';
import { VerificationCodeForm } from './verification_code_form';
Expand All @@ -21,16 +21,14 @@ jest.mock('@elastic/eui/lib/services/accessibility/html_id_generator', () => ({
describe('VerificationCodeForm', () => {
jest.setTimeout(20_000);

const theme$ = themeServiceMock.createTheme$();

it('calls enrollment API when submitting form', async () => {
const coreStart = coreMock.createStart();
coreStart.http.post.mockResolvedValue({});

const onSuccess = jest.fn();

const { findByRole, findByLabelText } = render(
<Providers services={coreStart} theme$={theme$}>
<Providers services={coreStart}>
<VerificationCodeForm onSuccess={onSuccess} />
</Providers>
);
Expand Down Expand Up @@ -67,7 +65,7 @@ describe('VerificationCodeForm', () => {
const onSuccess = jest.fn();

const { findAllByText, findByRole, findByLabelText } = render(
<Providers services={coreStart} theme$={theme$}>
<Providers services={coreStart}>
<VerificationCodeForm onSuccess={onSuccess} />
</Providers>
);
Expand Down
3 changes: 1 addition & 2 deletions src/plugins/interactive_setup/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,8 @@
"@kbn/utils",
"@kbn/core-logging-server-mocks",
"@kbn/core-preboot-server",
"@kbn/react-kibana-context-theme",
"@kbn/core-theme-browser",
"@kbn/security-hardening",
"@kbn/react-kibana-context-render",
],
"exclude": [
"target/**/*",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,8 @@ import type {
StartServicesAccessor,
} from '@kbn/core/public';
import { i18n } from '@kbn/i18n';
import { I18nProvider } from '@kbn/i18n-react';
import { KibanaContextProvider } from '@kbn/kibana-react-plugin/public';
import { KibanaThemeProvider } from '@kbn/react-kibana-context-theme';
import { KibanaRenderContextProvider } from '@kbn/react-kibana-context-render';
import { toMountPoint } from '@kbn/react-kibana-mount';
import type { AuthenticationServiceSetup } from '@kbn/security-plugin-types-public';
import { Router } from '@kbn/shared-ux-router';
Expand Down Expand Up @@ -87,27 +86,25 @@ export const Providers: FunctionComponent<ProvidersProps> = ({
onChange,
children,
}) => (
<KibanaContextProvider services={services}>
<AuthenticationProvider authc={authc}>
<SecurityApiClientsProvider {...securityApiClients}>
<I18nProvider>
<KibanaThemeProvider theme={services.theme}>
<Router history={history}>
<BreadcrumbsProvider onChange={onChange}>
<UserProfilesKibanaProvider
core={services}
security={{
userProfiles: securityApiClients.userProfiles,
}}
toMountPoint={toMountPoint}
>
{children}
</UserProfilesKibanaProvider>
</BreadcrumbsProvider>
</Router>
</KibanaThemeProvider>
</I18nProvider>
</SecurityApiClientsProvider>
</AuthenticationProvider>
</KibanaContextProvider>
<KibanaRenderContextProvider {...services}>
<KibanaContextProvider services={services}>
<AuthenticationProvider authc={authc}>
<SecurityApiClientsProvider {...securityApiClients}>
<Router history={history}>
<BreadcrumbsProvider onChange={onChange}>
<UserProfilesKibanaProvider
core={services}
security={{
userProfiles: securityApiClients.userProfiles,
}}
toMountPoint={toMountPoint}
>
{children}
</UserProfilesKibanaProvider>
</BreadcrumbsProvider>
</Router>
</SecurityApiClientsProvider>
</AuthenticationProvider>
</KibanaContextProvider>
</KibanaRenderContextProvider>
);
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,8 @@ describe('accessAgreementApp', () => {
const mockRenderApp = jest.requireMock('./access_agreement_page').renderAccessAgreementPage;
expect(mockRenderApp).toHaveBeenCalledTimes(1);
expect(mockRenderApp).toHaveBeenCalledWith(
coreStartMock.i18n,
{ element: appMountParams.element, theme$: appMountParams.theme$ },
coreStartMock,
{ element: appMountParams.element },
{
http: coreStartMock.http,
notifications: coreStartMock.notifications,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,14 @@ export const accessAgreementApp = Object.freeze({
}),
chromeless: true,
appRoute: '/security/access_agreement',
async mount({ element, theme$ }: AppMountParameters) {
async mount({ element }: AppMountParameters) {
const [[coreStart], { renderAccessAgreementPage }] = await Promise.all([
getStartServices(),
import('./access_agreement_page'),
]);
return renderAccessAgreementPage(
coreStart.i18n,
{ element, theme$ },
coreStart,
{ element },
{
http: coreStart.http,
notifications: coreStart.notifications,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,15 +23,15 @@ import ReactMarkdown from 'react-markdown';

import type {
AppMountParameters,
CoreStart,
FatalErrorsStart,
HttpStart,
NotificationsStart,
} from '@kbn/core/public';
import { i18n } from '@kbn/i18n';
import { FormattedMessage } from '@kbn/i18n-react';
import { KibanaThemeProvider } from '@kbn/kibana-react-plugin/public';
import { KibanaRenderContextProvider } from '@kbn/react-kibana-context-render';

import type { StartServices } from '../..';
import { parseNext } from '../../../common/parse_next';
import { AuthenticationStatePage } from '../components';

Expand Down Expand Up @@ -128,16 +128,14 @@ export function AccessAgreementPage({ http, fatalErrors, notifications }: Props)
}

export function renderAccessAgreementPage(
i18nStart: CoreStart['i18n'],
{ element, theme$ }: Pick<AppMountParameters, 'element' | 'theme$'>,
services: StartServices,
{ element }: Pick<AppMountParameters, 'element'>,
props: Props
) {
ReactDOM.render(
<i18nStart.Context>
<KibanaThemeProvider theme$={theme$}>
<AccessAgreementPage {...props} />
</KibanaThemeProvider>
</i18nStart.Context>,
<KibanaRenderContextProvider {...services}>
<AccessAgreementPage {...props} />
</KibanaRenderContextProvider>,
element
);

Expand Down
Loading

0 comments on commit ef5af17

Please sign in to comment.