mirror of
https://github.com/open-metadata/OpenMetadata.git
synced 2025-11-07 14:31:08 +00:00
GEN-1296: sort test cases by latest run (#18097)
* GEN-1296: sort test cases by latest run * minor fix * added sort support for name field * fixed unit test * fixed failing playwright test * fixed failing playwright test
This commit is contained in:
parent
49fceb4674
commit
a74811481f
@ -79,4 +79,7 @@ Thumbs.db
|
|||||||
src/generated
|
src/generated
|
||||||
|
|
||||||
# Snapshots
|
# Snapshots
|
||||||
*.snap
|
*.snap
|
||||||
|
|
||||||
|
# env
|
||||||
|
".env"
|
||||||
@ -231,7 +231,7 @@ test.describe('Incident Manager', PLAYWRIGHT_INGESTION_TAG_OBJ, () => {
|
|||||||
await test.step('Resolve task from incident list page', async () => {
|
await test.step('Resolve task from incident list page', async () => {
|
||||||
await visitProfilerTab(page, table1);
|
await visitProfilerTab(page, table1);
|
||||||
const testCaseResponse = page.waitForResponse(
|
const testCaseResponse = page.waitForResponse(
|
||||||
'/api/v1/dataQuality/testCases/search/list?fields=*'
|
'/api/v1/dataQuality/testCases/search/list?*fields=*'
|
||||||
);
|
);
|
||||||
await page
|
await page
|
||||||
.getByTestId('profiler-tab-left-panel')
|
.getByTestId('profiler-tab-left-panel')
|
||||||
@ -277,7 +277,7 @@ test.describe('Incident Manager', PLAYWRIGHT_INGESTION_TAG_OBJ, () => {
|
|||||||
await test.step('Task should be closed', async () => {
|
await test.step('Task should be closed', async () => {
|
||||||
await visitProfilerTab(page, table1);
|
await visitProfilerTab(page, table1);
|
||||||
const testCaseResponse = page.waitForResponse(
|
const testCaseResponse = page.waitForResponse(
|
||||||
'/api/v1/dataQuality/testCases/search/list?fields=*'
|
'/api/v1/dataQuality/testCases/search/list?*fields=*'
|
||||||
);
|
);
|
||||||
await page
|
await page
|
||||||
.getByTestId('profiler-tab-left-panel')
|
.getByTestId('profiler-tab-left-panel')
|
||||||
@ -373,7 +373,7 @@ test.describe('Incident Manager', PLAYWRIGHT_INGESTION_TAG_OBJ, () => {
|
|||||||
await test.step("Verify incident's status on DQ page", async () => {
|
await test.step("Verify incident's status on DQ page", async () => {
|
||||||
await visitProfilerTab(page, table1);
|
await visitProfilerTab(page, table1);
|
||||||
const testCaseResponse = page.waitForResponse(
|
const testCaseResponse = page.waitForResponse(
|
||||||
'/api/v1/dataQuality/testCases/search/list?fields=*'
|
'/api/v1/dataQuality/testCases/search/list?*fields=*'
|
||||||
);
|
);
|
||||||
await page
|
await page
|
||||||
.getByTestId('profiler-tab-left-panel')
|
.getByTestId('profiler-tab-left-panel')
|
||||||
|
|||||||
@ -130,7 +130,7 @@ test('Table test case', PLAYWRIGHT_INGESTION_TAG_OBJ, async ({ page }) => {
|
|||||||
).toBeVisible();
|
).toBeVisible();
|
||||||
|
|
||||||
const testCaseResponse = page.waitForResponse(
|
const testCaseResponse = page.waitForResponse(
|
||||||
'/api/v1/dataQuality/testCases/search/list?fields=*'
|
'/api/v1/dataQuality/testCases/search/list?*fields=*'
|
||||||
);
|
);
|
||||||
await page.click(`[data-testid="view-service-button"]`);
|
await page.click(`[data-testid="view-service-button"]`);
|
||||||
await testCaseResponse;
|
await testCaseResponse;
|
||||||
@ -210,7 +210,7 @@ test('Column test case', PLAYWRIGHT_INGESTION_TAG_OBJ, async ({ page }) => {
|
|||||||
await page.waitForSelector('[data-testid="view-service-button"]');
|
await page.waitForSelector('[data-testid="view-service-button"]');
|
||||||
|
|
||||||
const testCaseResponse = page.waitForResponse(
|
const testCaseResponse = page.waitForResponse(
|
||||||
'/api/v1/dataQuality/testCases/search/list?fields=*'
|
'/api/v1/dataQuality/testCases/search/list?*fields=*'
|
||||||
);
|
);
|
||||||
await page.click(`[data-testid="view-service-button"]`);
|
await page.click(`[data-testid="view-service-button"]`);
|
||||||
await testCaseResponse;
|
await testCaseResponse;
|
||||||
|
|||||||
@ -99,7 +99,7 @@ test('Table difference test case', async ({ page }) => {
|
|||||||
await page.getByTestId('submit-test').click();
|
await page.getByTestId('submit-test').click();
|
||||||
await createTestCaseResponse;
|
await createTestCaseResponse;
|
||||||
const tableTestResponse = page.waitForResponse(
|
const tableTestResponse = page.waitForResponse(
|
||||||
`/api/v1/dataQuality/testCases/search/list?fields=*`
|
`/api/v1/dataQuality/testCases/search/list?*fields=*`
|
||||||
);
|
);
|
||||||
await page.getByTestId('view-service-button').click();
|
await page.getByTestId('view-service-button').click();
|
||||||
await tableTestResponse;
|
await tableTestResponse;
|
||||||
@ -196,7 +196,7 @@ test('Custom SQL Query', async ({ page }) => {
|
|||||||
await page.getByTestId('submit-test').click();
|
await page.getByTestId('submit-test').click();
|
||||||
await createTestCaseResponse;
|
await createTestCaseResponse;
|
||||||
const tableTestResponse = page.waitForResponse(
|
const tableTestResponse = page.waitForResponse(
|
||||||
`/api/v1/dataQuality/testCases/search/list?fields=*`
|
`/api/v1/dataQuality/testCases/search/list?*fields=*`
|
||||||
);
|
);
|
||||||
await page.getByTestId('view-service-button').click();
|
await page.getByTestId('view-service-button').click();
|
||||||
await tableTestResponse;
|
await tableTestResponse;
|
||||||
@ -300,7 +300,7 @@ test('Column Values To Be Not Null', async ({ page }) => {
|
|||||||
await page.waitForSelector('[data-testid="success-line"]');
|
await page.waitForSelector('[data-testid="success-line"]');
|
||||||
await page.waitForSelector('[data-testid="view-service-button"]');
|
await page.waitForSelector('[data-testid="view-service-button"]');
|
||||||
const testCaseResponse = page.waitForResponse(
|
const testCaseResponse = page.waitForResponse(
|
||||||
'/api/v1/dataQuality/testCases/search/list?fields=*'
|
'/api/v1/dataQuality/testCases/search/list?*fields=*'
|
||||||
);
|
);
|
||||||
await page.click(`[data-testid="view-service-button"]`);
|
await page.click(`[data-testid="view-service-button"]`);
|
||||||
await testCaseResponse;
|
await testCaseResponse;
|
||||||
|
|||||||
@ -32,7 +32,7 @@ export const visitDataQualityTab = async (page: Page, table: TableClass) => {
|
|||||||
await table.visitEntityPage(page);
|
await table.visitEntityPage(page);
|
||||||
await page.getByTestId('profiler').click();
|
await page.getByTestId('profiler').click();
|
||||||
const testCaseResponse = page.waitForResponse(
|
const testCaseResponse = page.waitForResponse(
|
||||||
'/api/v1/dataQuality/testCases/search/list?fields=*'
|
'/api/v1/dataQuality/testCases/search/list?*fields=*'
|
||||||
);
|
);
|
||||||
await page
|
await page
|
||||||
.getByTestId('profiler-tab-left-panel')
|
.getByTestId('profiler-tab-left-panel')
|
||||||
|
|||||||
@ -53,13 +53,14 @@ import {
|
|||||||
TIER_CATEGORY,
|
TIER_CATEGORY,
|
||||||
} from '../../../constants/constants';
|
} from '../../../constants/constants';
|
||||||
import {
|
import {
|
||||||
|
DEFAULT_SORT_ORDER,
|
||||||
TEST_CASE_FILTERS,
|
TEST_CASE_FILTERS,
|
||||||
TEST_CASE_PLATFORM_OPTION,
|
TEST_CASE_PLATFORM_OPTION,
|
||||||
TEST_CASE_STATUS_OPTION,
|
TEST_CASE_STATUS_OPTION,
|
||||||
TEST_CASE_TYPE_OPTION,
|
TEST_CASE_TYPE_OPTION,
|
||||||
} from '../../../constants/profiler.constant';
|
} from '../../../constants/profiler.constant';
|
||||||
import { usePermissionProvider } from '../../../context/PermissionProvider/PermissionProvider';
|
import { usePermissionProvider } from '../../../context/PermissionProvider/PermissionProvider';
|
||||||
import { ERROR_PLACEHOLDER_TYPE, SORT_ORDER } from '../../../enums/common.enum';
|
import { ERROR_PLACEHOLDER_TYPE } from '../../../enums/common.enum';
|
||||||
import { TabSpecificField } from '../../../enums/entity.enum';
|
import { TabSpecificField } from '../../../enums/entity.enum';
|
||||||
import { SearchIndex } from '../../../enums/search.enum';
|
import { SearchIndex } from '../../../enums/search.enum';
|
||||||
import { TestCase } from '../../../generated/tests/testCase';
|
import { TestCase } from '../../../generated/tests/testCase';
|
||||||
@ -68,7 +69,10 @@ import useCustomLocation from '../../../hooks/useCustomLocation/useCustomLocatio
|
|||||||
import { DataQualityPageTabs } from '../../../pages/DataQuality/DataQualityPage.interface';
|
import { DataQualityPageTabs } from '../../../pages/DataQuality/DataQualityPage.interface';
|
||||||
import { searchQuery } from '../../../rest/searchAPI';
|
import { searchQuery } from '../../../rest/searchAPI';
|
||||||
import { getTags } from '../../../rest/tagAPI';
|
import { getTags } from '../../../rest/tagAPI';
|
||||||
import { getListTestCaseBySearch } from '../../../rest/testAPI';
|
import {
|
||||||
|
getListTestCaseBySearch,
|
||||||
|
ListTestCaseParamsBySearch,
|
||||||
|
} from '../../../rest/testAPI';
|
||||||
import { getTestCaseFiltersValue } from '../../../utils/DataQuality/DataQualityUtils';
|
import { getTestCaseFiltersValue } from '../../../utils/DataQuality/DataQualityUtils';
|
||||||
import { getEntityName } from '../../../utils/EntityUtils';
|
import { getEntityName } from '../../../utils/EntityUtils';
|
||||||
import { getDataQualityPagePath } from '../../../utils/RouterUtils';
|
import { getDataQualityPagePath } from '../../../utils/RouterUtils';
|
||||||
@ -94,6 +98,8 @@ export const TestCases = ({ summaryPanel }: { summaryPanel: ReactNode }) => {
|
|||||||
const [tagOptions, setTagOptions] = useState<DefaultOptionType[]>([]);
|
const [tagOptions, setTagOptions] = useState<DefaultOptionType[]>([]);
|
||||||
const [tierOptions, setTierOptions] = useState<DefaultOptionType[]>([]);
|
const [tierOptions, setTierOptions] = useState<DefaultOptionType[]>([]);
|
||||||
const [serviceOptions, setServiceOptions] = useState<DefaultOptionType[]>([]);
|
const [serviceOptions, setServiceOptions] = useState<DefaultOptionType[]>([]);
|
||||||
|
const [sortOptions, setSortOptions] =
|
||||||
|
useState<ListTestCaseParamsBySearch>(DEFAULT_SORT_ORDER);
|
||||||
|
|
||||||
const params = useMemo(() => {
|
const params = useMemo(() => {
|
||||||
const search = location.search;
|
const search = location.search;
|
||||||
@ -146,7 +152,8 @@ export const TestCases = ({ summaryPanel }: { summaryPanel: ReactNode }) => {
|
|||||||
|
|
||||||
const fetchTestCases = async (
|
const fetchTestCases = async (
|
||||||
currentPage = INITIAL_PAGING_VALUE,
|
currentPage = INITIAL_PAGING_VALUE,
|
||||||
filters?: string[]
|
filters?: string[],
|
||||||
|
apiParams?: ListTestCaseParamsBySearch
|
||||||
) => {
|
) => {
|
||||||
const updatedParams = getTestCaseFiltersValue(
|
const updatedParams = getTestCaseFiltersValue(
|
||||||
params,
|
params,
|
||||||
@ -157,6 +164,8 @@ export const TestCases = ({ summaryPanel }: { summaryPanel: ReactNode }) => {
|
|||||||
try {
|
try {
|
||||||
const { data, paging } = await getListTestCaseBySearch({
|
const { data, paging } = await getListTestCaseBySearch({
|
||||||
...updatedParams,
|
...updatedParams,
|
||||||
|
...sortOptions,
|
||||||
|
...apiParams,
|
||||||
testCaseStatus: isEmpty(params?.testCaseStatus)
|
testCaseStatus: isEmpty(params?.testCaseStatus)
|
||||||
? undefined
|
? undefined
|
||||||
: params?.testCaseStatus,
|
: params?.testCaseStatus,
|
||||||
@ -169,8 +178,6 @@ export const TestCases = ({ summaryPanel }: { summaryPanel: ReactNode }) => {
|
|||||||
],
|
],
|
||||||
q: searchValue ? `*${searchValue}*` : undefined,
|
q: searchValue ? `*${searchValue}*` : undefined,
|
||||||
offset: (currentPage - 1) * pageSize,
|
offset: (currentPage - 1) * pageSize,
|
||||||
sortType: SORT_ORDER.DESC,
|
|
||||||
sortField: 'testCaseResult.timestamp',
|
|
||||||
});
|
});
|
||||||
setTestCase(data);
|
setTestCase(data);
|
||||||
handlePagingChange(paging);
|
handlePagingChange(paging);
|
||||||
@ -182,6 +189,16 @@ export const TestCases = ({ summaryPanel }: { summaryPanel: ReactNode }) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const sortTestCase = async (apiParams?: TestCaseSearchParams) => {
|
||||||
|
const updatedValue = uniq([...selectedFilter, ...Object.keys(params)]);
|
||||||
|
await fetchTestCases(
|
||||||
|
INITIAL_PAGING_VALUE,
|
||||||
|
updatedValue,
|
||||||
|
apiParams ?? DEFAULT_SORT_ORDER
|
||||||
|
);
|
||||||
|
setSortOptions(apiParams ?? DEFAULT_SORT_ORDER);
|
||||||
|
};
|
||||||
|
|
||||||
const handleStatusSubmit = (testCase: TestCase) => {
|
const handleStatusSubmit = (testCase: TestCase) => {
|
||||||
setTestCase((prev) => {
|
setTestCase((prev) => {
|
||||||
const data = prev.map((test) => {
|
const data = prev.map((test) => {
|
||||||
@ -620,6 +637,7 @@ export const TestCases = ({ summaryPanel }: { summaryPanel: ReactNode }) => {
|
|||||||
url: getDataQualityPagePath(DataQualityPageTabs.TEST_CASES),
|
url: getDataQualityPagePath(DataQualityPageTabs.TEST_CASES),
|
||||||
},
|
},
|
||||||
]}
|
]}
|
||||||
|
fetchTestCases={sortTestCase}
|
||||||
isLoading={isLoading}
|
isLoading={isLoading}
|
||||||
pagingData={pagingData}
|
pagingData={pagingData}
|
||||||
showPagination={showPagination}
|
showPagination={showPagination}
|
||||||
|
|||||||
@ -27,6 +27,7 @@ import DataQualityTab from './DataQualityTab';
|
|||||||
const mockProps: DataQualityTabProps = {
|
const mockProps: DataQualityTabProps = {
|
||||||
testCases: MOCK_TEST_CASE,
|
testCases: MOCK_TEST_CASE,
|
||||||
onTestUpdate: jest.fn(),
|
onTestUpdate: jest.fn(),
|
||||||
|
fetchTestCases: jest.fn(),
|
||||||
};
|
};
|
||||||
const mockPermissionsData = {
|
const mockPermissionsData = {
|
||||||
permissions: {
|
permissions: {
|
||||||
@ -114,6 +115,76 @@ describe('DataQualityTab test', () => {
|
|||||||
expect(await findByText(header, 'label.action-plural')).toBeInTheDocument();
|
expect(await findByText(header, 'label.action-plural')).toBeInTheDocument();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('Should send API request with sort params on click of last-run', async () => {
|
||||||
|
await act(async () => {
|
||||||
|
render(<DataQualityTab {...mockProps} />);
|
||||||
|
});
|
||||||
|
const tableRows = await screen.findAllByRole('row');
|
||||||
|
const header = tableRows[0];
|
||||||
|
const lastRunHeader = await findByText(header, 'label.last-run');
|
||||||
|
|
||||||
|
expect(lastRunHeader).toBeInTheDocument();
|
||||||
|
|
||||||
|
await act(async () => {
|
||||||
|
fireEvent.click(lastRunHeader);
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(mockProps.fetchTestCases).toHaveBeenCalledWith({
|
||||||
|
sortField: 'testCaseResult.timestamp',
|
||||||
|
sortType: 'asc',
|
||||||
|
});
|
||||||
|
|
||||||
|
await act(async () => {
|
||||||
|
fireEvent.click(lastRunHeader);
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(mockProps.fetchTestCases).toHaveBeenCalledWith({
|
||||||
|
sortField: 'testCaseResult.timestamp',
|
||||||
|
sortType: 'desc',
|
||||||
|
});
|
||||||
|
|
||||||
|
await act(async () => {
|
||||||
|
fireEvent.click(lastRunHeader);
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(mockProps.fetchTestCases).toHaveBeenCalledWith(undefined);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Should send API request with sort params on click of name', async () => {
|
||||||
|
await act(async () => {
|
||||||
|
render(<DataQualityTab {...mockProps} />);
|
||||||
|
});
|
||||||
|
const tableRows = await screen.findAllByRole('row');
|
||||||
|
const header = tableRows[0];
|
||||||
|
const lastRunHeader = await findByText(header, 'label.name');
|
||||||
|
|
||||||
|
expect(lastRunHeader).toBeInTheDocument();
|
||||||
|
|
||||||
|
await act(async () => {
|
||||||
|
fireEvent.click(lastRunHeader);
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(mockProps.fetchTestCases).toHaveBeenCalledWith({
|
||||||
|
sortField: 'name.keyword',
|
||||||
|
sortType: 'asc',
|
||||||
|
});
|
||||||
|
|
||||||
|
await act(async () => {
|
||||||
|
fireEvent.click(lastRunHeader);
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(mockProps.fetchTestCases).toHaveBeenCalledWith({
|
||||||
|
sortField: 'name.keyword',
|
||||||
|
sortType: 'desc',
|
||||||
|
});
|
||||||
|
|
||||||
|
await act(async () => {
|
||||||
|
fireEvent.click(lastRunHeader);
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(mockProps.fetchTestCases).toHaveBeenCalledWith(undefined);
|
||||||
|
});
|
||||||
|
|
||||||
it('Table data should be render as per data props', async () => {
|
it('Table data should be render as per data props', async () => {
|
||||||
const firstRowData = MOCK_TEST_CASE[0];
|
const firstRowData = MOCK_TEST_CASE[0];
|
||||||
await act(async () => {
|
await act(async () => {
|
||||||
|
|||||||
@ -12,13 +12,14 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { Button, Col, Row, Skeleton, Space, Tooltip, Typography } from 'antd';
|
import { Button, Col, Row, Skeleton, Space, Tooltip, Typography } from 'antd';
|
||||||
import { ColumnsType } from 'antd/lib/table';
|
import { ColumnsType, TablePaginationConfig } from 'antd/lib/table';
|
||||||
|
import { FilterValue, SorterResult } from 'antd/lib/table/interface';
|
||||||
import { AxiosError } from 'axios';
|
import { AxiosError } from 'axios';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import { isUndefined, sortBy } from 'lodash';
|
import { isArray, isUndefined, sortBy } from 'lodash';
|
||||||
import { PagingResponse } from 'Models';
|
import { PagingResponse } from 'Models';
|
||||||
import QueryString from 'qs';
|
import QueryString from 'qs';
|
||||||
import React, { useEffect, useMemo, useState } from 'react';
|
import React, { useEffect, useMemo, useRef, useState } from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { Link } from 'react-router-dom';
|
import { Link } from 'react-router-dom';
|
||||||
import { ReactComponent as IconEdit } from '../../../../assets/svg/edit-new.svg';
|
import { ReactComponent as IconEdit } from '../../../../assets/svg/edit-new.svg';
|
||||||
@ -28,10 +29,14 @@ import { DATA_QUALITY_PROFILER_DOCS } from '../../../../constants/docs.constants
|
|||||||
import { NO_PERMISSION_FOR_ACTION } from '../../../../constants/HelperTextUtil';
|
import { NO_PERMISSION_FOR_ACTION } from '../../../../constants/HelperTextUtil';
|
||||||
import { usePermissionProvider } from '../../../../context/PermissionProvider/PermissionProvider';
|
import { usePermissionProvider } from '../../../../context/PermissionProvider/PermissionProvider';
|
||||||
import { ResourceEntity } from '../../../../context/PermissionProvider/PermissionProvider.interface';
|
import { ResourceEntity } from '../../../../context/PermissionProvider/PermissionProvider.interface';
|
||||||
|
import { SORT_ORDER } from '../../../../enums/common.enum';
|
||||||
import { EntityTabs, EntityType } from '../../../../enums/entity.enum';
|
import { EntityTabs, EntityType } from '../../../../enums/entity.enum';
|
||||||
import { TestCaseStatus } from '../../../../generated/configuration/testResultNotificationConfiguration';
|
|
||||||
import { Operation } from '../../../../generated/entity/policies/policy';
|
import { Operation } from '../../../../generated/entity/policies/policy';
|
||||||
import { TestCase, TestCaseResult } from '../../../../generated/tests/testCase';
|
import {
|
||||||
|
TestCase,
|
||||||
|
TestCaseResult,
|
||||||
|
TestCaseStatus,
|
||||||
|
} from '../../../../generated/tests/testCase';
|
||||||
import { TestCaseResolutionStatus } from '../../../../generated/tests/testCaseResolutionStatus';
|
import { TestCaseResolutionStatus } from '../../../../generated/tests/testCaseResolutionStatus';
|
||||||
import { getListTestCaseIncidentByStateId } from '../../../../rest/incidentManagerAPI';
|
import { getListTestCaseIncidentByStateId } from '../../../../rest/incidentManagerAPI';
|
||||||
import { removeTestCaseFromTestSuite } from '../../../../rest/testAPI';
|
import { removeTestCaseFromTestSuite } from '../../../../rest/testAPI';
|
||||||
@ -74,6 +79,7 @@ const DataQualityTab: React.FC<DataQualityTabProps> = ({
|
|||||||
afterDeleteAction,
|
afterDeleteAction,
|
||||||
showPagination,
|
showPagination,
|
||||||
breadcrumbData,
|
breadcrumbData,
|
||||||
|
fetchTestCases,
|
||||||
}) => {
|
}) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const { permissions } = usePermissionProvider();
|
const { permissions } = usePermissionProvider();
|
||||||
@ -82,6 +88,7 @@ const DataQualityTab: React.FC<DataQualityTabProps> = ({
|
|||||||
const [testCaseStatus, setTestCaseStatus] = useState<
|
const [testCaseStatus, setTestCaseStatus] = useState<
|
||||||
TestCaseResolutionStatus[]
|
TestCaseResolutionStatus[]
|
||||||
>([]);
|
>([]);
|
||||||
|
const isApiSortingEnabled = useRef(false);
|
||||||
|
|
||||||
const testCaseEditPermission = useMemo(() => {
|
const testCaseEditPermission = useMemo(() => {
|
||||||
return checkPermission(
|
return checkPermission(
|
||||||
@ -101,19 +108,21 @@ const DataQualityTab: React.FC<DataQualityTabProps> = ({
|
|||||||
|
|
||||||
const sortedData = useMemo(
|
const sortedData = useMemo(
|
||||||
() =>
|
() =>
|
||||||
sortBy(testCases, (test) => {
|
isApiSortingEnabled.current
|
||||||
switch (test.testCaseResult?.testCaseStatus) {
|
? testCases
|
||||||
case TestCaseStatus.Failed:
|
: sortBy(testCases, (test) => {
|
||||||
return 0;
|
switch (test.testCaseResult?.testCaseStatus) {
|
||||||
case TestCaseStatus.Aborted:
|
case TestCaseStatus.Failed:
|
||||||
return 1;
|
return 0;
|
||||||
case TestCaseStatus.Success:
|
case TestCaseStatus.Aborted:
|
||||||
return 2;
|
return 1;
|
||||||
|
case TestCaseStatus.Success:
|
||||||
|
return 2;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return 3;
|
return 3;
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
[testCases]
|
[testCases]
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -144,7 +153,7 @@ const DataQualityTab: React.FC<DataQualityTabProps> = ({
|
|||||||
dataIndex: 'name',
|
dataIndex: 'name',
|
||||||
key: 'name',
|
key: 'name',
|
||||||
width: 300,
|
width: 300,
|
||||||
sorter: (a, b) => a.name.localeCompare(b.name),
|
sorter: true,
|
||||||
sortDirections: ['ascend', 'descend'],
|
sortDirections: ['ascend', 'descend'],
|
||||||
render: (name: string, record) => {
|
render: (name: string, record) => {
|
||||||
const status = record.testCaseResult?.testCaseStatus;
|
const status = record.testCaseResult?.testCaseStatus;
|
||||||
@ -247,6 +256,7 @@ const DataQualityTab: React.FC<DataQualityTabProps> = ({
|
|||||||
dataIndex: 'testCaseResult',
|
dataIndex: 'testCaseResult',
|
||||||
key: 'lastRun',
|
key: 'lastRun',
|
||||||
width: 150,
|
width: 150,
|
||||||
|
sorter: true,
|
||||||
render: (result: TestCaseResult) =>
|
render: (result: TestCaseResult) =>
|
||||||
result?.timestamp ? formatDateTime(result.timestamp) : '--',
|
result?.timestamp ? formatDateTime(result.timestamp) : '--',
|
||||||
},
|
},
|
||||||
@ -411,6 +421,29 @@ const DataQualityTab: React.FC<DataQualityTabProps> = ({
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleTableChange = (
|
||||||
|
_pagination: TablePaginationConfig,
|
||||||
|
_filters: Record<string, FilterValue | null>,
|
||||||
|
sorter: SorterResult<TestCase> | SorterResult<TestCase>[]
|
||||||
|
) => {
|
||||||
|
if (!isArray(sorter) && fetchTestCases) {
|
||||||
|
if (sorter?.columnKey === 'lastRun' || sorter?.columnKey === 'name') {
|
||||||
|
const sortData = isUndefined(sorter.order)
|
||||||
|
? undefined
|
||||||
|
: {
|
||||||
|
sortField:
|
||||||
|
sorter?.columnKey === 'lastRun'
|
||||||
|
? 'testCaseResult.timestamp'
|
||||||
|
: 'name.keyword',
|
||||||
|
sortType:
|
||||||
|
sorter?.order === 'ascend' ? SORT_ORDER.ASC : SORT_ORDER.DESC,
|
||||||
|
};
|
||||||
|
isApiSortingEnabled.current = !isUndefined(sorter.order);
|
||||||
|
fetchTestCases(sortData);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (testCases.length) {
|
if (testCases.length) {
|
||||||
fetchTestCaseStatus();
|
fetchTestCaseStatus();
|
||||||
@ -454,6 +487,7 @@ const DataQualityTab: React.FC<DataQualityTabProps> = ({
|
|||||||
pagination={false}
|
pagination={false}
|
||||||
rowKey="id"
|
rowKey="id"
|
||||||
size="small"
|
size="small"
|
||||||
|
onChange={handleTableChange}
|
||||||
/>
|
/>
|
||||||
</Col>
|
</Col>
|
||||||
<Col span={24}>
|
<Col span={24}>
|
||||||
|
|||||||
@ -21,7 +21,10 @@ import {
|
|||||||
import { Thread } from '../../../../generated/entity/feed/thread';
|
import { Thread } from '../../../../generated/entity/feed/thread';
|
||||||
import { TestCase } from '../../../../generated/tests/testCase';
|
import { TestCase } from '../../../../generated/tests/testCase';
|
||||||
import { TestSuite } from '../../../../generated/tests/testSuite';
|
import { TestSuite } from '../../../../generated/tests/testSuite';
|
||||||
import { ListTestCaseParams } from '../../../../rest/testAPI';
|
import {
|
||||||
|
ListTestCaseParams,
|
||||||
|
ListTestCaseParamsBySearch,
|
||||||
|
} from '../../../../rest/testAPI';
|
||||||
import { NextPreviousProps } from '../../../common/NextPrevious/NextPrevious.interface';
|
import { NextPreviousProps } from '../../../common/NextPrevious/NextPrevious.interface';
|
||||||
import { TitleBreadcrumbProps } from '../../../common/TitleBreadcrumb/TitleBreadcrumb.interface';
|
import { TitleBreadcrumbProps } from '../../../common/TitleBreadcrumb/TitleBreadcrumb.interface';
|
||||||
|
|
||||||
@ -115,6 +118,7 @@ export interface DataQualityTabProps {
|
|||||||
};
|
};
|
||||||
showPagination?: boolean;
|
showPagination?: boolean;
|
||||||
breadcrumbData?: TitleBreadcrumbProps['titleLinks'];
|
breadcrumbData?: TitleBreadcrumbProps['titleLinks'];
|
||||||
|
fetchTestCases?: (params?: ListTestCaseParamsBySearch) => Promise<void>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface TestSummaryProps {
|
export interface TestSummaryProps {
|
||||||
|
|||||||
@ -16,9 +16,13 @@ import { isEmpty } from 'lodash';
|
|||||||
import React, { useMemo, useState } from 'react';
|
import React, { useMemo, useState } from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { useHistory } from 'react-router-dom';
|
import { useHistory } from 'react-router-dom';
|
||||||
import { getEntityDetailsPath } from '../../../../../constants/constants';
|
import {
|
||||||
|
getEntityDetailsPath,
|
||||||
|
INITIAL_PAGING_VALUE,
|
||||||
|
} from '../../../../../constants/constants';
|
||||||
import { PAGE_HEADERS } from '../../../../../constants/PageHeaders.constant';
|
import { PAGE_HEADERS } from '../../../../../constants/PageHeaders.constant';
|
||||||
import {
|
import {
|
||||||
|
DEFAULT_SORT_ORDER,
|
||||||
TEST_CASE_STATUS_OPTION,
|
TEST_CASE_STATUS_OPTION,
|
||||||
TEST_CASE_TYPE_OPTION,
|
TEST_CASE_TYPE_OPTION,
|
||||||
} from '../../../../../constants/profiler.constant';
|
} from '../../../../../constants/profiler.constant';
|
||||||
@ -29,7 +33,10 @@ import { ProfilerDashboardType } from '../../../../../enums/table.enum';
|
|||||||
import { TestCaseStatus } from '../../../../../generated/tests/testCase';
|
import { TestCaseStatus } from '../../../../../generated/tests/testCase';
|
||||||
import LimitWrapper from '../../../../../hoc/LimitWrapper';
|
import LimitWrapper from '../../../../../hoc/LimitWrapper';
|
||||||
import { useFqn } from '../../../../../hooks/useFqn';
|
import { useFqn } from '../../../../../hooks/useFqn';
|
||||||
import { TestCaseType } from '../../../../../rest/testAPI';
|
import {
|
||||||
|
ListTestCaseParamsBySearch,
|
||||||
|
TestCaseType,
|
||||||
|
} from '../../../../../rest/testAPI';
|
||||||
import {
|
import {
|
||||||
getBreadcrumbForTable,
|
getBreadcrumbForTable,
|
||||||
getEntityName,
|
getEntityName,
|
||||||
@ -78,6 +85,8 @@ export const QualityTab = () => {
|
|||||||
useState<TestCaseStatus>('' as TestCaseStatus);
|
useState<TestCaseStatus>('' as TestCaseStatus);
|
||||||
const [selectedTestType, setSelectedTestType] = useState(TestCaseType.all);
|
const [selectedTestType, setSelectedTestType] = useState(TestCaseType.all);
|
||||||
const [searchValue, setSearchValue] = useState<string>();
|
const [searchValue, setSearchValue] = useState<string>();
|
||||||
|
const [sortOptions, setSortOptions] =
|
||||||
|
useState<ListTestCaseParamsBySearch>(DEFAULT_SORT_ORDER);
|
||||||
const testSuite = useMemo(() => table?.testSuite, [table]);
|
const testSuite = useMemo(() => table?.testSuite, [table]);
|
||||||
|
|
||||||
const handleTestCasePageChange: NextPreviousProps['pagingHandler'] = ({
|
const handleTestCasePageChange: NextPreviousProps['pagingHandler'] = ({
|
||||||
@ -85,6 +94,7 @@ export const QualityTab = () => {
|
|||||||
}) => {
|
}) => {
|
||||||
if (currentPage) {
|
if (currentPage) {
|
||||||
fetchAllTests({
|
fetchAllTests({
|
||||||
|
...sortOptions,
|
||||||
testCaseType: selectedTestType,
|
testCaseType: selectedTestType,
|
||||||
testCaseStatus: isEmpty(selectedTestCaseStatus)
|
testCaseStatus: isEmpty(selectedTestCaseStatus)
|
||||||
? undefined
|
? undefined
|
||||||
@ -106,6 +116,12 @@ export const QualityTab = () => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleSortTestCase = async (apiParams?: ListTestCaseParamsBySearch) => {
|
||||||
|
setSortOptions(apiParams ?? DEFAULT_SORT_ORDER);
|
||||||
|
await fetchAllTests({ ...(apiParams ?? DEFAULT_SORT_ORDER), offset: 0 });
|
||||||
|
handlePageChange(INITIAL_PAGING_VALUE);
|
||||||
|
};
|
||||||
|
|
||||||
const tableBreadcrumb = useMemo(() => {
|
const tableBreadcrumb = useMemo(() => {
|
||||||
return table
|
return table
|
||||||
? [
|
? [
|
||||||
@ -147,6 +163,7 @@ export const QualityTab = () => {
|
|||||||
(await getResourceLimit('dataQuality', true, true));
|
(await getResourceLimit('dataQuality', true, true));
|
||||||
}}
|
}}
|
||||||
breadcrumbData={tableBreadcrumb}
|
breadcrumbData={tableBreadcrumb}
|
||||||
|
fetchTestCases={handleSortTestCase}
|
||||||
isLoading={isTestsLoading}
|
isLoading={isTestsLoading}
|
||||||
showTableColumn={false}
|
showTableColumn={false}
|
||||||
testCases={allTestCases}
|
testCases={allTestCases}
|
||||||
|
|||||||
@ -165,6 +165,8 @@ describe('QualityTab', () => {
|
|||||||
offset: 10,
|
offset: 10,
|
||||||
testCaseStatus: undefined,
|
testCaseStatus: undefined,
|
||||||
testCaseType: 'all',
|
testCaseType: 'all',
|
||||||
|
sortField: 'testCaseResult.timestamp',
|
||||||
|
sortType: 'desc',
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -26,7 +26,10 @@ import React, {
|
|||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { PAGE_SIZE } from '../../../../constants/constants';
|
import { PAGE_SIZE } from '../../../../constants/constants';
|
||||||
import { mockDatasetData } from '../../../../constants/mockTourData.constants';
|
import { mockDatasetData } from '../../../../constants/mockTourData.constants';
|
||||||
import { DEFAULT_RANGE_DATA } from '../../../../constants/profiler.constant';
|
import {
|
||||||
|
DEFAULT_RANGE_DATA,
|
||||||
|
DEFAULT_SORT_ORDER,
|
||||||
|
} from '../../../../constants/profiler.constant';
|
||||||
import { useTourProvider } from '../../../../context/TourProvider/TourProvider';
|
import { useTourProvider } from '../../../../context/TourProvider/TourProvider';
|
||||||
import { TabSpecificField } from '../../../../enums/entity.enum';
|
import { TabSpecificField } from '../../../../enums/entity.enum';
|
||||||
import { Table } from '../../../../generated/entity/data/table';
|
import { Table } from '../../../../generated/entity/data/table';
|
||||||
@ -209,6 +212,7 @@ export const TableProfilerProvider = ({
|
|||||||
setIsTestsLoading(true);
|
setIsTestsLoading(true);
|
||||||
try {
|
try {
|
||||||
const { data, paging } = await getListTestCaseBySearch({
|
const { data, paging } = await getListTestCaseBySearch({
|
||||||
|
...DEFAULT_SORT_ORDER,
|
||||||
...params,
|
...params,
|
||||||
fields: [
|
fields: [
|
||||||
TabSpecificField.TEST_CASE_RESULT,
|
TabSpecificField.TEST_CASE_RESULT,
|
||||||
|
|||||||
@ -16,6 +16,7 @@ import { capitalize, map, startCase, values } from 'lodash';
|
|||||||
import { DateFilterType, StepperStepType } from 'Models';
|
import { DateFilterType, StepperStepType } from 'Models';
|
||||||
import { TestCaseSearchParams } from '../components/DataQuality/DataQuality.interface';
|
import { TestCaseSearchParams } from '../components/DataQuality/DataQuality.interface';
|
||||||
import { CSMode } from '../enums/codemirror.enum';
|
import { CSMode } from '../enums/codemirror.enum';
|
||||||
|
import { SORT_ORDER } from '../enums/common.enum';
|
||||||
import { DMLOperationType } from '../generated/api/data/createTableProfile';
|
import { DMLOperationType } from '../generated/api/data/createTableProfile';
|
||||||
import {
|
import {
|
||||||
ColumnProfilerConfig,
|
ColumnProfilerConfig,
|
||||||
@ -466,3 +467,8 @@ export const DEFAULT_PROFILER_CONFIG_VALUE = {
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const DEFAULT_SORT_ORDER = {
|
||||||
|
sortType: SORT_ORDER.DESC,
|
||||||
|
sortField: 'testCaseResult.timestamp',
|
||||||
|
};
|
||||||
|
|||||||
@ -31,6 +31,8 @@ import { TitleBreadcrumbProps } from '../../components/common/TitleBreadcrumb/Ti
|
|||||||
import DataQualityTab from '../../components/Database/Profiler/DataQualityTab/DataQualityTab';
|
import DataQualityTab from '../../components/Database/Profiler/DataQualityTab/DataQualityTab';
|
||||||
import { AddTestCaseList } from '../../components/DataQuality/AddTestCaseList/AddTestCaseList.component';
|
import { AddTestCaseList } from '../../components/DataQuality/AddTestCaseList/AddTestCaseList.component';
|
||||||
import PageLayoutV1 from '../../components/PageLayoutV1/PageLayoutV1';
|
import PageLayoutV1 from '../../components/PageLayoutV1/PageLayoutV1';
|
||||||
|
import { INITIAL_PAGING_VALUE } from '../../constants/constants';
|
||||||
|
import { DEFAULT_SORT_ORDER } from '../../constants/profiler.constant';
|
||||||
import { usePermissionProvider } from '../../context/PermissionProvider/PermissionProvider';
|
import { usePermissionProvider } from '../../context/PermissionProvider/PermissionProvider';
|
||||||
import {
|
import {
|
||||||
OperationPermission,
|
OperationPermission,
|
||||||
@ -86,10 +88,12 @@ const TestSuiteDetailsPage = () => {
|
|||||||
showPagination,
|
showPagination,
|
||||||
} = usePaging();
|
} = usePaging();
|
||||||
const [isLoading, setIsLoading] = useState<boolean>(false);
|
const [isLoading, setIsLoading] = useState<boolean>(false);
|
||||||
const [testSuitePermissions, setTestSuitePermission] =
|
const [testSuitePermissions, setTestSuitePermissions] =
|
||||||
useState<OperationPermission>(DEFAULT_ENTITY_PERMISSION);
|
useState<OperationPermission>(DEFAULT_ENTITY_PERMISSION);
|
||||||
const [isTestCaseModalOpen, setIsTestCaseModalOpen] =
|
const [isTestCaseModalOpen, setIsTestCaseModalOpen] =
|
||||||
useState<boolean>(false);
|
useState<boolean>(false);
|
||||||
|
const [sortOptions, setSortOptions] =
|
||||||
|
useState<ListTestCaseParamsBySearch>(DEFAULT_SORT_ORDER);
|
||||||
|
|
||||||
const [slashedBreadCrumb, setSlashedBreadCrumb] = useState<
|
const [slashedBreadCrumb, setSlashedBreadCrumb] = useState<
|
||||||
TitleBreadcrumbProps['titleLinks']
|
TitleBreadcrumbProps['titleLinks']
|
||||||
@ -133,7 +137,7 @@ const TestSuiteDetailsPage = () => {
|
|||||||
ResourceEntity.TEST_SUITE,
|
ResourceEntity.TEST_SUITE,
|
||||||
testSuiteFQN
|
testSuiteFQN
|
||||||
);
|
);
|
||||||
setTestSuitePermission(response);
|
setTestSuitePermissions(response);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
showErrorToast(error as AxiosError);
|
showErrorToast(error as AxiosError);
|
||||||
} finally {
|
} finally {
|
||||||
@ -152,6 +156,7 @@ const TestSuiteDetailsPage = () => {
|
|||||||
TabSpecificField.INCIDENT_ID,
|
TabSpecificField.INCIDENT_ID,
|
||||||
],
|
],
|
||||||
testSuiteId,
|
testSuiteId,
|
||||||
|
...sortOptions,
|
||||||
...param,
|
...param,
|
||||||
limit: pageSize,
|
limit: pageSize,
|
||||||
});
|
});
|
||||||
@ -169,6 +174,11 @@ const TestSuiteDetailsPage = () => {
|
|||||||
setIsTestCaseLoading(false);
|
setIsTestCaseLoading(false);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
const handleSortTestCase = async (apiParams?: ListTestCaseParamsBySearch) => {
|
||||||
|
setSortOptions(apiParams ?? DEFAULT_SORT_ORDER);
|
||||||
|
await fetchTestCases({ ...(apiParams ?? DEFAULT_SORT_ORDER), offset: 0 });
|
||||||
|
handlePageChange(INITIAL_PAGING_VALUE);
|
||||||
|
};
|
||||||
|
|
||||||
const handleAddTestCaseSubmit = async (testCases: TestCase[]) => {
|
const handleAddTestCaseSubmit = async (testCases: TestCase[]) => {
|
||||||
const testCaseIds = testCases.reduce((ids, curr) => {
|
const testCaseIds = testCases.reduce((ids, curr) => {
|
||||||
@ -391,6 +401,7 @@ const TestSuiteDetailsPage = () => {
|
|||||||
<DataQualityTab
|
<DataQualityTab
|
||||||
afterDeleteAction={fetchTestCases}
|
afterDeleteAction={fetchTestCases}
|
||||||
breadcrumbData={incidentUrlState}
|
breadcrumbData={incidentUrlState}
|
||||||
|
fetchTestCases={handleSortTestCase}
|
||||||
isLoading={isLoading || isTestCaseLoading}
|
isLoading={isLoading || isTestCaseLoading}
|
||||||
pagingData={pagingData}
|
pagingData={pagingData}
|
||||||
removeFromTestSuite={{ testSuite: testSuite as TestSuite }}
|
removeFromTestSuite={{ testSuite: testSuite as TestSuite }}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user