mirror of
https://github.com/open-metadata/OpenMetadata.git
synced 2025-08-27 18:36:08 +00:00
fix kpi data not showing in widget (#17594)
This commit is contained in:
parent
60ed221cf1
commit
7813d82b91
@ -22,6 +22,11 @@ test.use({ storageState: 'playwright/.auth/admin.json' });
|
||||
|
||||
test.describe.configure({ mode: 'serial' });
|
||||
|
||||
const DESCRIPTION_WITH_PERCENTAGE =
|
||||
'playwright-description-with-percentage-percentage';
|
||||
|
||||
const DESCRIPTION_WITH_OWNER = 'playwright-owner-with-percentage-percentage';
|
||||
|
||||
test.describe('Data Insight Page', { tag: '@data-insight' }, () => {
|
||||
test.beforeAll(async ({ browser }) => {
|
||||
const { apiContext } = await createNewPage(browser);
|
||||
@ -137,14 +142,10 @@ test.describe('Data Insight Page', { tag: '@data-insight' }, () => {
|
||||
|
||||
await expect(page.getByTestId('kpi-card')).toBeVisible();
|
||||
await expect(
|
||||
page.locator(
|
||||
'[data-row-key="playwright-description-with-percentage-percentage"]'
|
||||
)
|
||||
page.locator(`[data-row-key=${DESCRIPTION_WITH_PERCENTAGE}]`)
|
||||
).toBeVisible();
|
||||
await expect(
|
||||
page.locator(
|
||||
'[data-row-key="playwright-owner-with-percentage-percentage"]'
|
||||
)
|
||||
page.locator(`[data-row-key=${DESCRIPTION_WITH_OWNER}]`)
|
||||
).toBeVisible();
|
||||
});
|
||||
|
||||
@ -162,6 +163,20 @@ test.describe('Data Insight Page', { tag: '@data-insight' }, () => {
|
||||
}
|
||||
});
|
||||
|
||||
test('Verify KPI widget in Landing page', async ({ page }) => {
|
||||
const kpiResponse = page.waitForResponse('/api/v1/kpi/*/kpiResult?*');
|
||||
|
||||
await redirectToHomePage(page);
|
||||
|
||||
await kpiResponse;
|
||||
|
||||
expect(page.locator('[data-testid="kpi-widget"]')).toBeVisible();
|
||||
|
||||
// description and owner data to be visible
|
||||
expect(page.getByTestId(DESCRIPTION_WITH_PERCENTAGE)).toBeVisible();
|
||||
expect(page.getByTestId(DESCRIPTION_WITH_OWNER)).toBeVisible();
|
||||
});
|
||||
|
||||
test('Delete Kpi', async ({ page }) => {
|
||||
await page.waitForResponse(
|
||||
'/api/v1/kpi/playwright-owner-with-percentage-percentage/latestKpiResult'
|
||||
|
@ -33,12 +33,11 @@ import {
|
||||
} from '../../../../constants/constants';
|
||||
import { DATA_INSIGHT_GRAPH_COLORS } from '../../../../constants/DataInsight.constants';
|
||||
import { DATA_INSIGHT_DOCS } from '../../../../constants/docs.constants';
|
||||
import { SIZE } from '../../../../enums/common.enum';
|
||||
import { ERROR_PLACEHOLDER_TYPE, SIZE } from '../../../../enums/common.enum';
|
||||
import { WidgetWidths } from '../../../../enums/CustomizablePage.enum';
|
||||
import { TabSpecificField } from '../../../../enums/entity.enum';
|
||||
import { Kpi, KpiResult } from '../../../../generated/dataInsight/kpi/kpi';
|
||||
import { UIKpiResult } from '../../../../interface/data-insight.interface';
|
||||
import { useDataInsightProvider } from '../../../../pages/DataInsightPage/DataInsightProvider';
|
||||
import { DataInsightCustomChartResult } from '../../../../rest/DataInsightAPI';
|
||||
import {
|
||||
getLatestKpiResult,
|
||||
@ -46,42 +45,17 @@ import {
|
||||
getListKPIs,
|
||||
} from '../../../../rest/KpiAPI';
|
||||
import { Transi18next } from '../../../../utils/CommonUtils';
|
||||
import { customFormatDateTime } from '../../../../utils/date-time/DateTimeUtils';
|
||||
import {
|
||||
customFormatDateTime,
|
||||
getCurrentMillis,
|
||||
getEpochMillisForPastDays,
|
||||
} from '../../../../utils/date-time/DateTimeUtils';
|
||||
import { showErrorToast } from '../../../../utils/ToastUtils';
|
||||
import ErrorPlaceHolder from '../../../common/ErrorWithPlaceholder/ErrorPlaceHolder';
|
||||
import KPILatestResultsV1 from '../../../DataInsight/KPILatestResultsV1';
|
||||
import './kpi-widget.less';
|
||||
import { KPIWidgetProps } from './KPIWidget.interface';
|
||||
|
||||
const EmptyPlaceholder = () => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
return (
|
||||
<div className="flex-center flex-col h-full p-t-sm">
|
||||
<KPIEmptyIcon width={SIZE.X_SMALL} />
|
||||
<div className="m-t-xs text-center">
|
||||
<Typography.Paragraph style={{ marginBottom: '0' }}>
|
||||
{t('message.no-kpi')}
|
||||
</Typography.Paragraph>
|
||||
<Typography.Paragraph>
|
||||
<Transi18next
|
||||
i18nKey="message.refer-to-our-doc"
|
||||
renderElement={
|
||||
<Link
|
||||
rel="noreferrer"
|
||||
target="_blank"
|
||||
to={{ pathname: DATA_INSIGHT_DOCS }}
|
||||
/>
|
||||
}
|
||||
values={{
|
||||
doc: t('label.doc-plural-lowercase'),
|
||||
}}
|
||||
/>
|
||||
</Typography.Paragraph>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const KPIWidget = ({
|
||||
isEditView = false,
|
||||
selectedDays = CHART_WIDGET_DAYS_DURATION,
|
||||
@ -98,12 +72,11 @@ const KPIWidget = ({
|
||||
const [kpiLatestResults, setKpiLatestResults] =
|
||||
useState<Record<string, UIKpiResult>>();
|
||||
const [isLoading, setIsLoading] = useState<boolean>(false);
|
||||
const { chartFilter } = useDataInsightProvider();
|
||||
|
||||
const getKPIResult = async (kpi: Kpi) => {
|
||||
const response = await getListKpiResult(kpi.fullyQualifiedName ?? '', {
|
||||
startTs: chartFilter.startTs,
|
||||
endTs: chartFilter.endTs,
|
||||
startTs: getEpochMillisForPastDays(selectedDays),
|
||||
endTs: getCurrentMillis(),
|
||||
});
|
||||
|
||||
return { name: kpi.name, data: response.results };
|
||||
@ -253,7 +226,28 @@ const KPIWidget = ({
|
||||
</Col>
|
||||
</Row>
|
||||
{isEmpty(kpiList) || isEmpty(kpiResults) ? (
|
||||
<EmptyPlaceholder />
|
||||
<ErrorPlaceHolder
|
||||
icon={<KPIEmptyIcon height={SIZE.X_SMALL} width={SIZE.X_SMALL} />}
|
||||
type={ERROR_PLACEHOLDER_TYPE.CUSTOM}>
|
||||
<Typography.Paragraph style={{ marginBottom: '0' }}>
|
||||
{t('message.no-kpi')}
|
||||
</Typography.Paragraph>
|
||||
<Typography.Paragraph>
|
||||
<Transi18next
|
||||
i18nKey="message.refer-to-our-doc"
|
||||
renderElement={
|
||||
<Link
|
||||
rel="noreferrer"
|
||||
target="_blank"
|
||||
to={{ pathname: DATA_INSIGHT_DOCS }}
|
||||
/>
|
||||
}
|
||||
values={{
|
||||
doc: t('label.doc-plural-lowercase'),
|
||||
}}
|
||||
/>
|
||||
</Typography.Paragraph>
|
||||
</ErrorPlaceHolder>
|
||||
) : (
|
||||
<Row className="p-t-md">
|
||||
<Col span={isWidgetSizeMedium ? 14 : 24}>
|
||||
|
@ -0,0 +1,145 @@
|
||||
/*
|
||||
* Copyright 2024 Collate.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import { fireEvent, render, screen } from '@testing-library/react';
|
||||
import React from 'react';
|
||||
import { act } from 'react-test-renderer';
|
||||
import { WidgetWidths } from '../../../../enums/CustomizablePage.enum';
|
||||
import { MOCK_KPI_LIST_RESPONSE } from '../../../../pages/KPIPage/KPIMock.mock';
|
||||
import { getListKPIs } from '../../../../rest/KpiAPI';
|
||||
import KPIWidget from './KPIWidget.component';
|
||||
|
||||
jest.mock('../../../../constants/DataInsight.constants', () => ({
|
||||
DATA_INSIGHT_GRAPH_COLORS: ['#E7B85D'],
|
||||
}));
|
||||
|
||||
jest.mock('../../../../constants/constants', () => ({
|
||||
CHART_WIDGET_DAYS_DURATION: 14,
|
||||
GRAPH_BACKGROUND_COLOR: '#000000',
|
||||
}));
|
||||
|
||||
jest.mock('../../../../utils/date-time/DateTimeUtils', () => ({
|
||||
customFormatDateTime: jest.fn().mockReturnValue('Dec 05, 11:54'),
|
||||
getCurrentMillis: jest.fn().mockReturnValue(1711583974000),
|
||||
getEpochMillisForPastDays: jest.fn().mockReturnValue(1709424034000),
|
||||
}));
|
||||
|
||||
jest.mock('../../../../rest/DataInsightAPI', () => ({
|
||||
DataInsightCustomChartResult: jest
|
||||
.fn()
|
||||
.mockImplementation(() => Promise.resolve()),
|
||||
}));
|
||||
|
||||
jest.mock('../../../../rest/KpiAPI', () => ({
|
||||
getLatestKpiResult: jest.fn().mockImplementation(() =>
|
||||
Promise.resolve({
|
||||
timestamp: 1724760319723,
|
||||
kpiFqn: 'description-percentage',
|
||||
targetResult: [
|
||||
{
|
||||
value: '23.52941176470588',
|
||||
targetMet: false,
|
||||
},
|
||||
],
|
||||
})
|
||||
),
|
||||
getListKpiResult: jest.fn().mockImplementation(() =>
|
||||
Promise.resolve({
|
||||
results: [
|
||||
{
|
||||
count: 23.52941176470588,
|
||||
day: 1724716800000,
|
||||
},
|
||||
],
|
||||
})
|
||||
),
|
||||
getListKPIs: jest
|
||||
.fn()
|
||||
.mockImplementation(() => Promise.resolve(MOCK_KPI_LIST_RESPONSE)),
|
||||
}));
|
||||
|
||||
jest.mock('../../../../utils/ToastUtils', () => ({
|
||||
showErrorToast: jest.fn(),
|
||||
}));
|
||||
|
||||
jest.mock('../../../../utils/CommonUtils', () => ({
|
||||
Transi18next: jest.fn().mockReturnValue('text'),
|
||||
}));
|
||||
|
||||
jest.mock('../../../DataInsight/KPILatestResultsV1', () =>
|
||||
jest.fn().mockReturnValue(<p>KPILatestResultsV1.Component</p>)
|
||||
);
|
||||
|
||||
jest.mock('../../../common/ErrorWithPlaceholder/ErrorPlaceHolder', () =>
|
||||
jest.fn().mockReturnValue(<p>ErrorPlaceHolder.Component</p>)
|
||||
);
|
||||
|
||||
const mockHandleRemoveWidget = jest.fn();
|
||||
|
||||
const widgetProps = {
|
||||
selectedGridSize: WidgetWidths.medium,
|
||||
isEditView: true,
|
||||
widgetKey: 'testWidgetKey',
|
||||
handleRemoveWidget: mockHandleRemoveWidget,
|
||||
};
|
||||
|
||||
describe('KPIWidget', () => {
|
||||
it('should fetch kpi list api initially', async () => {
|
||||
render(<KPIWidget {...widgetProps} />);
|
||||
|
||||
expect(getListKPIs).toHaveBeenCalledWith({ fields: 'dataInsightChart' });
|
||||
});
|
||||
|
||||
it('should handle close click when in edit view', async () => {
|
||||
await act(async () => {
|
||||
render(<KPIWidget {...widgetProps} />);
|
||||
});
|
||||
|
||||
fireEvent.click(screen.getByTestId('remove-widget-button'));
|
||||
|
||||
expect(mockHandleRemoveWidget).toHaveBeenCalledWith(widgetProps.widgetKey);
|
||||
});
|
||||
|
||||
it('should render charts and data if present', async () => {
|
||||
await act(async () => {
|
||||
render(<KPIWidget {...widgetProps} />);
|
||||
});
|
||||
|
||||
expect(screen.getByText('label.kpi-title')).toBeInTheDocument();
|
||||
expect(
|
||||
screen.getByText('KPILatestResultsV1.Component')
|
||||
).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should not render data if selectedGridSize is small', async () => {
|
||||
await act(async () => {
|
||||
render(
|
||||
<KPIWidget {...widgetProps} selectedGridSize={WidgetWidths.small} />
|
||||
);
|
||||
});
|
||||
|
||||
expect(screen.getByText('label.kpi-title')).toBeInTheDocument();
|
||||
expect(
|
||||
screen.queryByText('KPILatestResultsV1.Component')
|
||||
).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should render ErrorPlaceholder if no data there', async () => {
|
||||
(getListKPIs as jest.Mock).mockImplementation(() => Promise.resolve());
|
||||
|
||||
await act(async () => {
|
||||
render(<KPIWidget {...widgetProps} />);
|
||||
});
|
||||
|
||||
expect(screen.getByText('ErrorPlaceHolder.Component')).toBeInTheDocument();
|
||||
});
|
||||
});
|
@ -442,3 +442,36 @@ export const DESCRIPTION_CHART = {
|
||||
href: 'http://localhost:8585/api/v1/analytics/dataInsights/charts/7dc794d3-1881-408c-92fc-6182aa453bc8',
|
||||
deleted: false,
|
||||
};
|
||||
|
||||
export const MOCK_KPI_LIST_RESPONSE = {
|
||||
data: [
|
||||
{
|
||||
id: '17651e36-2350-414a-a68d-bea58cc96d02',
|
||||
name: 'description-percentage',
|
||||
displayName: 'description',
|
||||
fullyQualifiedName: 'description-percentage',
|
||||
description: 'this is description',
|
||||
metricType: 'PERCENTAGE',
|
||||
dataInsightChart: {
|
||||
id: 'e10d1bef-0d6b-42cd-a215-5771f40803eb',
|
||||
type: 'dataInsightCustomChart',
|
||||
name: 'percentage_of_data_asset_with_description_kpi',
|
||||
fullyQualifiedName: 'percentage_of_data_asset_with_description_kpi',
|
||||
displayName: 'percentage_of_data_asset_with_description_kpi',
|
||||
deleted: false,
|
||||
href: 'http://localhost:8585/api/v1/analytics/dataInsights/system/charts/e10d1bef-0d6b-42cd-a215-5771f40803eb',
|
||||
},
|
||||
targetValue: 58,
|
||||
startDate: 1724697000000,
|
||||
endDate: 1725128999999,
|
||||
version: 0.1,
|
||||
updatedAt: 1724760086039,
|
||||
updatedBy: 'admin',
|
||||
href: 'http://localhost:8585/api/v1/kpi/17651e36-2350-414a-a68d-bea58cc96d02',
|
||||
deleted: false,
|
||||
},
|
||||
],
|
||||
paging: {
|
||||
total: 1,
|
||||
},
|
||||
};
|
||||
|
Loading…
x
Reference in New Issue
Block a user