Fixed issue Update Right panel content for add test-suite workflow, and icon for test suite #7043 (#7069)

* Fixed issue Update Right panel content for add test-suite workflow, and icon for test suite #7043

* updated link redirection path for add test

* fixed failing unit test
This commit is contained in:
Shailesh Parmar 2022-08-31 00:17:11 +05:30 committed by GitHub
parent d438fbead8
commit c681494e44
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 141 additions and 39 deletions

View File

@ -0,0 +1,13 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="currentColor" xmlns="http://www.w3.org/2000/svg">
<path d="M13.9221 3.6123L10.9766 0.580214C10.9299 0.532086 10.8675 0.5 10.7896 0.5H3.74545C2.77922 0.5 2 1.30214 2 2.29679V13.7032C2 14.6979 2.77922 15.5 3.74545 15.5H12.2545C13.2208 15.5 14 14.6979 14 13.7032V3.80481C14 3.7246 13.9688 3.66043 13.9221 3.6123V3.6123ZM11.0545 1.46257C11.7558 2.18449 12.3636 2.81016 13.0649 3.53209H11.6C11.2883 3.53209 11.0545 3.2754 11.0545 2.97059V1.46257ZM12.2545 14.9385H3.74545C3.09091 14.9385 2.54545 14.393 2.54545 13.7032V2.28075C2.54545 1.60695 3.07532 1.04545 3.74545 1.04545H10.5091V2.95455C10.5091 3.58021 11.0078 4.07754 11.6 4.07754H13.4545V13.7032C13.4545 14.393 12.9091 14.9385 12.2545 14.9385Z" fill="currentColor" stroke="currentColor" stroke-width="0.35"/>
<path d="M11.0012 5.15234H7.93723C7.81612 5.15234 7.71924 5.26345 7.71924 5.40234C7.71924 5.54123 7.81612 5.65234 7.93723 5.65234H11.0012C11.1224 5.65234 11.2192 5.54123 11.2192 5.40234C11.2192 5.26345 11.1224 5.15234 11.0012 5.15234Z" fill="currentColor" stroke="currentColor" stroke-width="0.4"/>
<path d="M5.2107 3.08291H9.15355C9.3094 3.08291 9.43407 2.95457 9.43407 2.79414C9.43407 2.63371 9.3094 2.50537 9.15355 2.50537H5.2107C5.05485 2.50537 4.93018 2.63371 4.93018 2.79414C4.93018 2.95457 5.05485 3.08291 5.2107 3.08291V3.08291Z" fill="currentColor" stroke="currentColor" stroke-width="0.25"/>
<path d="M5.93531 4.66335L5.0341 5.59106L4.55424 5.09709C4.47231 5.01275 4.34357 5.01275 4.26164 5.09709C4.17971 5.18142 4.17971 5.31395 4.26164 5.39829L4.88195 6.03684C4.96388 6.12118 5.09262 6.12118 5.17455 6.03684L6.2162 4.96456C6.29813 4.88022 6.29813 4.74769 6.2162 4.66335C6.13427 4.57901 6.00553 4.57901 5.93531 4.66335V4.66335Z" fill="currentColor" stroke="currentColor" stroke-width="0.25"/>
<path d="M11.0012 7.57471H7.93723C7.81612 7.57471 7.71924 7.68582 7.71924 7.82471C7.71924 7.9636 7.81612 8.07471 7.93723 8.07471H11.0012C11.1224 8.07471 11.2192 7.9636 11.2192 7.82471C11.2192 7.68582 11.1224 7.57471 11.0012 7.57471Z" fill="currentColor" stroke="currentColor" stroke-width="0.4"/>
<path d="M5.94582 7.05455L5.03916 7.98788L4.55639 7.49091C4.47396 7.40606 4.34444 7.40606 4.26201 7.49091C4.17959 7.57576 4.17959 7.70909 4.26201 7.79394L4.88608 8.43636C4.96851 8.52121 5.09803 8.52121 5.18046 8.43636L6.22842 7.35758C6.31084 7.27273 6.31084 7.13939 6.22842 7.05455C6.146 6.98182 6.01647 6.98182 5.94582 7.05455V7.05455Z" fill="currentColor" stroke="currentColor" stroke-width="0.25"/>
<path d="M11.0012 9.99731H7.93723C7.81612 9.99731 7.71924 10.1084 7.71924 10.2473C7.71924 10.3862 7.81612 10.4973 7.93723 10.4973H11.0012C11.1224 10.4973 11.2192 10.3862 11.2192 10.2473C11.2192 10.1084 11.1224 9.99731 11.0012 9.99731Z" fill="currentColor" stroke="currentColor" stroke-width="0.4"/>
<path d="M5.93531 9.56325L5.0341 10.491L4.55424 9.99699C4.47231 9.91265 4.34357 9.91265 4.26164 9.99699C4.17971 10.0813 4.17971 10.2139 4.26164 10.2982L4.88195 10.9367C4.96388 11.0211 5.09262 11.0211 5.17455 10.9367L6.2162 9.86446C6.29813 9.78012 6.29813 9.64759 6.2162 9.56325C6.14598 9.47892 6.01723 9.47892 5.93531 9.56325V9.56325Z" fill="currentColor" stroke="currentColor" stroke-width="0.25"/>
<path d="M11.0012 12.4199H7.93723C7.81612 12.4199 7.71924 12.531 7.71924 12.6699C7.71924 12.8088 7.81612 12.9199 7.93723 12.9199H11.0012C11.1224 12.9199 11.2192 12.8088 11.2192 12.6699C11.2192 12.531 11.1224 12.4199 11.0012 12.4199Z" fill="currentColor" stroke="currentColor" stroke-width="0.4"/>
<path d="M5.62387 12.0072L4.4925 13.1386C4.41443 13.2167 4.41443 13.3434 4.4925 13.4215C4.57056 13.4995 4.69727 13.4995 4.77534 13.4215L5.90671 12.2901C5.98477 12.212 5.98477 12.0853 5.90671 12.0072C5.82864 11.9292 5.70193 11.9292 5.62387 12.0072Z" fill="currentColor" stroke="currentColor" stroke-width="0.25"/>
<path d="M5.90658 13.1385L4.77521 12.0071C4.69715 11.9291 4.57043 11.9291 4.49237 12.0071C4.4143 12.0852 4.4143 12.2119 4.49237 12.29L5.62374 13.4214C5.7018 13.4994 5.82852 13.4994 5.90658 13.4214C5.98465 13.3433 5.98465 13.2166 5.90658 13.1385Z" fill="currentColor" stroke="currentColor" stroke-width="0.25"/>
</svg>

