diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/role_mappings/role_mappings.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/role_mappings/role_mappings.test.tsx index d7ce8053c71f027..350a0d7bf6162b1 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/role_mappings/role_mappings.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/role_mappings/role_mappings.test.tsx @@ -12,10 +12,13 @@ import React from 'react'; import { shallow } from 'enzyme'; -import { Loading } from '../../../shared/loading'; -import { RoleMappingsTable, RoleMappingsHeading } from '../../../shared/role_mapping'; +import { EuiButton } from '@elastic/eui'; + +import { RoleMappingsTable } from '../../../shared/role_mapping'; import { wsRoleMapping } from '../../../shared/role_mapping/__mocks__/roles'; +import { getPageHeaderActions } from '../../../test_helpers'; + import { RoleMapping } from './role_mapping'; import { RoleMappings } from './role_mappings'; @@ -44,13 +47,6 @@ describe('RoleMappings', () => { expect(wrapper.find(RoleMappingsTable)).toHaveLength(1); }); - it('returns Loading when loading', () => { - setMockValues({ ...mockValues, dataLoading: true }); - const wrapper = shallow(); - - expect(wrapper.find(Loading)).toHaveLength(1); - }); - it('renders RoleMapping flyout', () => { setMockValues({ ...mockValues, roleMappingFlyoutOpen: true }); const wrapper = shallow(); @@ -60,8 +56,9 @@ describe('RoleMappings', () => { it('handles onClick', () => { const wrapper = shallow(); - wrapper.find(RoleMappingsHeading).prop('onClick')(); + const actions = getPageHeaderActions(wrapper); + actions.find(EuiButton).simulate('click'); expect(initializeRoleMapping).toHaveBeenCalled(); }); }); diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/role_mappings/role_mappings.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/role_mappings/role_mappings.tsx index 78d0a5cbc8638ec..903e6b54a9bb291 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/role_mappings/role_mappings.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/role_mappings/role_mappings.tsx @@ -9,11 +9,13 @@ import React, { useEffect } from 'react'; import { useActions, useValues } from 'kea'; -import { FlashMessages } from '../../../shared/flash_messages'; -import { SetAppSearchChrome as SetPageChrome } from '../../../shared/kibana_chrome'; -import { Loading } from '../../../shared/loading'; -import { RoleMappingsTable, RoleMappingsHeading } from '../../../shared/role_mapping'; -import { ROLE_MAPPINGS_TITLE } from '../../../shared/role_mapping/constants'; +import { APP_SEARCH_PLUGIN } from '../../../../../common/constants'; +import { + ROLE_MAPPINGS_TITLE, + getRoleMappingsHeader, + RoleMappingsTable, +} from '../../../shared/role_mapping'; +import { AppSearchPageTemplate } from '../layout'; import { ROLE_MAPPINGS_ENGINE_ACCESS_HEADING } from './constants'; import { RoleMapping } from './role_mapping'; @@ -38,11 +40,16 @@ export const RoleMappings: React.FC = () => { return resetState; }, []); - if (dataLoading) return ; - - const roleMappingsSection = ( - <> - initializeRoleMapping()} /> + return ( + initializeRoleMapping(), + })} + isLoading={dataLoading} + > + {roleMappingFlyoutOpen && } { shouldShowAuthProvider={multipleAuthProvidersConfig} handleDeleteMapping={handleDeleteMapping} /> - - ); - - return ( - <> - - {roleMappingFlyoutOpen && } - - {roleMappingsSection} - + ); }; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/index.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/index.tsx index 20f65ba2c346ca0..caf0f805e8ca7eb 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/index.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/index.tsx @@ -92,6 +92,11 @@ export const AppSearchConfigured: React.FC> = (props) = )} + {canViewRoleMappings && ( + + + + )} } readOnlyMode={readOnlyMode}> @@ -110,11 +115,6 @@ export const AppSearchConfigured: React.FC> = (props) = - {canViewRoleMappings && ( - - - - )} {canManageEngines && ( diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/role_mapping/constants.ts b/x-pack/plugins/enterprise_search/public/applications/shared/role_mapping/constants.ts index 47d481630510e26..e5312c6c0343f7a 100644 --- a/x-pack/plugins/enterprise_search/public/applications/shared/role_mapping/constants.ts +++ b/x-pack/plugins/enterprise_search/public/applications/shared/role_mapping/constants.ts @@ -7,8 +7,6 @@ import { i18n } from '@kbn/i18n'; -import { ProductName } from '../types'; - export const ANY_AUTH_PROVIDER = '*'; export const ANY_AUTH_PROVIDER_OPTION_LABEL = i18n.translate( @@ -184,7 +182,7 @@ export const ROLE_MAPPINGS_HEADING_TITLE = i18n.translate( { defaultMessage: 'Role mappings' } ); -export const ROLE_MAPPINGS_HEADING_DESCRIPTION = (productName: ProductName) => +export const ROLE_MAPPINGS_HEADING_DESCRIPTION = (productName: string) => i18n.translate('xpack.enterpriseSearch.roleMapping.roleMappingsHeadingDescription', { defaultMessage: 'Role mappings provide an interface to associate native or SAML-governed role attributes with {productName} permissions.', @@ -193,7 +191,7 @@ export const ROLE_MAPPINGS_HEADING_DESCRIPTION = (productName: ProductName) => export const ROLE_MAPPINGS_HEADING_DOCS_LINK = i18n.translate( 'xpack.enterpriseSearch.roleMapping.roleMappingsHeadingDocsLink', - { defaultMessage: 'Learn more about role mappings' } + { defaultMessage: 'Learn more about role mappings.' } ); export const ROLE_MAPPINGS_HEADING_BUTTON = i18n.translate( diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/role_mapping/index.ts b/x-pack/plugins/enterprise_search/public/applications/shared/role_mapping/index.ts index b0d10e9692714f6..d254c712617a79b 100644 --- a/x-pack/plugins/enterprise_search/public/applications/shared/role_mapping/index.ts +++ b/x-pack/plugins/enterprise_search/public/applications/shared/role_mapping/index.ts @@ -5,10 +5,11 @@ * 2.0. */ +export { ROLE_MAPPINGS_TITLE } from './constants'; export { AttributeSelector } from './attribute_selector'; export { RoleMappingsTable } from './role_mappings_table'; export { RoleOptionLabel } from './role_option_label'; export { RoleSelector } from './role_selector'; export { RoleMappingFlyout } from './role_mapping_flyout'; -export { RoleMappingsHeading } from './role_mappings_heading'; +export { getRoleMappingsHeader } from './role_mappings_header'; export { UsersAndRolesRowActions } from './users_and_roles_row_actions'; diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/role_mapping/role_mappings_header.test.tsx b/x-pack/plugins/enterprise_search/public/applications/shared/role_mapping/role_mappings_header.test.tsx new file mode 100644 index 000000000000000..36b883afdd2e227 --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/shared/role_mapping/role_mappings_header.test.tsx @@ -0,0 +1,41 @@ +/* + * 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 { shallow } from 'enzyme'; + +import { EuiLink, EuiButton } from '@elastic/eui'; + +import { getRoleMappingsHeader } from './role_mappings_header'; + +describe('getRoleMappingsHeader', () => { + const onClick = jest.fn(); + const pageHeader = getRoleMappingsHeader({ productName: 'Workplace Search', onClick }); + + it('returns an EuiPageHeader object', () => { + expect(pageHeader.pageTitle).toEqual('Role mappings'); + }); + + it('renders the passed productName in the description', () => { + const Description = () => <>{pageHeader.description}; + const wrapper = shallow(); + + expect(wrapper.text()).toEqual( + expect.stringContaining('role attributes with Workplace Search permissions') + ); + expect(wrapper.find(EuiLink)).toHaveLength(1); + }); + + it('renders an action button with a passed onClick', () => { + const Button = () => <>{pageHeader.rightSideItems[0]}; + const wrapper = shallow(