Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
ffc8622
feat(suggested dashboards): suggested dashboards are shown in related…
cesco-f Jun 10, 2025
01975d6
feat(add suggested dashboard): added add suggested dashboard button
cesco-f Jun 10, 2025
0e1ef1d
feat(update rule): rule updated with the suggested dashboard when cli…
cesco-f Jun 10, 2025
3c871e9
feat(optimistic update): removed optimistic update
cesco-f Jun 11, 2025
0ab9b53
feat(description): returning description for suggested dashboards
cesco-f Jun 11, 2025
137bb1d
refactor(rename): just renamed some components
cesco-f Jun 11, 2025
7ee7e61
fix(linked dashboards): linked dashboards are passed to related dashb…
cesco-f Jun 11, 2025
aee698d
fix(related dashboard no): promoting a suggested dashboard the linked…
cesco-f Jun 11, 2025
66bf51b
test(hooks): added unit tests for use_add_suggested_dashboard and use…
cesco-f Jun 11, 2025
d1e0521
feat(telemetry): added page name and rule type to data-test-subj of t…
cesco-f Jun 11, 2025
b0204da
fix(design): changed add to linked dashboards button and added succes…
cesco-f Jun 11, 2025
7ac4e6a
test(alert details): added a test in alert details tests
cesco-f Jun 11, 2025
34bb04c
fix(suggested dashboards): suggested dashboards are filtered in the b…
cesco-f Jun 12, 2025
e73845d
feat(linked dashboards): linked dashboards are now coming from the re…
cesco-f Jun 12, 2025
d7c409c
fix(refetch): dashboards are refetched when a suggested one is promoted
cesco-f Jun 12, 2025
3c95e2d
related dashboards api - handle missing dashboards gracefully'
dominiqueclarke Jun 12, 2025
a5f10d2
fix(refetch rule): rule is also refetched after adding a suggested da…
cesco-f Jun 12, 2025
ad9ba1f
fix(dashboards number): related dashboards number is the sum of linke…
cesco-f Jun 12, 2025
183d707
fix(refetch): minor fix
cesco-f Jun 12, 2025
14b02cd
fix(cr): cr comments
cesco-f Jun 13, 2025
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 @@ -11,6 +11,7 @@ import { relevantPanelSchema } from '../relevant_panel/latest';
export const relatedDashboardSchema = z.object({
id: z.string(),
title: z.string(),
description: z.string(),
matchedBy: z.object({
fields: z.array(z.string()).optional(),
index: z.array(z.string()).optional(),
Expand All @@ -23,6 +24,7 @@ export const relatedDashboardSchema = z.object({
export const suggestedDashboardSchema = z.object({
id: z.string(),
title: z.string(),
description: z.string(),
matchedBy: z.object({
fields: z.array(z.string()).optional(),
index: z.array(z.string()).optional(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,3 +39,7 @@ export const OBSERVABILITY_RULE_TYPE_IDS_WITH_SUPPORTED_STACK_RULE_TYPES = [
...OBSERVABILITY_RULE_TYPE_IDS,
...STACK_RULE_TYPE_IDS_SUPPORTED_BY_OBSERVABILITY,
];

export enum ALERTS_API_URLS {
Comment thread
cesco-f marked this conversation as resolved.
INTERNAL_RELATED_DASHBOARDS = '/internal/observability/alerts/related_dashboards',
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import { observabilityAIAssistantPluginMock } from '@kbn/observability-ai-assist
import { useBreadcrumbs, TagsList } from '@kbn/observability-shared-plugin/public';
import { RuleTypeModel, ValidationResult } from '@kbn/triggers-actions-ui-plugin/public';
import { ruleTypeRegistryMock } from '@kbn/triggers-actions-ui-plugin/public/application/rule_type_registry.mock';
import { dashboardServiceProvider } from '@kbn/response-ops-rule-form/src/common';
import { waitFor } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { Chance } from 'chance';
Expand Down Expand Up @@ -49,12 +48,36 @@ const ruleType: RuleTypeModel = {
ruleParamsExpression: () => <Fragment />,
alertDetailsAppSection: () => <Fragment />,
};

jest.mock('./hooks/use_add_suggested_dashboard', () => ({
useAddSuggestedDashboards: () => ({
onClickAddSuggestedDashboard: jest.fn(),
addingDashboardId: undefined,
}),
}));

jest.mock('./hooks/use_related_dashboards', () => ({
useRelatedDashboards: () => ({
isLoadingSuggestedDashboards: false,
suggestedDashboards: [
{
id: 'suggested-dashboard-1',
title: 'Suggested Dashboard 1',
description: 'A suggested dashboard for testing',
},
],
linkedDashboards: [
{
id: 'dashboard-1',
},
],
}),
}));

const ruleTypeRegistry = ruleTypeRegistryMock.create();

const useKibanaMock = useKibana as jest.Mock;

const dashboardServiceProviderMock = dashboardServiceProvider as jest.Mock;

const mockObservabilityAIAssistant = observabilityAIAssistantPluginMock.createStartContract();

const mockKibana = () => {
Expand All @@ -76,26 +99,30 @@ const mockKibana = () => {
});
};

const MOCK_RULE_TYPE_ID = 'observability.rules.custom_threshold';

const MOCK_RULE = {
id: 'ruleId',
name: 'ruleName',
ruleTypeId: MOCK_RULE_TYPE_ID,
consumer: 'logs',
artifacts: {
dashboards: [
{
id: 'dashboard-1',
},
{
id: 'dashboard-2',
},
],
},
};
jest.mock('../../hooks/use_fetch_alert_detail');
jest.mock('../../hooks/use_fetch_rule', () => {
return {
useFetchRule: () => ({
reloadRule: jest.fn(),
rule: {
id: 'ruleId',
name: 'ruleName',
consumer: 'logs',
artifacts: {
dashboards: [
{
id: 'dashboard-1',
},
{
id: 'dashboard-2',
},
],
},
},
rule: MOCK_RULE,
}),
};
});
Expand All @@ -112,14 +139,6 @@ const TagsListMock = TagsList as jest.Mock;

usePerformanceContextMock.mockReturnValue({ onPageReady: jest.fn() });

dashboardServiceProviderMock.mockReturnValue({
fetchValidDashboards: jest.fn().mockResolvedValue([
{
id: 'dashboard-1',
},
]),
});

const chance = new Chance();
const params = {
alertId: chance.guid(),
Expand Down Expand Up @@ -168,7 +187,7 @@ describe('Alert details', () => {

expect(alertDetails.queryByTestId('alertDetails')).toBeTruthy();
expect(alertDetails.queryByTestId('alertDetailsError')).toBeFalsy();
expect(alertDetails.queryByTestId('alertDetailsPageTitle')).toBeTruthy();
expect(alertDetails.queryByTestId(MOCK_RULE_TYPE_ID)).toBeTruthy();
expect(alertDetails.queryByTestId('alertDetailsTabbedContent')).toBeTruthy();
expect(alertDetails.queryByTestId('alert-summary-container')).toBeFalsy();
expect(alertDetails.queryByTestId('overviewTab')).toBeTruthy();
Expand Down Expand Up @@ -211,4 +230,33 @@ describe('Alert details', () => {
expect(alertDetails.queryByTestId('alertDetailsError')).toBeFalsy();
expect(alertDetails.queryByTestId('alertDetails')).toBeFalsy();
});

it('should navigate to Related Dashboards tab and display linked and suggested dashboards', async () => {
useFetchAlertDetailMock.mockReturnValue([false, alertDetail]);

const alertDetails = renderComponent();

await waitFor(() => expect(alertDetails.queryByTestId('centerJustifiedSpinner')).toBeFalsy());

// Find and click the Related Dashboards tab
const relatedDashboardsTab = alertDetails.getByText(/Related dashboards/);
expect(relatedDashboardsTab).toBeTruthy();
expect(relatedDashboardsTab.textContent).toContain('2');

// Click on the Related Dashboards tab
await userEvent.click(relatedDashboardsTab);

// Check that linked dashboards section is displayed
expect(alertDetails.queryByTestId('linked-dashboards')).toBeTruthy();

// Check that suggested dashboards section is displayed
expect(alertDetails.queryByTestId('suggested-dashboards')).toBeTruthy();

// Verify the suggested dashboard from our mock is displayed
expect(alertDetails.queryByText('Suggested Dashboard 1')).toBeTruthy();
expect(alertDetails.queryByText('A suggested dashboard for testing')).toBeTruthy();
expect(
alertDetails.queryByTestId('addSuggestedDashboard_alertDetailsPage_custom_threshold')
).toBeTruthy();
});
});
Loading