Skip to content

Commit

Permalink
fix kpi data not showing in widget (#17594)
Browse files Browse the repository at this point in the history
  • Loading branch information
Ashish8689 authored Aug 27, 2024
1 parent 60ed221 commit 7813d82
Show file tree
Hide file tree
Showing 4 changed files with 230 additions and 43 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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();
});

Expand All @@ -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'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,55 +33,29 @@ 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,
getListKpiResult,
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,
Expand All @@ -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 };
Expand Down Expand Up @@ -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}>
Expand Down
Original file line number Diff line number Diff line change
@@ -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();
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -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,
},
};

0 comments on commit 7813d82

Please sign in to comment.