Minor: added support for search param based test case filter (#17030)

* Minor: added support for search param based test case filter

* fixed remove filter issue
This commit is contained in:
Shailesh Parmar 2024-07-16 10:44:48 +05:30 committed by GitHub
parent f8beaa6c30
commit c2db1bbf0f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 409 additions and 215 deletions

View File

@ -1057,6 +1057,7 @@ describe(
});
cy.get('[value="serviceName"]').click({ waitForAnimations: true });
verifyResponseStatusCode('@getTestCase', 200);
cy.get('#serviceName').should('not.exist');
// Test case filter by Tags
interceptURL(
@ -1073,12 +1074,13 @@ describe(
verifyResponseStatusCode('@getTestCaseByTags', 200);
verifyFilterTestCase();
verifyFilter2TestCase(true);
// remove service filter
// remove tags filter
cy.get('[data-testid="advanced-filter"]').click({
waitForAnimations: true,
});
cy.get('[value="tags"]').click({ waitForAnimations: true });
verifyResponseStatusCode('@getTestCase', 200);
cy.get('#tags').should('not.exist');
// Test case filter by Tier
interceptURL(
@ -1094,12 +1096,13 @@ describe(
verifyResponseStatusCode('@getTestCaseByTier', 200);
verifyFilterTestCase();
verifyFilter2TestCase(true);
// remove service filter
// remove tier filter
cy.get('[data-testid="advanced-filter"]').click({
waitForAnimations: true,
});
cy.get('[value="tier"]').click({ waitForAnimations: true });
verifyResponseStatusCode('@getTestCase', 200);
cy.get('#tier').should('not.exist');
// Test case filter by table name
interceptURL(
@ -1196,6 +1199,25 @@ describe(
verifyResponseStatusCode('@testCasePlatformByOpenMetadata', 200);
cy.clickOutside();
verifyFilterTestCase();
cy.url().then((url) => {
cy.reload();
verifyResponseStatusCode('@testCasePlatformByOpenMetadata', 200);
cy.url().then((updatedUrl) => {
expect(url).to.be.equal(updatedUrl);
});
});
cy.get('[data-testid="advanced-filter"]').click({
waitForAnimations: true,
});
cy.get('[value="testPlatforms"]').click({
waitForAnimations: true,
});
verifyResponseStatusCode('@getTestCase', 200);
cy.get('[value="platform-select-filter"]').should('not.exist');
cy.reload();
verifyResponseStatusCode('@getTestCase', 200);
cy.get('[value="tier"]').should('not.exist');
});
it('Filter with domain', () => {

View File

@ -1,3 +1,8 @@
import { DateRangeObject } from 'Models';
import { TestCaseStatus } from '../../generated/tests/testCase';
import { TestPlatform } from '../../generated/tests/testDefinition';
import { TestCaseType } from '../../rest/testAPI';
/*
* Copyright 2023 Collate.
* Licensed under the Apache License, Version 2.0 (the "License");
@ -10,9 +15,21 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
export type DataQualitySearchParams = {
export type TestSuiteSearchParams = {
searchValue: string;
status: string;
type: string;
owner: string;
};
export type TestCaseSearchParams = {
searchValue?: string;
tableFqn?: string;
testPlatforms?: TestPlatform[];
testCaseStatus?: TestCaseStatus;
testCaseType?: TestCaseType;
lastRunRange?: DateRangeObject;
tier?: string;
tags?: string;
serviceName?: string;
};

View File

@ -30,11 +30,9 @@ import {
debounce,
entries,
isEmpty,
isEqual,
isUndefined,
omit,
omitBy,
startCase,
uniq,
} from 'lodash';
import QueryString from 'qs';
import React, {
@ -67,14 +65,10 @@ import { usePaging } from '../../../hooks/paging/usePaging';
import { DataQualityPageTabs } from '../../../pages/DataQuality/DataQualityPage.interface';
import { searchQuery } from '../../../rest/searchAPI';
import { getTags } from '../../../rest/tagAPI';
import {
getListTestCaseBySearch,
ListTestCaseParamsBySearch,
} from '../../../rest/testAPI';
import { buildTestCaseParams } from '../../../utils/DataQuality/DataQualityUtils';
import { getListTestCaseBySearch } from '../../../rest/testAPI';
import { getTestCaseFiltersValue } from '../../../utils/DataQuality/DataQualityUtils';
import { getEntityName } from '../../../utils/EntityUtils';
import { getDataQualityPagePath } from '../../../utils/RouterUtils';
import { generateEntityLink } from '../../../utils/TableUtils';
import tagClassBase from '../../../utils/TagClassBase';
import { showErrorToast } from '../../../utils/ToastUtils';
import DatePickerMenu from '../../common/DatePickerMenu/DatePickerMenu.component';
@ -82,7 +76,7 @@ import ErrorPlaceHolder from '../../common/ErrorWithPlaceholder/ErrorPlaceHolder
import { PagingHandlerParams } from '../../common/NextPrevious/NextPrevious.interface';
import Searchbar from '../../common/SearchBarComponent/SearchBar.component';
import DataQualityTab from '../../Database/Profiler/DataQualityTab/DataQualityTab';
import { DataQualitySearchParams } from '../DataQuality.interface';
import { TestCaseSearchParams } from '../DataQuality.interface';
export const TestCases = ({ summaryPanel }: { summaryPanel: ReactNode }) => {
const [form] = useForm();
@ -105,13 +99,12 @@ export const TestCases = ({ summaryPanel }: { summaryPanel: ReactNode }) => {
search.startsWith('?') ? search.substring(1) : search
);
return params as DataQualitySearchParams;
}, [location]);
return params as TestCaseSearchParams;
}, [location.search]);
const { searchValue = '' } = params;
const [testCase, setTestCase] = useState<TestCase[]>([]);
const [isLoading, setIsLoading] = useState<boolean>(true);
const [filters, setFilters] = useState<ListTestCaseParamsBySearch>({});
const [selectedFilter, setSelectedFilter] = useState<string[]>([
TEST_CASE_FILTERS.status,
TEST_CASE_FILTERS.type,
@ -127,12 +120,12 @@ export const TestCases = ({ summaryPanel }: { summaryPanel: ReactNode }) => {
showPagination,
} = usePaging(PAGE_SIZE);
const handleSearchParam = (
value: string | boolean,
key: keyof DataQualitySearchParams
const handleSearchParam = <K extends keyof TestCaseSearchParams>(
key: K,
value?: TestCaseSearchParams[K]
) => {
history.push({
search: QueryString.stringify({ ...params, [key]: value }),
search: QueryString.stringify({ ...params, [key]: value || undefined }),
});
};
@ -150,12 +143,17 @@ export const TestCases = ({ summaryPanel }: { summaryPanel: ReactNode }) => {
const fetchTestCases = async (
currentPage = INITIAL_PAGING_VALUE,
params?: ListTestCaseParamsBySearch
filters?: string[]
) => {
const updatedParams = getTestCaseFiltersValue(
params,
filters ?? selectedFilter
);
setIsLoading(true);
try {
const { data, paging } = await getListTestCaseBySearch({
...params,
...updatedParams,
testCaseStatus: isEmpty(params?.testCaseStatus)
? undefined
: params?.testCaseStatus,
@ -192,31 +190,16 @@ export const TestCases = ({ summaryPanel }: { summaryPanel: ReactNode }) => {
};
const handlePagingClick = ({ currentPage }: PagingHandlerParams) => {
fetchTestCases(currentPage, filters);
fetchTestCases(currentPage);
};
const handleFilterChange: FormProps['onValuesChange'] = (_, values) => {
const { lastRunRange, tableFqn } = values;
const startTimestamp = lastRunRange?.startTs;
const endTimestamp = lastRunRange?.endTs;
const entityLink = tableFqn ? generateEntityLink(tableFqn) : undefined;
const params = {
...omit(values, ['lastRunRange', 'tableFqn']),
startTimestamp,
endTimestamp,
entityLink,
const handleFilterChange: FormProps<TestCaseSearchParams>['onValuesChange'] =
(value?: TestCaseSearchParams) => {
if (!isUndefined(value)) {
const [data] = Object.entries(value);
handleSearchParam(data[0] as keyof TestCaseSearchParams, data[1]);
}
};
const updatedParams = omitBy(
buildTestCaseParams(params, selectedFilter),
isUndefined
);
if (!isEqual(filters, updatedParams)) {
fetchTestCases(INITIAL_PAGING_VALUE, updatedParams);
}
setFilters(updatedParams);
};
const fetchTierOptions = async () => {
try {
@ -360,33 +343,46 @@ export const TestCases = ({ summaryPanel }: { summaryPanel: ReactNode }) => {
}
};
const getInitialOptions = (key: string, isLengthCheck = false) => {
switch (key) {
case TEST_CASE_FILTERS.tier:
(isEmpty(tierOptions) || !isLengthCheck) && fetchTierOptions();
break;
case TEST_CASE_FILTERS.table:
(isEmpty(tableOptions) || !isLengthCheck) && fetchTableData();
break;
case TEST_CASE_FILTERS.tags:
(isEmpty(tagOptions) || !isLengthCheck) && fetchTagOptions();
break;
case TEST_CASE_FILTERS.service:
(isEmpty(serviceOptions) || !isLengthCheck) && fetchServiceOptions();
break;
default:
break;
}
};
const handleMenuClick = ({ key }: { key: string }) => {
setSelectedFilter((prevSelected) => {
if (prevSelected.includes(key)) {
const updatedValue = prevSelected.filter(
(selected) => selected !== key
);
const updatedFilters = omitBy(
buildTestCaseParams(filters, updatedValue),
isUndefined
);
form.setFieldsValue({ [key]: undefined });
if (!isEqual(filters, updatedFilters)) {
fetchTestCases(INITIAL_PAGING_VALUE, updatedFilters);
}
setFilters(updatedFilters);
return updatedValue;
}
return [...prevSelected, key];
return uniq([...prevSelected, key]);
});
// Fetch options based on the selected filter
key === TEST_CASE_FILTERS.tier && fetchTierOptions();
key === TEST_CASE_FILTERS.tags && fetchTagOptions();
key === TEST_CASE_FILTERS.table && fetchTableData();
key === TEST_CASE_FILTERS.service && fetchServiceOptions();
getInitialOptions(key);
handleSearchParam(key as keyof TestCaseSearchParams, undefined);
};
const filterMenu: ItemType[] = useMemo(() => {
@ -396,7 +392,7 @@ export const TestCases = ({ summaryPanel }: { summaryPanel: ReactNode }) => {
value: filter,
onClick: handleMenuClick,
}));
}, [filters]);
}, []);
const debounceFetchTableData = useCallback(debounce(fetchTableData, 1000), [
fetchTableData,
@ -411,15 +407,30 @@ export const TestCases = ({ summaryPanel }: { summaryPanel: ReactNode }) => {
[fetchServiceOptions]
);
useEffect(() => {
if (testCasePermission?.ViewAll || testCasePermission?.ViewBasic) {
if (tab === DataQualityPageTabs.TEST_CASES) {
fetchTestCases(INITIAL_PAGING_VALUE, filters);
const getTestCases = () => {
if (!isEmpty(params)) {
const updatedValue = uniq([...selectedFilter, ...Object.keys(params)]);
for (const key of updatedValue) {
getInitialOptions(key, true);
}
setSelectedFilter(updatedValue);
fetchTestCases(INITIAL_PAGING_VALUE, updatedValue);
form.setFieldsValue(params);
} else {
fetchTestCases(INITIAL_PAGING_VALUE);
}
};
useEffect(() => {
if (
(testCasePermission?.ViewAll || testCasePermission?.ViewBasic) &&
tab === DataQualityPageTabs.TEST_CASES
) {
getTestCases();
} else {
setIsLoading(false);
}
}, [tab, searchValue, testCasePermission, pageSize]);
}, [tab, testCasePermission, pageSize, params]);
const pagingData = useMemo(
() => ({
@ -443,9 +454,8 @@ export const TestCases = ({ summaryPanel }: { summaryPanel: ReactNode }) => {
data-testid="test-case-container"
gutter={[16, 16]}>
<Col span={24}>
<Form
<Form<TestCaseSearchParams>
form={form}
initialValues={filters}
layout="horizontal"
onValuesChange={handleFilterChange}>
<Space wrap align="center" className="w-full" size={16}>
@ -456,7 +466,7 @@ export const TestCases = ({ summaryPanel }: { summaryPanel: ReactNode }) => {
entity: t('label.test-case-lowercase'),
})}
searchValue={searchValue}
onSearch={(value) => handleSearchParam(value, 'searchValue')}
onSearch={(value) => handleSearchParam('searchValue', value)}
/>
</Form.Item>
<Form.Item noStyle name="selectedFilters">

View File

@ -58,7 +58,7 @@ import Table from '../../../common/Table/Table';
import { UserTeamSelectableList } from '../../../common/UserTeamSelectableList/UserTeamSelectableList.component';
import { TableProfilerTab } from '../../../Database/Profiler/ProfilerDashboard/profilerDashboard.interface';
import ProfilerProgressWidget from '../../../Database/Profiler/TableProfiler/ProfilerProgressWidget/ProfilerProgressWidget';
import { DataQualitySearchParams } from '../../DataQuality.interface';
import { TestSuiteSearchParams } from '../../DataQuality.interface';
export const TestSuites = ({ summaryPanel }: { summaryPanel: ReactNode }) => {
const { t } = useTranslation();
@ -74,7 +74,7 @@ export const TestSuites = ({ summaryPanel }: { summaryPanel: ReactNode }) => {
search.startsWith('?') ? search.substring(1) : search
);
return params as DataQualitySearchParams;
return params as TestSuiteSearchParams;
}, [location]);
const { searchValue, owner } = params;
const selectedOwner = useMemo(
@ -228,7 +228,7 @@ export const TestSuites = ({ summaryPanel }: { summaryPanel: ReactNode }) => {
const handleSearchParam = (
value: string,
key: keyof DataQualitySearchParams
key: keyof TestSuiteSearchParams
) => {
history.push({
search: QueryString.stringify({

View File

@ -14,6 +14,7 @@
import { t } from 'i18next';
import { capitalize, map, startCase, values } from 'lodash';
import { DateFilterType, StepperStepType } from 'Models';
import { TestCaseSearchParams } from '../components/DataQuality/DataQuality.interface';
import { CSMode } from '../enums/codemirror.enum';
import { DMLOperationType } from '../generated/api/data/createTableProfile';
import {
@ -417,7 +418,7 @@ export const TEST_CASE_STATUS_OPTION = [
})),
];
export const TEST_CASE_FILTERS = {
export const TEST_CASE_FILTERS: Record<string, keyof TestCaseSearchParams> = {
table: 'tableFqn',
platform: 'testPlatforms',
type: 'testCaseType',

View File

@ -10,6 +10,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { TestCaseSearchParams } from '../../components/DataQuality/DataQuality.interface';
import {
TestDataType,
TestDefinition,
@ -18,162 +19,279 @@ import { ListTestCaseParamsBySearch } from '../../rest/testAPI';
import {
buildTestCaseParams,
createTestCaseParameters,
getTestCaseFiltersValue,
} from './DataQualityUtils';
jest.mock('../../constants/profiler.constant', () => ({
TEST_CASE_FILTERS: {
lastRun: 'lastRun',
table: 'table',
platform: 'platform',
type: 'type',
status: 'status',
table: 'tableFqn',
platform: 'testPlatforms',
type: 'testCaseType',
status: 'testCaseStatus',
lastRun: 'lastRunRange',
tier: 'tier',
tags: 'tags',
service: 'serviceName',
},
}));
describe('buildTestCaseParams', () => {
it('should return an empty object if params is undefined', () => {
const params = undefined;
const filters = ['lastRun', 'table'];
jest.mock('../TableUtils', () => ({
generateEntityLink: jest.fn().mockImplementation((fqn: string) => {
return `<#E::table::${fqn}>`;
}),
}));
const result = buildTestCaseParams(params, filters);
describe('DataQualityUtils', () => {
describe('buildTestCaseParams', () => {
it('should return an empty object if params is undefined', () => {
const params = undefined;
const filters = ['lastRun', 'table'];
expect(result).toEqual({});
const result = buildTestCaseParams(params, filters);
expect(result).toEqual({});
});
it('should return the updated test case parameters with the applied filters', () => {
const params = {
endTimestamp: 1234567890,
startTimestamp: 1234567890,
entityLink: 'table1',
testPlatforms: ['DBT'],
} as ListTestCaseParamsBySearch;
const filters = ['lastRunRange', 'tableFqn'];
const result = buildTestCaseParams(params, filters);
expect(result).toEqual({
endTimestamp: 1234567890,
startTimestamp: 1234567890,
entityLink: 'table1',
});
});
});
it('should return the updated test case parameters with the applied filters', () => {
const params = {
endTimestamp: 1234567890,
startTimestamp: 1234567890,
entityLink: 'table1',
testPlatforms: ['DBT'],
} as ListTestCaseParamsBySearch;
const filters = ['lastRun', 'table'];
describe('createTestCaseParameters', () => {
const mockDefinition = {
parameterDefinition: [
{ name: 'arrayParam', dataType: TestDataType.Array },
{ name: 'stringParam', dataType: TestDataType.String },
],
} as TestDefinition;
const result = buildTestCaseParams(params, filters);
it('should return an empty array for empty parameters', () => {
const result = createTestCaseParameters({}, mockDefinition);
expect(result).toEqual({
endTimestamp: 1234567890,
startTimestamp: 1234567890,
entityLink: 'table1',
expect(result).toEqual([]);
});
it('should handle parameters not matching any definition', () => {
const params = { unrelatedParam: 'value' };
const result = createTestCaseParameters(params, mockDefinition);
expect(result).toEqual([{ name: 'unrelatedParam', value: 'value' }]);
});
it('should handle a mix of string and array parameters', () => {
const params = {
stringParam: 'stringValue',
arrayParam: [{ value: 'arrayValue1' }, { value: 'arrayValue2' }],
};
const expected = [
{ name: 'stringParam', value: 'stringValue' },
{
name: 'arrayParam',
value: JSON.stringify(['arrayValue1', 'arrayValue2']),
},
];
const result = createTestCaseParameters(params, mockDefinition);
expect(result).toEqual(expected);
});
it('should ignore array items without a value', () => {
const params = {
arrayParam: [{ value: '' }, { value: 'validValue' }],
};
const expected = [
{ name: 'arrayParam', value: JSON.stringify(['validValue']) },
];
const result = createTestCaseParameters(params, mockDefinition);
expect(result).toEqual(expected);
});
it('should return undefined if params not present', () => {
const result = createTestCaseParameters(undefined, undefined);
expect(result).toBeUndefined();
});
it('should return params value for sqlExpression test defination type', () => {
const data = {
params: {
sqlExpression: 'select * from dim_address',
strategy: 'COUNT',
threshold: '12',
},
selectedDefinition: {
parameterDefinition: [
{
name: 'sqlExpression',
displayName: 'SQL Expression',
dataType: 'STRING',
description: 'SQL expression to run against the table',
required: true,
optionValues: [],
},
{
name: 'strategy',
displayName: 'Strategy',
dataType: 'ARRAY',
description:
'Strategy to use to run the custom SQL query (i.e. `SELECT COUNT(<col>)` or `SELECT <col> (defaults to ROWS)',
required: false,
optionValues: ['ROWS', 'COUNT'],
},
{
name: 'threshold',
displayName: 'Threshold',
dataType: 'NUMBER',
description:
'Threshold to use to determine if the test passes or fails (defaults to 0).',
required: false,
optionValues: [],
},
],
} as TestDefinition,
};
const expected = [
{
name: 'sqlExpression',
value: 'select * from dim_address',
},
{
name: 'strategy',
value: 'COUNT',
},
{
name: 'threshold',
value: '12',
},
];
const result = createTestCaseParameters(
data.params,
data.selectedDefinition
);
expect(result).toEqual(expected);
});
});
describe('getTestCaseFiltersValue', () => {
const testCaseSearchParams = {
testCaseType: 'column',
testCaseStatus: 'Success',
searchValue: 'between',
testPlatforms: ['DBT', 'Deequ'],
lastRunRange: {
startTs: '1720417883445',
endTs: '1721022683445',
key: 'last7days',
title: 'Last 7 days',
},
tags: ['PII.None'],
tier: 'Tier.Tier1',
serviceName: 'sample_data',
tableFqn: 'sample_data.ecommerce_db.shopify.fact_sale',
} as unknown as TestCaseSearchParams;
it('should correctly process values and selectedFilter', () => {
const selectedFilter = [
'testCaseStatus',
'testCaseType',
'searchValue',
'testPlatforms',
'lastRunRange',
'tags',
'tier',
'serviceName',
'tableFqn',
];
const expected = {
endTimestamp: '1721022683445',
startTimestamp: '1720417883445',
entityLink: '<#E::table::sample_data.ecommerce_db.shopify.fact_sale>',
testPlatforms: ['DBT', 'Deequ'],
testCaseType: 'column',
testCaseStatus: 'Success',
tags: ['PII.None'],
tier: 'Tier.Tier1',
serviceName: 'sample_data',
};
const result = getTestCaseFiltersValue(
testCaseSearchParams,
selectedFilter
);
expect(result).toEqual(expected);
});
it('should only create params based on selected filters', () => {
const selectedFilter = ['testPlatforms', 'lastRunRange'];
const expected = {
testPlatforms: ['DBT', 'Deequ'],
endTimestamp: '1721022683445',
startTimestamp: '1720417883445',
};
const result = getTestCaseFiltersValue(
testCaseSearchParams,
selectedFilter
);
expect(result).toEqual(expected);
});
it('should only create params based on selected filters and available data', () => {
const testCaseSearchParams = {
testCaseType: 'column',
testCaseStatus: 'Success',
searchValue: 'between',
testPlatforms: ['DBT', 'Deequ'],
tags: ['PII.None'],
tier: 'Tier.Tier1',
} as unknown as TestCaseSearchParams;
const selectedFilter = ['testPlatforms', 'tags', 'testCaseStatus'];
const expected = {
testPlatforms: ['DBT', 'Deequ'],
tags: ['PII.None'],
testCaseStatus: 'Success',
};
const result = getTestCaseFiltersValue(
testCaseSearchParams,
selectedFilter
);
expect(result).toEqual(expected);
});
it('should not send params if selected filter is empty', () => {
const selectedFilter: string[] = [];
const result = getTestCaseFiltersValue(
testCaseSearchParams,
selectedFilter
);
expect(result).toEqual({});
});
});
});
describe('createTestCaseParameters', () => {
const mockDefinition = {
parameterDefinition: [
{ name: 'arrayParam', dataType: TestDataType.Array },
{ name: 'stringParam', dataType: TestDataType.String },
],
} as TestDefinition;
it('should return an empty array for empty parameters', () => {
const result = createTestCaseParameters({}, mockDefinition);
expect(result).toEqual([]);
});
it('should handle parameters not matching any definition', () => {
const params = { unrelatedParam: 'value' };
const result = createTestCaseParameters(params, mockDefinition);
expect(result).toEqual([{ name: 'unrelatedParam', value: 'value' }]);
});
it('should handle a mix of string and array parameters', () => {
const params = {
stringParam: 'stringValue',
arrayParam: [{ value: 'arrayValue1' }, { value: 'arrayValue2' }],
};
const expected = [
{ name: 'stringParam', value: 'stringValue' },
{
name: 'arrayParam',
value: JSON.stringify(['arrayValue1', 'arrayValue2']),
},
];
const result = createTestCaseParameters(params, mockDefinition);
expect(result).toEqual(expected);
});
it('should ignore array items without a value', () => {
const params = {
arrayParam: [{ value: '' }, { value: 'validValue' }],
};
const expected = [
{ name: 'arrayParam', value: JSON.stringify(['validValue']) },
];
const result = createTestCaseParameters(params, mockDefinition);
expect(result).toEqual(expected);
});
it('should return undefined if params not present', () => {
const result = createTestCaseParameters(undefined, undefined);
expect(result).toBeUndefined();
});
it('should return params value for sqlExpression test defination type', () => {
const data = {
params: {
sqlExpression: 'select * from dim_address',
strategy: 'COUNT',
threshold: '12',
},
selectedDefinition: {
parameterDefinition: [
{
name: 'sqlExpression',
displayName: 'SQL Expression',
dataType: 'STRING',
description: 'SQL expression to run against the table',
required: true,
optionValues: [],
},
{
name: 'strategy',
displayName: 'Strategy',
dataType: 'ARRAY',
description:
'Strategy to use to run the custom SQL query (i.e. `SELECT COUNT(<col>)` or `SELECT <col> (defaults to ROWS)',
required: false,
optionValues: ['ROWS', 'COUNT'],
},
{
name: 'threshold',
displayName: 'Threshold',
dataType: 'NUMBER',
description:
'Threshold to use to determine if the test passes or fails (defaults to 0).',
required: false,
optionValues: [],
},
],
} as TestDefinition,
};
const expected = [
{
name: 'sqlExpression',
value: 'select * from dim_address',
},
{
name: 'strategy',
value: 'COUNT',
},
{
name: 'threshold',
value: '12',
},
];
const result = createTestCaseParameters(
data.params,
data.selectedDefinition
);
expect(result).toEqual(expected);
});
});

View File

@ -10,7 +10,8 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { isArray } from 'lodash';
import { isArray, isUndefined, omit, omitBy } from 'lodash';
import { TestCaseSearchParams } from '../../components/DataQuality/DataQuality.interface';
import { TEST_CASE_FILTERS } from '../../constants/profiler.constant';
import { TestCaseParameterValue } from '../../generated/tests/testCase';
import {
@ -18,6 +19,7 @@ import {
TestDefinition,
} from '../../generated/tests/testDefinition';
import { ListTestCaseParamsBySearch } from '../../rest/testAPI';
import { generateEntityLink } from '../TableUtils';
/**
* Builds the parameters for a test case search based on the given filters.
@ -74,3 +76,27 @@ export const createTestCaseParameters = (
}, [] as TestCaseParameterValue[])
: params;
};
export const getTestCaseFiltersValue = (
values: TestCaseSearchParams,
selectedFilter: string[]
) => {
const { lastRunRange, tableFqn } = values;
const startTimestamp = lastRunRange?.startTs;
const endTimestamp = lastRunRange?.endTs;
const entityLink = tableFqn ? generateEntityLink(tableFqn) : undefined;
const apiParams = {
...omit(values, ['lastRunRange', 'tableFqn', 'searchValue']),
startTimestamp,
endTimestamp,
entityLink,
};
const updatedParams = omitBy(
buildTestCaseParams(apiParams, selectedFilter),
isUndefined
);
return updatedParams;
};