Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[8.x] [Security Solution] [Onboarding] t1_analyst role blocked from interacting with cards due to missing integration privileges (#202413) #202553

Merged
merged 1 commit into from
Dec 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ const props = {
checkComplete: jest.fn(),
isCardComplete: jest.fn(),
setExpandedCardId: jest.fn(),
isCardAvailable: jest.fn(),
};

describe('AlertsCard', () => {
Expand All @@ -31,7 +32,8 @@ describe('AlertsCard', () => {
expect(getByTestId('alertsCardDescription')).toBeInTheDocument();
});

it('card callout should be rendered if integrations cards is not complete', () => {
it('card callout should be rendered if integrations card is available but not complete', () => {
props.isCardAvailable.mockReturnValueOnce(true);
props.isCardComplete.mockReturnValueOnce(false);

const { getByText } = render(
Expand All @@ -43,7 +45,20 @@ describe('AlertsCard', () => {
expect(getByText('To view alerts add integrations first.')).toBeInTheDocument();
});

it('card button should be disabled if integrations cards is not complete', () => {
it('card callout should not be rendered if integrations card is not available', () => {
props.isCardAvailable.mockReturnValueOnce(false);

const { queryByText } = render(
<TestProviders>
<AlertsCard {...props} />
</TestProviders>
);

expect(queryByText('To view alerts add integrations first.')).not.toBeInTheDocument();
});

it('card button should be disabled if integrations card is available but not complete', () => {
props.isCardAvailable.mockReturnValueOnce(true);
props.isCardComplete.mockReturnValueOnce(false);

const { getByTestId } = render(
Expand All @@ -54,4 +69,17 @@ describe('AlertsCard', () => {

expect(getByTestId('alertsCardButton').querySelector('button')).toBeDisabled();
});

it('card button should be enabled if integrations card is complete', () => {
props.isCardAvailable.mockReturnValueOnce(true);
props.isCardComplete.mockReturnValueOnce(true);

const { getByTestId } = render(
<TestProviders>
<AlertsCard {...props} />
</TestProviders>
);

expect(getByTestId('alertsCardButton').querySelector('button')).not.toBeDisabled();
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,18 @@ export const AlertsCard: OnboardingCardComponent = ({
isCardComplete,
setExpandedCardId,
setComplete,
isCardAvailable,
}) => {
const isIntegrationsCardComplete = useMemo(
() => isCardComplete(OnboardingCardId.integrations),
[isCardComplete]
);

const isIntegrationsCardAvailable = useMemo(
() => isCardAvailable(OnboardingCardId.integrations),
[isCardAvailable]
);

const expandIntegrationsCard = useCallback(() => {
setExpandedCardId(OnboardingCardId.integrations, { scroll: true });
}, [setExpandedCardId]);
Expand All @@ -43,7 +49,7 @@ export const AlertsCard: OnboardingCardComponent = ({
<CardSubduedText data-test-subj="alertsCardDescription" size="s">
{i18n.ALERTS_CARD_DESCRIPTION}
</CardSubduedText>
{!isIntegrationsCardComplete && (
{isIntegrationsCardAvailable && !isIntegrationsCardComplete && (
<>
<EuiSpacer size="m" />
<CardCallOut
Expand All @@ -69,7 +75,7 @@ export const AlertsCard: OnboardingCardComponent = ({
onClick={() => setComplete(true)}
deepLinkId={SecurityPageName.alerts}
fill
isDisabled={!isIntegrationsCardComplete}
isDisabled={isIntegrationsCardAvailable && !isIntegrationsCardComplete}
>
{i18n.ALERTS_CARD_VIEW_ALERTS_BUTTON}
</SecuritySolutionLinkButton>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,18 @@ export const AssistantCard: OnboardingCardComponent<AssistantCardMetadata> = ({
setExpandedCardId,
checkCompleteMetadata,
checkComplete,
isCardAvailable,
}) => {
const isIntegrationsCardComplete = useMemo(
() => isCardComplete(OnboardingCardId.integrations),
[isCardComplete]
);

const isIntegrationsCardAvailable = useMemo(
() => isCardAvailable(OnboardingCardId.integrations),
[isCardAvailable]
);

const expandIntegrationsCard = useCallback(() => {
setExpandedCardId(OnboardingCardId.integrations, { scroll: true });
}, [setExpandedCardId]);
Expand All @@ -45,13 +51,7 @@ export const AssistantCard: OnboardingCardComponent<AssistantCardMetadata> = ({
<CardSubduedText size="s">{i18n.ASSISTANT_CARD_DESCRIPTION}</CardSubduedText>
</EuiFlexItem>
<EuiFlexItem>
{isIntegrationsCardComplete ? (
<ConnectorCards
canCreateConnectors={canCreateConnectors}
connectors={connectors}
onConnectorSaved={checkComplete}
/>
) : (
{isIntegrationsCardAvailable && !isIntegrationsCardComplete ? (
<EuiFlexItem
className={css`
width: 45%;
Expand All @@ -73,6 +73,12 @@ export const AssistantCard: OnboardingCardComponent<AssistantCardMetadata> = ({
}
/>
</EuiFlexItem>
) : (
<ConnectorCards
canCreateConnectors={canCreateConnectors}
connectors={connectors}
onConnectorSaved={checkComplete}
/>
)}
</EuiFlexItem>
</EuiFlexGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ const props = {
checkComplete: jest.fn(),
isCardComplete: jest.fn(),
setExpandedCardId: jest.fn(),
isCardAvailable: jest.fn(),
};

describe('RulesCard', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,10 @@ const props = {
checkComplete: jest.fn(),
isCardComplete: jest.fn(),
setExpandedCardId: jest.fn(),
isCardAvailable: jest.fn(),
};

describe('RulesCard', () => {
describe('DashboardsCard', () => {
beforeEach(() => {
jest.clearAllMocks();
});
Expand All @@ -34,7 +35,8 @@ describe('RulesCard', () => {
expect(getByTestId('dashboardsDescription')).toBeInTheDocument();
});

it('card callout should be rendered if integrations cards is not complete', () => {
it('card callout should be rendered if integrations card is available but not complete', () => {
props.isCardAvailable.mockReturnValueOnce(true);
props.isCardComplete.mockReturnValueOnce(false);

const { getByText } = render(
Expand All @@ -46,7 +48,20 @@ describe('RulesCard', () => {
expect(getByText('To view dashboards add integrations first.')).toBeInTheDocument();
});

it('card button should be disabled if integrations cards is not complete', () => {
it('card callout should not be rendered if integrations card is not available', () => {
props.isCardAvailable.mockReturnValueOnce(false);

const { queryByText } = render(
<TestProviders>
<DashboardsCard {...props} />
</TestProviders>
);

expect(queryByText('To view dashboards add integrations first.')).not.toBeInTheDocument();
});

it('card button should be disabled if integrations card is available but not complete', () => {
props.isCardAvailable.mockReturnValueOnce(true);
props.isCardComplete.mockReturnValueOnce(false);

const { getByTestId } = render(
Expand All @@ -57,7 +72,22 @@ describe('RulesCard', () => {

expect(getByTestId('dashboardsCardButton').querySelector('button')).toBeDisabled();
});

it('card button should be enabled if integrations card is complete', () => {
props.isCardAvailable.mockReturnValueOnce(true);
props.isCardComplete.mockReturnValueOnce(true);

const { getByTestId } = render(
<TestProviders>
<DashboardsCard {...props} />
</TestProviders>
);

expect(getByTestId('dashboardsCardButton').querySelector('button')).not.toBeDisabled();
});

it('should expand integrations card when callout link is clicked', () => {
props.isCardAvailable.mockReturnValueOnce(true);
props.isCardComplete.mockReturnValueOnce(false); // To show the callout

const { getByTestId } = render(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,18 @@ export const DashboardsCard: OnboardingCardComponent = ({
isCardComplete,
setComplete,
setExpandedCardId,
isCardAvailable,
}) => {
const isIntegrationsCardComplete = useMemo(
() => isCardComplete(OnboardingCardId.integrations),
[isCardComplete]
);

const isIntegrationsCardAvailable = useMemo(
() => isCardAvailable(OnboardingCardId.integrations),
[isCardAvailable]
);

const expandIntegrationsCard = useCallback(() => {
setExpandedCardId(OnboardingCardId.integrations, { scroll: true });
}, [setExpandedCardId]);
Expand All @@ -46,7 +52,7 @@ export const DashboardsCard: OnboardingCardComponent = ({
<CardSubduedText data-test-subj="dashboardsDescription" size="s">
{i18n.DASHBOARDS_CARD_DESCRIPTION}
</CardSubduedText>
{!isIntegrationsCardComplete && (
{isIntegrationsCardAvailable && !isIntegrationsCardComplete && (
<>
<EuiSpacer size="m" />
<CardCallOut
Expand Down Expand Up @@ -77,7 +83,7 @@ export const DashboardsCard: OnboardingCardComponent = ({
cardId={OnboardingCardId.dashboards}
deepLinkId={SecurityPageName.dashboards}
fill
isDisabled={!isIntegrationsCardComplete}
isDisabled={isIntegrationsCardAvailable && !isIntegrationsCardComplete}
>
{i18n.DASHBOARDS_CARD_GO_TO_DASHBOARDS_BUTTON}
</CardLinkButton>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ const props = {
checkComplete: jest.fn(),
isCardComplete: jest.fn(),
setExpandedCardId: jest.fn(),
isCardAvailable: jest.fn(),
};

describe('IntegrationsCard', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ const props = {
setComplete: jest.fn(),
checkComplete: jest.fn(),
isCardComplete: jest.fn(),
isCardAvailable: jest.fn(),
setExpandedCardId: jest.fn(),
};

Expand All @@ -31,7 +32,8 @@ describe('RulesCard', () => {
expect(getByTestId('rulesCardDescription')).toBeInTheDocument();
});

it('card callout should be rendered if integrations cards is not complete', () => {
it('card callout should be rendered if integrations card is available but not complete', () => {
props.isCardAvailable.mockReturnValueOnce(true);
props.isCardComplete.mockReturnValueOnce(false);

const { getByText } = render(
Expand All @@ -43,7 +45,20 @@ describe('RulesCard', () => {
expect(getByText('To add Elastic rules add integrations first.')).toBeInTheDocument();
});

it('card button should be disabled if integrations cards is not complete', () => {
it('card callout should not be rendered if integrations card is not available', () => {
props.isCardAvailable.mockReturnValueOnce(false);

const { queryByText } = render(
<TestProviders>
<RulesCard {...props} />
</TestProviders>
);

expect(queryByText('To add Elastic rules add integrations first.')).not.toBeInTheDocument();
});

it('card button should be disabled if integrations card is available but not complete', () => {
props.isCardAvailable.mockReturnValueOnce(true);
props.isCardComplete.mockReturnValueOnce(false);

const { getByTestId } = render(
Expand All @@ -54,4 +69,17 @@ describe('RulesCard', () => {

expect(getByTestId('rulesCardButton').querySelector('button')).toBeDisabled();
});

it('card button should be enabled if integrations card is complete', () => {
props.isCardAvailable.mockReturnValueOnce(true);
props.isCardComplete.mockReturnValueOnce(true);

const { getByTestId } = render(
<TestProviders>
<RulesCard {...props} />
</TestProviders>
);

expect(getByTestId('rulesCardButton').querySelector('button')).not.toBeDisabled();
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,21 @@ import { CardSubduedText } from '../common/card_subdued_text';
import rulesImageSrc from './images/rules.png';
import * as i18n from './translations';

export const RulesCard: OnboardingCardComponent = ({ isCardComplete, setExpandedCardId }) => {
export const RulesCard: OnboardingCardComponent = ({
isCardComplete,
setExpandedCardId,
isCardAvailable,
}) => {
const isIntegrationsCardComplete = useMemo(
() => isCardComplete(OnboardingCardId.integrations),
[isCardComplete]
);

const isIntegrationsCardAvailable = useMemo(
() => isCardAvailable(OnboardingCardId.integrations),
[isCardAvailable]
);

const expandIntegrationsCard = useCallback(() => {
setExpandedCardId(OnboardingCardId.integrations, { scroll: true });
}, [setExpandedCardId]);
Expand All @@ -39,7 +48,7 @@ export const RulesCard: OnboardingCardComponent = ({ isCardComplete, setExpanded
<CardSubduedText data-test-subj="rulesCardDescription" size="s">
{i18n.RULES_CARD_DESCRIPTION}
</CardSubduedText>
{!isIntegrationsCardComplete && (
{isIntegrationsCardAvailable && !isIntegrationsCardComplete && (
<>
<EuiSpacer size="m" />
<CardCallOut
Expand All @@ -64,7 +73,7 @@ export const RulesCard: OnboardingCardComponent = ({ isCardComplete, setExpanded
<SecuritySolutionLinkButton
deepLinkId={SecurityPageName.rules}
fill
isDisabled={!isIntegrationsCardComplete}
isDisabled={isIntegrationsCardAvailable && !isIntegrationsCardComplete}
>
{i18n.RULES_CARD_ADD_RULES_BUTTON}
</SecuritySolutionLinkButton>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import { OnboardingCardGroup } from './onboarding_card_group';
import { OnboardingCardPanel } from './onboarding_card_panel';
import { useExpandedCard } from './hooks/use_expanded_card';
import { useCompletedCards } from './hooks/use_completed_cards';
import type { IsCardAvailable } from '../../types';

export const OnboardingBody = React.memo(() => {
const bodyConfig = useBodyConfig();
Expand Down Expand Up @@ -47,6 +48,12 @@ export const OnboardingBody = React.memo(() => {
[checkCardComplete]
);

const isCardAvailable = useCallback<IsCardAvailable>(
(cardId: OnboardingCardId) =>
bodyConfig.some((group) => group.cards.some((card) => card.id === cardId)),
[bodyConfig]
);

return (
<EuiFlexGroup direction="column" gutterSize="xl">
{bodyConfig.map((group, index) => (
Expand All @@ -72,6 +79,7 @@ export const OnboardingBody = React.memo(() => {
setComplete={createSetCardComplete(id)}
checkComplete={createCheckCardComplete(id)}
isCardComplete={isCardComplete}
isCardAvailable={isCardAvailable}
setExpandedCardId={setExpandedCardId}
checkCompleteMetadata={cardCheckCompleteResult?.metadata}
/>
Expand Down
Loading
Loading