[Enterprise Search] Update WS Overview logic to use new config data (#77122)
* Update AppLogic to use new data structure * Update components to use AppLogic * Remove unused props from logic file * Fix failing tests * Add tests to get 100% converage The test added for app_logic will never happen but hey, 100 is 100. Also added test to recent_activity for 100% coverage * Use non-null assertion operator in logic file TIL this is a thing * Remove test for undefined
This commit is contained in:
parent
50ec790f71
commit
65abdfffee
12 changed files with 116 additions and 90 deletions
|
@ -16,7 +16,28 @@ describe('AppLogic', () => {
|
|||
});
|
||||
|
||||
const DEFAULT_VALUES = {
|
||||
account: {},
|
||||
hasInitialized: false,
|
||||
isFederatedAuth: true,
|
||||
organization: {},
|
||||
};
|
||||
|
||||
const expectedLogicValues = {
|
||||
account: {
|
||||
canCreateInvitations: true,
|
||||
canCreatePersonalSources: true,
|
||||
groups: ['Default', 'Cats'],
|
||||
id: 'some-id-string',
|
||||
isAdmin: true,
|
||||
isCurated: false,
|
||||
viewedOnboardingPage: true,
|
||||
},
|
||||
hasInitialized: true,
|
||||
isFederatedAuth: false,
|
||||
organization: {
|
||||
defaultOrgName: 'My Organization',
|
||||
name: 'ACME Donuts',
|
||||
},
|
||||
};
|
||||
|
||||
it('has expected default values', () => {
|
||||
|
@ -27,9 +48,7 @@ describe('AppLogic', () => {
|
|||
it('sets values based on passed props', () => {
|
||||
AppLogic.actions.initializeAppData(DEFAULT_INITIAL_APP_DATA);
|
||||
|
||||
expect(AppLogic.values).toEqual({
|
||||
hasInitialized: true,
|
||||
});
|
||||
expect(AppLogic.values).toEqual(expectedLogicValues);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -7,18 +7,26 @@
|
|||
import { kea, MakeLogicType } from 'kea';
|
||||
|
||||
import { IInitialAppData } from '../../../common/types';
|
||||
import { IWorkplaceSearchInitialData } from '../../../common/types/workplace_search';
|
||||
import {
|
||||
IOrganization,
|
||||
IWorkplaceSearchInitialData,
|
||||
IAccount,
|
||||
} from '../../../common/types/workplace_search';
|
||||
|
||||
export interface IAppValues extends IWorkplaceSearchInitialData {
|
||||
hasInitialized: boolean;
|
||||
isFederatedAuth: boolean;
|
||||
}
|
||||
export interface IAppActions {
|
||||
initializeAppData(props: IInitialAppData): void;
|
||||
initializeAppData(props: IInitialAppData): IInitialAppData;
|
||||
}
|
||||
|
||||
export const AppLogic = kea<MakeLogicType<IAppValues, IAppActions>>({
|
||||
actions: {
|
||||
initializeAppData: ({ workplaceSearch }) => workplaceSearch,
|
||||
initializeAppData: ({ workplaceSearch, isFederatedAuth }) => ({
|
||||
workplaceSearch,
|
||||
isFederatedAuth,
|
||||
}),
|
||||
},
|
||||
reducers: {
|
||||
hasInitialized: [
|
||||
|
@ -27,5 +35,23 @@ export const AppLogic = kea<MakeLogicType<IAppValues, IAppActions>>({
|
|||
initializeAppData: () => true,
|
||||
},
|
||||
],
|
||||
isFederatedAuth: [
|
||||
true,
|
||||
{
|
||||
initializeAppData: (_, { isFederatedAuth }) => !!isFederatedAuth,
|
||||
},
|
||||
],
|
||||
organization: [
|
||||
{} as IOrganization,
|
||||
{
|
||||
initializeAppData: (_, { workplaceSearch }) => workplaceSearch!.organization,
|
||||
},
|
||||
],
|
||||
account: [
|
||||
{} as IAccount,
|
||||
{
|
||||
initializeAppData: (_, { workplaceSearch }) => workplaceSearch!.account,
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
|
|
|
@ -4,4 +4,4 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
export { setMockValues, mockValues, mockActions } from './overview_logic.mock';
|
||||
export { setMockValues, mockOverviewValues, mockActions } from './overview_logic.mock';
|
||||
|
|
|
@ -5,19 +5,18 @@
|
|||
*/
|
||||
|
||||
import { IOverviewValues } from '../overview_logic';
|
||||
import { IAccount, IOrganization } from '../../../types';
|
||||
|
||||
export const mockValues = {
|
||||
import { DEFAULT_INITIAL_APP_DATA } from '../../../../../../common/__mocks__';
|
||||
|
||||
const { workplaceSearch: mockAppValues } = DEFAULT_INITIAL_APP_DATA;
|
||||
|
||||
export const mockOverviewValues = {
|
||||
accountsCount: 0,
|
||||
activityFeed: [],
|
||||
canCreateContentSources: false,
|
||||
canCreateInvitations: false,
|
||||
fpAccount: {} as IAccount,
|
||||
hasOrgSources: false,
|
||||
hasUsers: false,
|
||||
isFederatedAuth: true,
|
||||
isOldAccount: false,
|
||||
organization: {} as IOrganization,
|
||||
pendingInvitationsCount: 0,
|
||||
personalSourcesCount: 0,
|
||||
sourcesCount: 0,
|
||||
|
@ -28,6 +27,8 @@ export const mockActions = {
|
|||
initializeOverview: jest.fn(() => ({})),
|
||||
};
|
||||
|
||||
const mockValues = { ...mockOverviewValues, ...mockAppValues, isFederatedAuth: true };
|
||||
|
||||
jest.mock('kea', () => ({
|
||||
...(jest.requireActual('kea') as object),
|
||||
useActions: jest.fn(() => ({ ...mockActions })),
|
||||
|
@ -37,8 +38,5 @@ jest.mock('kea', () => ({
|
|||
import { useValues } from 'kea';
|
||||
|
||||
export const setMockValues = (values: object) => {
|
||||
(useValues as jest.Mock).mockImplementationOnce(() => ({
|
||||
...mockValues,
|
||||
...values,
|
||||
}));
|
||||
(useValues as jest.Mock).mockImplementation(() => ({ ...mockValues, ...values }));
|
||||
};
|
||||
|
|
|
@ -25,6 +25,7 @@ const account = {
|
|||
canCreatePersonalSources: true,
|
||||
groups: [],
|
||||
isCurated: false,
|
||||
canCreateInvitations: true,
|
||||
};
|
||||
|
||||
describe('OnboardingSteps', () => {
|
||||
|
@ -60,9 +61,8 @@ describe('OnboardingSteps', () => {
|
|||
describe('Users & Invitations', () => {
|
||||
it('renders 0 users when not on federated auth', () => {
|
||||
setMockValues({
|
||||
canCreateInvitations: true,
|
||||
isFederatedAuth: false,
|
||||
fpAccount: account,
|
||||
account,
|
||||
accountsCount: 0,
|
||||
hasUsers: false,
|
||||
});
|
||||
|
@ -78,7 +78,7 @@ describe('OnboardingSteps', () => {
|
|||
it('renders completed users state', () => {
|
||||
setMockValues({
|
||||
isFederatedAuth: false,
|
||||
fpAccount: account,
|
||||
account,
|
||||
accountsCount: 1,
|
||||
hasUsers: true,
|
||||
});
|
||||
|
@ -90,7 +90,13 @@ describe('OnboardingSteps', () => {
|
|||
});
|
||||
|
||||
it('disables link when the user cannot create invitations', () => {
|
||||
setMockValues({ isFederatedAuth: false, canCreateInvitations: false });
|
||||
setMockValues({
|
||||
isFederatedAuth: false,
|
||||
account: {
|
||||
...account,
|
||||
canCreateInvitations: false,
|
||||
},
|
||||
});
|
||||
const wrapper = shallow(<OnboardingSteps />);
|
||||
expect(wrapper.find(OnboardingCard).last().prop('actionPath')).toBe(undefined);
|
||||
});
|
||||
|
@ -98,6 +104,12 @@ describe('OnboardingSteps', () => {
|
|||
|
||||
describe('Org Name', () => {
|
||||
it('renders button to change name', () => {
|
||||
setMockValues({
|
||||
organization: {
|
||||
name: 'foo',
|
||||
defaultOrgName: 'foo',
|
||||
},
|
||||
});
|
||||
const wrapper = shallow(<OnboardingSteps />);
|
||||
|
||||
const button = wrapper
|
||||
|
|
|
@ -28,6 +28,7 @@ import { ORG_SOURCES_PATH, USERS_PATH, ORG_SETTINGS_PATH } from '../../routes';
|
|||
|
||||
import { ContentSection } from '../../components/shared/content_section';
|
||||
|
||||
import { AppLogic } from '../../app_logic';
|
||||
import { OverviewLogic } from './overview_logic';
|
||||
|
||||
import { OnboardingCard } from './onboarding_card';
|
||||
|
@ -58,16 +59,18 @@ const ONBOARDING_USERS_CARD_DESCRIPTION = i18n.translate(
|
|||
);
|
||||
|
||||
export const OnboardingSteps: React.FC = () => {
|
||||
const {
|
||||
isFederatedAuth,
|
||||
organization: { name, defaultOrgName },
|
||||
account: { isCurated, canCreateInvitations },
|
||||
} = useValues(AppLogic);
|
||||
|
||||
const {
|
||||
hasUsers,
|
||||
hasOrgSources,
|
||||
canCreateContentSources,
|
||||
canCreateInvitations,
|
||||
accountsCount,
|
||||
sourcesCount,
|
||||
fpAccount: { isCurated },
|
||||
organization: { name, defaultOrgName },
|
||||
isFederatedAuth,
|
||||
} = useValues(OverviewLogic);
|
||||
|
||||
const accountsPath =
|
||||
|
|
|
@ -14,18 +14,17 @@ import { i18n } from '@kbn/i18n';
|
|||
import { ContentSection } from '../../components/shared/content_section';
|
||||
import { ORG_SOURCES_PATH, USERS_PATH } from '../../routes';
|
||||
|
||||
import { AppLogic } from '../../app_logic';
|
||||
import { OverviewLogic } from './overview_logic';
|
||||
|
||||
import { StatisticCard } from './statistic_card';
|
||||
|
||||
export const OrganizationStats: React.FC = () => {
|
||||
const {
|
||||
sourcesCount,
|
||||
pendingInvitationsCount,
|
||||
accountsCount,
|
||||
personalSourcesCount,
|
||||
isFederatedAuth,
|
||||
} = useValues(OverviewLogic);
|
||||
const { isFederatedAuth } = useValues(AppLogic);
|
||||
|
||||
const { sourcesCount, pendingInvitationsCount, accountsCount, personalSourcesCount } = useValues(
|
||||
OverviewLogic
|
||||
);
|
||||
|
||||
return (
|
||||
<ContentSection
|
||||
|
|
|
@ -14,6 +14,7 @@ import { useActions, useValues } from 'kea';
|
|||
import { SetWorkplaceSearchChrome as SetPageChrome } from '../../../shared/kibana_chrome';
|
||||
import { SendWorkplaceSearchTelemetry as SendTelemetry } from '../../../shared/telemetry';
|
||||
|
||||
import { AppLogic } from '../../app_logic';
|
||||
import { OverviewLogic } from './overview_logic';
|
||||
|
||||
import { Loading } from '../../components/shared/loading';
|
||||
|
@ -44,15 +45,12 @@ const HEADER_DESCRIPTION = i18n.translate(
|
|||
);
|
||||
|
||||
export const Overview: React.FC = () => {
|
||||
const { initializeOverview } = useActions(OverviewLogic);
|
||||
|
||||
const {
|
||||
dataLoading,
|
||||
hasUsers,
|
||||
hasOrgSources,
|
||||
isOldAccount,
|
||||
organization: { name: orgName, defaultOrgName },
|
||||
} = useValues(OverviewLogic);
|
||||
} = useValues(AppLogic);
|
||||
|
||||
const { initializeOverview } = useActions(OverviewLogic);
|
||||
const { dataLoading, hasUsers, hasOrgSources, isOldAccount } = useValues(OverviewLogic);
|
||||
|
||||
useEffect(() => {
|
||||
initializeOverview();
|
||||
|
|
|
@ -9,7 +9,7 @@ import { resetContext } from 'kea';
|
|||
jest.mock('../../../shared/http', () => ({ HttpLogic: { values: { http: { get: jest.fn() } } } }));
|
||||
import { HttpLogic } from '../../../shared/http';
|
||||
|
||||
import { mockValues } from './__mocks__';
|
||||
import { mockOverviewValues } from './__mocks__';
|
||||
import { OverviewLogic } from './overview_logic';
|
||||
|
||||
describe('OverviewLogic', () => {
|
||||
|
@ -20,32 +20,19 @@ describe('OverviewLogic', () => {
|
|||
});
|
||||
|
||||
it('has expected default values', () => {
|
||||
expect(OverviewLogic.values).toEqual(mockValues);
|
||||
expect(OverviewLogic.values).toEqual(mockOverviewValues);
|
||||
});
|
||||
|
||||
describe('setServerData', () => {
|
||||
const feed = [{ foo: 'bar' }] as any;
|
||||
const account = {
|
||||
id: '1243',
|
||||
groups: ['Default'],
|
||||
isAdmin: true,
|
||||
isCurated: false,
|
||||
canCreatePersonalSources: true,
|
||||
viewedOnboardingPage: false,
|
||||
};
|
||||
const org = { name: 'ACME', defaultOrgName: 'Org' };
|
||||
|
||||
const data = {
|
||||
accountsCount: 1,
|
||||
activityFeed: feed,
|
||||
canCreateContentSources: true,
|
||||
canCreateInvitations: true,
|
||||
fpAccount: account,
|
||||
hasOrgSources: true,
|
||||
hasUsers: true,
|
||||
isFederatedAuth: false,
|
||||
isOldAccount: true,
|
||||
organization: org,
|
||||
pendingInvitationsCount: 1,
|
||||
personalSourcesCount: 1,
|
||||
sourcesCount: 1,
|
||||
|
@ -60,10 +47,6 @@ describe('OverviewLogic', () => {
|
|||
});
|
||||
|
||||
it('will set server values', () => {
|
||||
expect(OverviewLogic.values.organization).toEqual(org);
|
||||
expect(OverviewLogic.values.isFederatedAuth).toEqual(false);
|
||||
expect(OverviewLogic.values.fpAccount).toEqual(account);
|
||||
expect(OverviewLogic.values.canCreateInvitations).toEqual(true);
|
||||
expect(OverviewLogic.values.hasUsers).toEqual(true);
|
||||
expect(OverviewLogic.values.hasOrgSources).toEqual(true);
|
||||
expect(OverviewLogic.values.canCreateContentSources).toEqual(true);
|
||||
|
|
|
@ -7,24 +7,18 @@
|
|||
import { kea, MakeLogicType } from 'kea';
|
||||
import { HttpLogic } from '../../../shared/http';
|
||||
|
||||
import { IAccount, IOrganization } from '../../types';
|
||||
|
||||
import { IFeedActivity } from './recent_activity';
|
||||
|
||||
export interface IOverviewServerData {
|
||||
hasUsers: boolean;
|
||||
hasOrgSources: boolean;
|
||||
canCreateContentSources: boolean;
|
||||
canCreateInvitations: boolean;
|
||||
isOldAccount: boolean;
|
||||
sourcesCount: number;
|
||||
pendingInvitationsCount: number;
|
||||
accountsCount: number;
|
||||
personalSourcesCount: number;
|
||||
activityFeed: IFeedActivity[];
|
||||
organization: IOrganization;
|
||||
isFederatedAuth: boolean;
|
||||
fpAccount: IAccount;
|
||||
}
|
||||
|
||||
export interface IOverviewActions {
|
||||
|
@ -42,30 +36,6 @@ export const OverviewLogic = kea<MakeLogicType<IOverviewValues, IOverviewActions
|
|||
initializeOverview: () => null,
|
||||
},
|
||||
reducers: {
|
||||
organization: [
|
||||
{} as IOrganization,
|
||||
{
|
||||
setServerData: (_, { organization }) => organization,
|
||||
},
|
||||
],
|
||||
isFederatedAuth: [
|
||||
true,
|
||||
{
|
||||
setServerData: (_, { isFederatedAuth }) => isFederatedAuth,
|
||||
},
|
||||
],
|
||||
fpAccount: [
|
||||
{} as IAccount,
|
||||
{
|
||||
setServerData: (_, { fpAccount }) => fpAccount,
|
||||
},
|
||||
],
|
||||
canCreateInvitations: [
|
||||
false,
|
||||
{
|
||||
setServerData: (_, { canCreateInvitations }) => canCreateInvitations,
|
||||
},
|
||||
],
|
||||
hasUsers: [
|
||||
false,
|
||||
{
|
||||
|
|
|
@ -12,6 +12,7 @@ import React from 'react';
|
|||
import { shallow } from 'enzyme';
|
||||
|
||||
import { EuiEmptyPrompt, EuiLink } from '@elastic/eui';
|
||||
import { FormattedMessage } from '@kbn/i18n/react';
|
||||
|
||||
import { RecentActivity, RecentActivityItem } from './recent_activity';
|
||||
|
||||
|
@ -61,4 +62,19 @@ describe('RecentActivity', () => {
|
|||
expect(wrapper.find('.activity--error__label')).toHaveLength(1);
|
||||
expect(wrapper.find(EuiLink).prop('color')).toEqual('danger');
|
||||
});
|
||||
|
||||
it('renders recent activity message for default org name', () => {
|
||||
setMockValues({
|
||||
organization: {
|
||||
name: 'foo',
|
||||
defaultOrgName: 'foo',
|
||||
},
|
||||
});
|
||||
const wrapper = shallow(<RecentActivity />);
|
||||
const emptyPrompt = wrapper.find(EuiEmptyPrompt).dive();
|
||||
|
||||
expect(emptyPrompt.find(FormattedMessage).prop('defaultMessage')).toEqual(
|
||||
'Your organization has no recent activity'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -17,6 +17,7 @@ import { sendTelemetry } from '../../../shared/telemetry';
|
|||
import { KibanaContext, IKibanaContext } from '../../../index';
|
||||
import { SOURCE_DETAILS_PATH, getContentSourcePath } from '../../routes';
|
||||
|
||||
import { AppLogic } from '../../app_logic';
|
||||
import { OverviewLogic } from './overview_logic';
|
||||
|
||||
import './recent_activity.scss';
|
||||
|
@ -32,8 +33,9 @@ export interface IFeedActivity {
|
|||
export const RecentActivity: React.FC = () => {
|
||||
const {
|
||||
organization: { name, defaultOrgName },
|
||||
activityFeed,
|
||||
} = useValues(OverviewLogic);
|
||||
} = useValues(AppLogic);
|
||||
|
||||
const { activityFeed } = useValues(OverviewLogic);
|
||||
|
||||
return (
|
||||
<ContentSection
|
||||
|
|
Loading…
Reference in a new issue