After

Width:  |  Height:  |  Size: 4.0 KiB

View File

@ -55,7 +55,7 @@ import {
import RightPanel from './components/RightPanel';
import SelectTestSuite from './components/SelectTestSuite';
import TestCaseForm from './components/TestCaseForm';
import { INGESTION_DATA, TEST_FORM_DATA } from './rightPanelData';
import { addTestSuiteRightPanel, INGESTION_DATA } from './rightPanelData';
import TestSuiteIngestion from './TestSuiteIngestion';
const AddDataQualityTestV1: React.FC<AddDataQualityTestProps> = ({ table }) => {
@ -126,7 +126,9 @@ const AddDataQualityTestV1: React.FC<AddDataQualityTestProps> = ({ table }) => {
}, [table, entityTypeFQN, isColumnFqn]);
const handleViewTestSuiteClick = () => {
history.push(getTestSuitePath(testSuiteData?.fullyQualifiedName || ''));
history.push(
getTestSuitePath(selectedTestSuite?.data?.fullyQualifiedName || '')
);
};
const handleAirflowStatusCheck = (): Promise<void> => {
@ -226,7 +228,8 @@ const AddDataQualityTestV1: React.FC<AddDataQualityTestProps> = ({ table }) => {
&quot;{successName}&quot;
</span>
<span>
has been created successfully. and will be pickup in next run.
has been created successfully. This will be picked up in the next
run.
</span>
</span>
);
@ -268,7 +271,14 @@ const AddDataQualityTestV1: React.FC<AddDataQualityTestProps> = ({ table }) => {
data={
addIngestion
? INGESTION_DATA
: TEST_FORM_DATA[activeServiceStep - 1]
: addTestSuiteRightPanel(
activeServiceStep,
selectedTestSuite?.isNewTestSuite,
{
testCase: testCaseData?.name || '',
testSuite: testSuiteData?.name || '',
}
)
}
/>
}>

View File

@ -13,7 +13,7 @@
import { Col, Row, Typography } from 'antd';
import { AxiosError } from 'axios';
import { compare } from 'fast-json-patch';
import { camelCase } from 'lodash';
import { camelCase, isEmpty } from 'lodash';
import React, { useMemo, useState } from 'react';
import { useHistory, useParams } from 'react-router-dom';
import {
@ -105,7 +105,9 @@ const TestSuiteIngestion: React.FC<TestSuiteIngestionProps> = ({
const createIngestionPipeline = async (repeatFrequency: string) => {
const ingestionPayload: CreateIngestionPipeline = {
airflowConfig: {
scheduleInterval: repeatFrequency,
scheduleInterval: isEmpty(repeatFrequency)
? undefined
: repeatFrequency,
},
name: `${testSuite.name}_${PipelineType.TestSuite}`,
pipelineType: PipelineType.TestSuite,
@ -131,7 +133,9 @@ const TestSuiteIngestion: React.FC<TestSuiteIngestionProps> = ({
...ingestionPipeline,
airflowConfig: {
...ingestionPipeline?.airflowConfig,
scheduleInterval: repeatFrequency,
scheduleInterval: isEmpty(repeatFrequency)
? undefined
: repeatFrequency,
},
};
const jsonPatch = compare(

View File

@ -1,3 +1,4 @@
/* eslint-disable max-len */
/*
* Copyright 2022 Collate
* Licensed under the Apache License, Version 2.0 (the "License");
@ -14,19 +15,49 @@
export const TEST_FORM_DATA = [
{
title: 'Select/Create Test Suite',
body: 'Select existing test suite or Create new Test Suite',
body: 'To create a Table or Column level test for an entity, start by selecting the Test Suite. Select an existing test suite or create a new test suite.',
},
{
title: 'Test Case',
body: 'Fill up the relevant details and create test case',
title: 'Create Test Case',
body: 'To create a test case, add a unique name. Select a test type from the options provided. Fill in the details for the parameters that show up for a selected test type. Enter a description (optional).',
},
{
title: 'Test case created successfully',
body: 'Visit the newly created test case to take a look at the details. Ensure that you have Airflow set up correctly before heading to ingest metadata.',
title: 'Test Case Created Successfully',
body: '{testCase} has been created successfully. View the Test Suite to check the details of the new created test case. This will be picked up in the next run.',
},
{
title: 'Test Suite & Test Case Created Successfully',
body: '{testSuite} & {testCase} has been created successfully. In the next step, you can schedule to ingest metadata at the desired frequency. You can also view the Test Suite to check the details of the new created test case.',
},
];
export const INGESTION_DATA = {
title: 'Schedule for Ingestion',
body: 'Scheduling can be set up at an hourly, daily, or weekly cadence. The timezone is in UTC.',
title: 'Scheduler for Tests',
body: 'The data quality tests can be scheduled to run at the desired frequency. The timezone is in UTC.',
};
export const addTestSuiteRightPanel = (
step: number,
isSuiteCreate?: boolean,
data?: { testSuite: string; testCase: string }
) => {
let message = TEST_FORM_DATA[step - 1];
if (step === 3) {
if (isSuiteCreate) {
message = TEST_FORM_DATA[step];
const updatedMessage = message.body
.replace('{testSuite}', data?.testSuite || 'Test Suite')
.replace('{testCase}', data?.testCase || 'Test Case');
message.body = updatedMessage;
} else {
const updatedMessage = message.body.replace(
'{testCase}',
data?.testCase || 'Test Case'
);
message.body = updatedMessage;
}
}
return message;
};

View File

@ -255,17 +255,6 @@ const DatasetDetails: React.FC<DatasetDetailsProps> = ({
isProtected: false,
position: 5,
},
{
name: 'Data Quality',
icon: {
alt: 'data-quality',
name: 'icon-quality',
title: 'Data Quality',
selectedName: '',
},
isProtected: false,
position: 6,
},
{
name: 'Lineage',
icon: {

View File

@ -241,7 +241,6 @@ describe('Test MyDataDetailsPage page', () => {
const sampleDataTab = await findByTestId(tabs, 'Sample Data');
const queriesTab = await findByTestId(tabs, 'Queries');
const profilerTab = await findByTestId(tabs, 'Profiler');
const dataQualityTab = await findByTestId(tabs, 'Data Quality');
const lineageTab = await findByTestId(tabs, 'Lineage');
const dbtTab = queryByTestId(tabs, 'DBT');
@ -254,7 +253,6 @@ describe('Test MyDataDetailsPage page', () => {
expect(sampleDataTab).toBeInTheDocument();
expect(queriesTab).toBeInTheDocument();
expect(profilerTab).toBeInTheDocument();
expect(dataQualityTab).toBeInTheDocument();
expect(lineageTab).toBeInTheDocument();
expect(dbtTab).not.toBeInTheDocument();
});

View File

@ -73,7 +73,7 @@ const MyAssetStats: FunctionComponent<MyAssetStatsProps> = ({
dataTestId: 'mlmodels',
},
testSuite: {
icon: Icons.TABLE_GREY,
icon: Icons.TEST_SUITE,
data: 'Test Suite',
count: entityCounts.testSuiteCount,
link: getSettingPath(

View File

@ -46,6 +46,7 @@ import {
getPartialNameFromTableFQN,
hasEditAccess,
} from '../../utils/CommonUtils';
import { getAddDataQualityTableTestPath } from '../../utils/RouterUtils';
import { serviceTypeLogo } from '../../utils/ServiceUtils';
import {
generateEntityLink,
@ -299,7 +300,12 @@ const ProfilerDashboard: React.FC<ProfilerDashboardProps> = ({
const handleAddTestClick = () => {
history.push(
getTableTabPath(table.fullyQualifiedName || '', 'data-quality')
getAddDataQualityTableTestPath(
isColumnView
? ProfilerDashboardType.COLUMN
: ProfilerDashboardType.TABLE,
entityTypeFQN || ''
)
);
};

View File

@ -12,16 +12,26 @@
*/
import { Card, Col, Row, Statistic } from 'antd';
import { AxiosError } from 'axios';
import { sortBy } from 'lodash';
import moment from 'moment';
import React, { useEffect, useMemo, useState } from 'react';
import { useParams } from 'react-router-dom';
import { getListTestCase } from '../../../axiosAPIs/testAPI';
import { API_RES_MAX_SIZE } from '../../../constants/constants';
import {
INITIAL_COUNT_METRIC_VALUE,
INITIAL_MATH_METRIC_VALUE,
INITIAL_PROPORTION_METRIC_VALUE,
INITIAL_SUM_METRIC_VALUE,
INITIAL_TEST_RESULT_SUMMARY,
} from '../../../constants/profiler.constant';
import { getTableFQNFromColumnFQN } from '../../../utils/CommonUtils';
import { updateTestResults } from '../../../utils/DataQualityAndProfilerUtils';
import { generateEntityLink } from '../../../utils/TableUtils';
import { showErrorToast } from '../../../utils/ToastUtils';
import Ellipses from '../../common/Ellipses/Ellipses';
import { TableTestsType } from '../../TableProfiler/TableProfiler.interface';
import {
MetricChartType,
ProfilerTabProps,
@ -34,6 +44,7 @@ const ProfilerTab: React.FC<ProfilerTabProps> = ({
profilerData,
tableProfile,
}) => {
const { entityTypeFQN } = useParams<Record<string, string>>();
const [countMetrics, setCountMetrics] = useState<MetricChartType>(
INITIAL_COUNT_METRIC_VALUE
);
@ -46,6 +57,10 @@ const ProfilerTab: React.FC<ProfilerTabProps> = ({
const [sumMetrics, setSumMetrics] = useState<MetricChartType>(
INITIAL_SUM_METRIC_VALUE
);
const [tableTests, setTableTests] = useState<TableTestsType>({
tests: [],
results: INITIAL_TEST_RESULT_SUMMARY,
});
const tableState = useMemo(
() => [
@ -64,23 +79,24 @@ const ProfilerTab: React.FC<ProfilerTabProps> = ({
],
[tableProfile]
);
const testSummary = useMemo(
() => [
const testSummary = useMemo(() => {
const { results } = tableTests;
return [
{
title: 'Success',
value: 0,
value: results.success,
},
{
title: 'Aborted',
value: 0,
value: results.aborted,
},
{
title: 'Failed',
value: 0,
value: results.failed,
},
],
[]
);
];
}, [tableTests]);
const createMetricsChartData = () => {
const updateProfilerData = sortBy(profilerData, 'timestamp');
@ -171,10 +187,38 @@ const ProfilerTab: React.FC<ProfilerTabProps> = ({
}));
};
const fetchAllTests = async () => {
const tableFqn = getTableFQNFromColumnFQN(entityTypeFQN);
try {
const { data } = await getListTestCase({
fields: 'testCaseResult',
entityLink: generateEntityLink(tableFqn),
limit: API_RES_MAX_SIZE,
});
const tableTests: TableTestsType = {
tests: [],
results: { ...INITIAL_TEST_RESULT_SUMMARY },
};
data.forEach((test) => {
updateTestResults(
tableTests.results,
test.testCaseResult?.testCaseStatus || ''
);
});
setTableTests(tableTests);
} catch (error) {
showErrorToast(error as AxiosError);
}
};
useEffect(() => {
createMetricsChartData();
}, [profilerData]);
useEffect(() => {
fetchAllTests();
}, []);
return (
<Row gutter={[16, 16]}>
<Col span={8}>

View File

@ -84,7 +84,7 @@ const ProfilerDashboardPage = () => {
};
const handleTestCaseUpdate = () => {
fetchTestCases(generateEntityLink(entityTypeFQN));
fetchTestCases(generateEntityLink(entityTypeFQN, isColumnView));
};
const fetchTableEntity = async () => {

View File

@ -17,6 +17,7 @@ import React, { ReactNode } from 'react';
import { ReactComponent as BotIcon } from '../../src/assets/svg/bot-profile.svg';
import { ReactComponent as DashboardIcon } from '../../src/assets/svg/dashboard-grey.svg';
import { ReactComponent as RolesIcon } from '../../src/assets/svg/icon-role-grey.svg';
import { ReactComponent as TestSuite } from '../../src/assets/svg/icon-test-suite.svg';
import { ReactComponent as MlModelIcon } from '../../src/assets/svg/mlmodal.svg';
import { ReactComponent as PipelineIcon } from '../../src/assets/svg/pipeline-grey.svg';
import { ReactComponent as PoliciesIcon } from '../../src/assets/svg/policies.svg';
@ -162,7 +163,7 @@ export const getGlobalSettingsMenuWithPermission = (
ResourceEntity.TEST_SUITE,
permissions
),
icon: <TableIcon className="side-panel-icons" />,
icon: <TestSuite className="side-panel-icons" />,
},
],
},

View File

@ -118,6 +118,7 @@ import IconKey from '../assets/svg/icon-key.svg';
import IconNotNull from '../assets/svg/icon-notnull.svg';
import IconPlusPrimaryOutlined from '../assets/svg/icon-plus-primary-outlined.svg';
import IconRoleGrey from '../assets/svg/icon-role-grey.svg';
import IconTestSuite from '../assets/svg/icon-test-suite.svg';
import IconTour from '../assets/svg/icon-tour.svg';
import IconUnique from '../assets/svg/icon-unique.svg';
import IconUp from '../assets/svg/icon-up.svg';
@ -204,6 +205,7 @@ export const Icons = {
SQL_BUILDER: 'icon-sql-builder',
TEAMS: 'icon-teams',
TEAMS_GREY: 'icon-teams-grey',
TEST_SUITE: 'icon-test-suite',
WORKFLOWS: 'icon-workflows',
MENU: 'icon-menu',
FEED: 'icon-feed',
@ -1008,6 +1010,10 @@ const SVGIcons: FunctionComponent<Props> = ({
case Icons.DELETE_COLORED:
IconComponent = IconDeleteColored;
break;
case Icons.TEST_SUITE:
IconComponent = IconTestSuite;
break;
default:
IconComponent = null;