Skip to content

Commit

Permalink
Review#1: use useKibana hook.
Browse files Browse the repository at this point in the history
  • Loading branch information
azasypkin committed Jan 14, 2021
1 parent 6638f1b commit d2952c3
Show file tree
Hide file tree
Showing 16 changed files with 249 additions and 390 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { ReactWrapper } from 'enzyme';
import { EuiCallOut } from '@elastic/eui';
import type { PublicMethodsOf } from '@kbn/utility-types';

import { KibanaContextProvider } from '../../../../../../../src/plugins/kibana_react/public';
import { NotEnabled } from './not_enabled';
import { PermissionDenied } from './permission_denied';
import { APIKeysAPIClient } from '../api_keys_api_client';
Expand Down Expand Up @@ -65,21 +66,17 @@ describe('APIKeysGridPage', () => {
});

const coreStart = coreMock.createStart();

const getViewProperties = () => {
const renderView = () => {
const { docLinks, notifications, application } = coreStart;
return {
docLinks,
navigateToApp: application.navigateToApp,
notifications,
apiKeysAPIClient: apiClientMock,
};
return mountWithIntl(
<KibanaContextProvider services={{ application, docLinks }}>
<APIKeysGridPage apiKeysAPIClient={apiClientMock} notifications={notifications} />
</KibanaContextProvider>
);
};

it('renders a loading state when fetching API keys', async () => {
const wrapper = mountWithIntl(<APIKeysGridPage {...getViewProperties()} />);

expect(wrapper.find('[data-test-subj="apiKeysSectionLoading"]')).toHaveLength(1);
expect(renderView().find('[data-test-subj="apiKeysSectionLoading"]')).toHaveLength(1);
});

it('renders a callout when API keys are not enabled', async () => {
Expand All @@ -89,8 +86,7 @@ describe('APIKeysGridPage', () => {
areApiKeysEnabled: false,
});

const wrapper = mountWithIntl(<APIKeysGridPage {...getViewProperties()} />);

const wrapper = renderView();
await waitForRender(wrapper, (updatedWrapper) => {
return updatedWrapper.find(NotEnabled).length > 0;
});
Expand All @@ -105,8 +101,7 @@ describe('APIKeysGridPage', () => {
areApiKeysEnabled: true,
});

const wrapper = mountWithIntl(<APIKeysGridPage {...getViewProperties()} />);

const wrapper = renderView();
await waitForRender(wrapper, (updatedWrapper) => {
return updatedWrapper.find(PermissionDenied).length > 0;
});
Expand All @@ -117,8 +112,7 @@ describe('APIKeysGridPage', () => {
it('renders error callout if error fetching API keys', async () => {
apiClientMock.getApiKeys.mockRejectedValue(mock500());

const wrapper = mountWithIntl(<APIKeysGridPage {...getViewProperties()} />);

const wrapper = renderView();
await waitForRender(wrapper, (updatedWrapper) => {
return updatedWrapper.find(EuiCallOut).length > 0;
});
Expand All @@ -129,7 +123,7 @@ describe('APIKeysGridPage', () => {
describe('Admin view', () => {
let wrapper: ReactWrapper<any>;
beforeEach(() => {
wrapper = mountWithIntl(<APIKeysGridPage {...getViewProperties()} />);
wrapper = renderView();
});

it('renders a callout indicating the user is an administrator', async () => {
Expand Down Expand Up @@ -164,7 +158,7 @@ describe('APIKeysGridPage', () => {
areApiKeysEnabled: true,
});

wrapper = mountWithIntl(<APIKeysGridPage {...getViewProperties()} />);
wrapper = renderView();
});

it('does NOT render a callout indicating the user is an administrator', async () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ import { i18n } from '@kbn/i18n';
import { FormattedMessage } from '@kbn/i18n/react';
import type { PublicMethodsOf } from '@kbn/utility-types';
import moment from 'moment-timezone';
import type { ApplicationStart, DocLinksStart, NotificationsStart } from 'src/core/public';
import type { NotificationsStart } from 'src/core/public';
import { SectionLoading } from '../../../../../../../src/plugins/es_ui_shared/public';
import { ApiKey, ApiKeyToInvalidate } from '../../../../common/model';
import { APIKeysAPIClient } from '../api_keys_api_client';
Expand All @@ -39,9 +39,7 @@ import { InvalidateProvider } from './invalidate_provider';

interface Props {
notifications: NotificationsStart;
docLinks: DocLinksStart;
apiKeysAPIClient: PublicMethodsOf<APIKeysAPIClient>;
navigateToApp: ApplicationStart['navigateToApp'];
}

interface State {
Expand Down Expand Up @@ -131,19 +129,15 @@ export class APIKeysGridPage extends Component<Props, State> {
if (!areApiKeysEnabled) {
return (
<EuiPageContent>
<NotEnabled docLinks={this.props.docLinks} />
<NotEnabled />
</EuiPageContent>
);
}

if (!isLoadingTable && apiKeys && apiKeys.length === 0) {
return (
<EuiPageContent>
<EmptyPrompt
isAdmin={isAdmin}
docLinks={this.props.docLinks}
navigateToApp={this.props.navigateToApp}
/>
<EmptyPrompt isAdmin={isAdmin} />
</EuiPageContent>
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,71 +5,70 @@
*/

import React, { Fragment } from 'react';
import type { ApplicationStart, DocLinksStart } from 'kibana/public';

import { EuiEmptyPrompt, EuiButton, EuiLink } from '@elastic/eui';
import { FormattedMessage } from '@kbn/i18n/react';
import { useKibana } from '../../../../../../../../src/plugins/kibana_react/public';

interface Props {
isAdmin: boolean;
docLinks: DocLinksStart;
navigateToApp: ApplicationStart['navigateToApp'];
}

export const EmptyPrompt: React.FunctionComponent<Props> = ({
isAdmin,
docLinks,
navigateToApp,
}) => (
<EuiEmptyPrompt
iconType="managementApp"
title={
<h1 data-test-subj="noApiKeysHeader">
{isAdmin ? (
export const EmptyPrompt: React.FunctionComponent<Props> = ({ isAdmin }) => {
const { services } = useKibana();
const application = services.application!;
const docLinks = services.docLinks!;
return (
<EuiEmptyPrompt
iconType="managementApp"
title={
<h1 data-test-subj="noApiKeysHeader">
{isAdmin ? (
<FormattedMessage
id="xpack.security.management.apiKeys.table.emptyPromptAdminTitle"
defaultMessage="No API keys"
/>
) : (
<FormattedMessage
id="xpack.security.management.apiKeys.table.emptyPromptNonAdminTitle"
defaultMessage="You don't have any API keys"
/>
)}
</h1>
}
body={
<Fragment>
<p>
<FormattedMessage
id="xpack.security.management.apiKeys.table.emptyPromptDescription"
defaultMessage="You can create an {link} from Console."
values={{
link: (
<EuiLink href={`${docLinks.links.apis.createApiKey}`} target="_blank">
<FormattedMessage
id="xpack.security.management.apiKeys.table.emptyPromptDocsLinkMessage"
defaultMessage="API key"
/>
</EuiLink>
),
}}
/>
</p>
</Fragment>
}
actions={
<EuiButton
type="primary"
onClick={() => application.navigateToApp('dev_tools')}
data-test-subj="goToConsoleButton"
>
<FormattedMessage
id="xpack.security.management.apiKeys.table.emptyPromptAdminTitle"
defaultMessage="No API keys"
id="xpack.security.management.apiKeys.table.emptyPromptConsoleButtonMessage"
defaultMessage="Go to Console"
/>
) : (
<FormattedMessage
id="xpack.security.management.apiKeys.table.emptyPromptNonAdminTitle"
defaultMessage="You don't have any API keys"
/>
)}
</h1>
}
body={
<Fragment>
<p>
<FormattedMessage
id="xpack.security.management.apiKeys.table.emptyPromptDescription"
defaultMessage="You can create an {link} from Console."
values={{
link: (
<EuiLink href={`${docLinks.links.apis.createApiKey}`} target="_blank">
<FormattedMessage
id="xpack.security.management.apiKeys.table.emptyPromptDocsLinkMessage"
defaultMessage="API key"
/>
</EuiLink>
),
}}
/>
</p>
</Fragment>
}
actions={
<EuiButton
type="primary"
onClick={() => navigateToApp('dev_tools')}
data-test-subj="goToConsoleButton"
>
<FormattedMessage
id="xpack.security.management.apiKeys.table.emptyPromptConsoleButtonMessage"
defaultMessage="Go to Console"
/>
</EuiButton>
}
data-test-subj="emptyPrompt"
/>
);
</EuiButton>
}
data-test-subj="emptyPrompt"
/>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -7,36 +7,35 @@
import React from 'react';
import { EuiCallOut, EuiLink } from '@elastic/eui';
import { FormattedMessage } from '@kbn/i18n/react';
import type { DocLinksStart } from 'src/core/public';
import { useKibana } from '../../../../../../../../src/plugins/kibana_react/public';

interface Props {
docLinks: DocLinksStart;
}

export const NotEnabled: React.FunctionComponent<Props> = ({ docLinks }) => (
<EuiCallOut
title={
export const NotEnabled: React.FunctionComponent = () => {
const docLinks = useKibana().services.docLinks!;
return (
<EuiCallOut
title={
<FormattedMessage
id="xpack.security.management.apiKeys.table.apiKeysDisabledErrorTitle"
defaultMessage="API keys not enabled in Elasticsearch"
/>
}
color="danger"
iconType="alert"
>
<FormattedMessage
id="xpack.security.management.apiKeys.table.apiKeysDisabledErrorTitle"
defaultMessage="API keys not enabled in Elasticsearch"
id="xpack.security.management.apiKeys.table.apiKeysDisabledErrorDescription"
defaultMessage="Contact your system administrator and refer to the {link} to enable API keys."
values={{
link: (
<EuiLink href={`${docLinks.links.security.apiKeyServiceSettings}`} target="_blank">
<FormattedMessage
id="xpack.security.management.apiKeys.table.apiKeysDisabledErrorLinkText"
defaultMessage="docs"
/>
</EuiLink>
),
}}
/>
}
color="danger"
iconType="alert"
>
<FormattedMessage
id="xpack.security.management.apiKeys.table.apiKeysDisabledErrorDescription"
defaultMessage="Contact your system administrator and refer to the {link} to enable API keys."
values={{
link: (
<EuiLink href={`${docLinks.links.security.apiKeyServiceSettings}`} target="_blank">
<FormattedMessage
id="xpack.security.management.apiKeys.table.apiKeysDisabledErrorLinkText"
defaultMessage="docs"
/>
</EuiLink>
),
}}
/>
</EuiCallOut>
);
</EuiCallOut>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,7 @@
*/

jest.mock('./api_keys_grid', () => ({
APIKeysGridPage: (props: any) =>
// `docLinks` object is too big to include into test snapshot, so we just check its existence.
`Page: ${JSON.stringify({ ...props, docLinks: props.docLinks ? {} : undefined })}`,
APIKeysGridPage: (props: any) => `Page: ${JSON.stringify(props)}`,
}));
import { apiKeysManagementApp } from './api_keys_management_app';
import { coreMock, scopedHistoryMock } from '../../../../../../src/core/public/mocks';
Expand Down Expand Up @@ -45,7 +43,7 @@ describe('apiKeysManagementApp', () => {
expect(setBreadcrumbs).toHaveBeenCalledWith([{ href: '/', text: 'API Keys' }]);
expect(container).toMatchInlineSnapshot(`
<div>
Page: {"notifications":{"toasts":{}},"docLinks":{},"apiKeysAPIClient":{"http":{"basePath":{"basePath":"","serverBasePath":""},"anonymousPaths":{},"externalUrl":{}}}}
Page: {"notifications":{"toasts":{}},"apiKeysAPIClient":{"http":{"basePath":{"basePath":"","serverBasePath":""},"anonymousPaths":{},"externalUrl":{}}}}
</div>
`);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { render, unmountComponentAtNode } from 'react-dom';
import { i18n } from '@kbn/i18n';
import { StartServicesAccessor } from 'src/core/public';
import { RegisterManagementAppArgs } from '../../../../../../src/plugins/management/public';
import { KibanaContextProvider } from '../../../../../../src/plugins/kibana_react/public';
import { PluginStartDependencies } from '../../plugin';

interface CreateParams {
Expand Down Expand Up @@ -45,14 +46,14 @@ export const apiKeysManagementApp = Object.freeze({
]);

render(
<i18nStart.Context>
<APIKeysGridPage
navigateToApp={application.navigateToApp}
notifications={notifications}
docLinks={docLinks}
apiKeysAPIClient={new APIKeysAPIClient(http)}
/>
</i18nStart.Context>,
<KibanaContextProvider services={{ application, docLinks }}>
<i18nStart.Context>
<APIKeysGridPage
notifications={notifications}
apiKeysAPIClient={new APIKeysAPIClient(http)}
/>
</i18nStart.Context>
</KibanaContextProvider>,
element
);

Expand Down
Loading

0 comments on commit d2952c3

Please sign in to comment.