mirror of
https://github.com/open-metadata/OpenMetadata.git
synced 2026-01-08 05:26:19 +00:00
* fix: added include field to incident list * added ui changes for allowing deleted entries in entity page and fix the count on incident page * fix: error retrieving soft deleted test cases * fix: ran java linting * Update openmetadata-ui/src/main/resources/ui/src/components/IncidentManager/IncidentManager.component.tsx Co-authored-by: Chirag Madlani <12962843+chirag-madlani@users.noreply.github.com> * fix testcase playwright * fix playwright test --------- Co-authored-by: Ashish Gupta <ashish@getcollate.io> Co-authored-by: Chirag Madlani <12962843+chirag-madlani@users.noreply.github.com> (cherry picked from commit 0b483ecb865341425abf47132185bdbde6051bc7)
This commit is contained in:
parent
5b83a2949f
commit
3998982d54
@ -374,10 +374,11 @@ public class TestCaseResolutionStatusRepository
|
||||
|
||||
public static String addOriginEntityFQNJoin(ListFilter filter, String condition) {
|
||||
// if originEntityFQN is present, we need to join with test_case table
|
||||
if (filter.getQueryParam("originEntityFQN") != null) {
|
||||
if ((filter.getQueryParam("originEntityFQN") != null)
|
||||
|| (filter.getQueryParam("include") != null)) {
|
||||
condition =
|
||||
"""
|
||||
INNER JOIN (SELECT entityFQN AS testCaseEntityFQN,fqnHash AS testCaseHash FROM test_case) tc \
|
||||
INNER JOIN (SELECT entityFQN AS testCaseEntityFQN,fqnHash AS testCaseHash, deleted FROM test_case) tc \
|
||||
ON entityFQNHash = testCaseHash
|
||||
"""
|
||||
+ condition;
|
||||
|
||||
@ -37,6 +37,7 @@ import lombok.extern.slf4j.Slf4j;
|
||||
import org.openmetadata.schema.api.tests.CreateTestCaseResolutionStatus;
|
||||
import org.openmetadata.schema.tests.type.TestCaseResolutionStatus;
|
||||
import org.openmetadata.schema.tests.type.TestCaseResolutionStatusTypes;
|
||||
import org.openmetadata.schema.type.Include;
|
||||
import org.openmetadata.schema.type.MetadataOperation;
|
||||
import org.openmetadata.service.Entity;
|
||||
import org.openmetadata.service.jdbi3.ListFilter;
|
||||
@ -137,6 +138,12 @@ public class TestCaseResolutionStatusResource
|
||||
schema = @Schema(type = "String"))
|
||||
@QueryParam("assignee")
|
||||
String assignee,
|
||||
@Parameter(
|
||||
description = "Include all, deleted, or non-deleted entities.",
|
||||
schema = @Schema(implementation = Include.class))
|
||||
@QueryParam("include")
|
||||
@DefaultValue("non-deleted")
|
||||
Include include,
|
||||
@Parameter(description = "Test case fully qualified name", schema = @Schema(type = "String"))
|
||||
@QueryParam("testCaseFQN")
|
||||
String testCaseFQN,
|
||||
@ -159,7 +166,7 @@ public class TestCaseResolutionStatusResource
|
||||
}
|
||||
authorizer.authorizeRequests(securityContext, requests, AuthorizationLogic.ANY);
|
||||
|
||||
ListFilter filter = new ListFilter(null);
|
||||
ListFilter filter = new ListFilter(include);
|
||||
filter.addQueryParam("testCaseResolutionStatusType", testCaseResolutionStatusType);
|
||||
filter.addQueryParam("assignee", assignee);
|
||||
filter.addQueryParam("entityFQNHash", FullyQualifiedName.buildHash(testCaseFQN));
|
||||
|
||||
@ -185,7 +185,7 @@ public class PIIMasker {
|
||||
Entity.TABLE,
|
||||
testCaseLink.getEntityFQN(),
|
||||
"owners,tags,columns",
|
||||
Include.NON_DELETED);
|
||||
Include.ALL);
|
||||
entityFQNToTable.put(testCaseLink.getEntityFQN(), table);
|
||||
}
|
||||
|
||||
|
||||
@ -1525,8 +1525,11 @@ public class TestCaseResourceTest extends EntityResourceTest<TestCase, CreateTes
|
||||
// 1. soft delete - should not delete the test case resolution status
|
||||
// 2. hard delete - should delete the test case resolution status
|
||||
deleteEntity(testCaseEntity1.getId(), true, false, ADMIN_AUTH_HEADERS);
|
||||
queryParams.clear();
|
||||
queryParams.put("include", "all");
|
||||
storedTestCaseResolutions =
|
||||
getTestCaseFailureStatus(startTs, endTs, null, TestCaseResolutionStatusTypes.Ack);
|
||||
getTestCaseFailureStatus(
|
||||
startTs, endTs, null, TestCaseResolutionStatusTypes.Ack, queryParams);
|
||||
assertEquals(2, storedTestCaseResolutions.getData().size());
|
||||
assertTrue(
|
||||
storedTestCaseResolutions.getData().stream()
|
||||
@ -1570,6 +1573,40 @@ public class TestCaseResourceTest extends EntityResourceTest<TestCase, CreateTes
|
||||
paginateTestCaseFailureStatus(maxEntities, allEntities, startTs, endTs);
|
||||
}
|
||||
|
||||
@Test
|
||||
void test_listTestCaseFailureStatusDeletedTestCase(TestInfo test)
|
||||
throws IOException, ParseException {
|
||||
List<TestCase> testCases = new ArrayList<>();
|
||||
Long startTs = System.currentTimeMillis() - 1000;
|
||||
for (int i = 0; i < 2; i++) {
|
||||
// We'll create random test cases
|
||||
TestCase testCaseEntity =
|
||||
createEntity(createRequest(getEntityName(test) + i), ADMIN_AUTH_HEADERS);
|
||||
testCases.add(testCaseEntity);
|
||||
// Adding failed test case, which will create a NEW incident
|
||||
postTestCaseResult(
|
||||
testCaseEntity.getFullyQualifiedName(),
|
||||
new CreateTestCaseResult()
|
||||
.withResult("result")
|
||||
.withTestCaseStatus(TestCaseStatus.Failed)
|
||||
.withTimestamp(TestUtils.dateToTimestamp("2024-01-01")),
|
||||
ADMIN_AUTH_HEADERS);
|
||||
}
|
||||
Long endTs = System.currentTimeMillis() + 1000;
|
||||
ResultList<TestCaseResolutionStatus> entities =
|
||||
getTestCaseFailureStatus(1000, null, false, startTs, endTs, null);
|
||||
assertTrue(
|
||||
entities.getData().stream()
|
||||
.anyMatch(
|
||||
tcrs -> tcrs.getTestCaseReference().getId().equals(testCases.get(0).getId())));
|
||||
deleteEntityByName(testCases.get(0).getFullyQualifiedName(), true, false, ADMIN_AUTH_HEADERS);
|
||||
entities = getTestCaseFailureStatus(1000, null, false, startTs, endTs, null);
|
||||
assertTrue(
|
||||
entities.getData().stream()
|
||||
.noneMatch(
|
||||
tcrs -> tcrs.getTestCaseReference().getId().equals(testCases.get(0).getId())));
|
||||
}
|
||||
|
||||
@Test
|
||||
void patch_TestCaseResultFailure(TestInfo test) throws HttpResponseException {
|
||||
TestCase testCaseEntity = createEntity(createRequest(getEntityName(test)), ADMIN_AUTH_HEADERS);
|
||||
|
||||
@ -254,7 +254,7 @@ test.describe('Incident Manager', PLAYWRIGHT_INGESTION_TAG_OBJ, () => {
|
||||
);
|
||||
|
||||
const incidentDetailsRes = page.waitForResponse(
|
||||
'/api/v1/dataQuality/testCases/testCaseIncidentStatus?latest=true&startTs=*&endTs=*&limit=*'
|
||||
'/api/v1/dataQuality/testCases/testCaseIncidentStatus?*'
|
||||
);
|
||||
await sidebarClick(page, SidebarItem.INCIDENT_MANAGER);
|
||||
await incidentDetailsRes;
|
||||
@ -456,7 +456,7 @@ test.describe('Incident Manager', PLAYWRIGHT_INGESTION_TAG_OBJ, () => {
|
||||
};
|
||||
const testCase1 = table1.testCasesResponseData[0]?.['name'];
|
||||
const incidentDetailsRes = page.waitForResponse(
|
||||
'/api/v1/dataQuality/testCases/testCaseIncidentStatus?latest=true&startTs=*&endTs=*&limit=*'
|
||||
'/api/v1/dataQuality/testCases/testCaseIncidentStatus?*'
|
||||
);
|
||||
await sidebarClick(page, SidebarItem.INCIDENT_MANAGER);
|
||||
await incidentDetailsRes;
|
||||
@ -485,7 +485,7 @@ test.describe('Incident Manager', PLAYWRIGHT_INGESTION_TAG_OBJ, () => {
|
||||
).not.toBeVisible();
|
||||
|
||||
const nonAssigneeFilterRes = page.waitForResponse(
|
||||
'/api/v1/dataQuality/testCases/testCaseIncidentStatus?latest=true&startTs=*&endTs=*&limit=*'
|
||||
'/api/v1/dataQuality/testCases/testCaseIncidentStatus?*'
|
||||
);
|
||||
await page
|
||||
.getByTestId('select-assignee')
|
||||
@ -508,7 +508,7 @@ test.describe('Incident Manager', PLAYWRIGHT_INGESTION_TAG_OBJ, () => {
|
||||
).not.toBeVisible();
|
||||
|
||||
const nonStatusFilterRes = page.waitForResponse(
|
||||
'/api/v1/dataQuality/testCases/testCaseIncidentStatus?latest=true&startTs=*&endTs=*&limit=*'
|
||||
'/api/v1/dataQuality/testCases/testCaseIncidentStatus?*'
|
||||
);
|
||||
await page.getByTestId('status-select').getByLabel('close-circle').click();
|
||||
await nonStatusFilterRes;
|
||||
@ -534,7 +534,7 @@ test.describe('Incident Manager', PLAYWRIGHT_INGESTION_TAG_OBJ, () => {
|
||||
).toBeVisible();
|
||||
|
||||
const nonTestCaseFilterRes = page.waitForResponse(
|
||||
'/api/v1/dataQuality/testCases/testCaseIncidentStatus?latest=true&startTs=*&endTs=*&limit=*'
|
||||
'/api/v1/dataQuality/testCases/testCaseIncidentStatus?*'
|
||||
);
|
||||
await page
|
||||
.getByTestId('test-case-select')
|
||||
@ -544,7 +544,7 @@ test.describe('Incident Manager', PLAYWRIGHT_INGESTION_TAG_OBJ, () => {
|
||||
|
||||
await page.click('[data-testid="date-picker-menu"]');
|
||||
const timeSeriesFilterRes = page.waitForResponse(
|
||||
'/api/v1/dataQuality/testCases/testCaseIncidentStatus?latest=true&startTs=*&endTs=*&limit=*'
|
||||
'/api/v1/dataQuality/testCases/testCaseIncidentStatus?*'
|
||||
);
|
||||
await page.getByRole('menuitem', { name: 'Yesterday' }).click();
|
||||
await timeSeriesFilterRes;
|
||||
|
||||
@ -73,19 +73,23 @@ const mockPermissions = {
|
||||
} as OperationPermission;
|
||||
|
||||
describe('TableProfilerProvider', () => {
|
||||
beforeEach(() => {
|
||||
it('renders children without crashing', async () => {
|
||||
render(
|
||||
<TableProfilerProvider permissions={mockPermissions} table={MOCK_TABLE}>
|
||||
<div>Test Children</div>
|
||||
</TableProfilerProvider>
|
||||
);
|
||||
});
|
||||
|
||||
it('renders children without crashing', async () => {
|
||||
expect(await screen.findByText('Test Children')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('test cases should be fetch on data quality tab', async () => {
|
||||
render(
|
||||
<TableProfilerProvider permissions={mockPermissions} table={MOCK_TABLE}>
|
||||
<div>Test Children</div>
|
||||
</TableProfilerProvider>
|
||||
);
|
||||
|
||||
const mockGetListTestCase = getListTestCaseBySearch as jest.Mock;
|
||||
|
||||
expect(mockGetListTestCase).toHaveBeenCalledTimes(1);
|
||||
@ -94,6 +98,28 @@ describe('TableProfilerProvider', () => {
|
||||
fields: ['testCaseResult', 'incidentId'],
|
||||
includeAllTests: true,
|
||||
limit: 10,
|
||||
include: 'non-deleted',
|
||||
});
|
||||
});
|
||||
|
||||
it('test cases should be fetch on data quality tab with deleted', async () => {
|
||||
render(
|
||||
<TableProfilerProvider
|
||||
permissions={mockPermissions}
|
||||
table={{ ...MOCK_TABLE, deleted: true }}>
|
||||
<div>Test Children</div>
|
||||
</TableProfilerProvider>
|
||||
);
|
||||
|
||||
const mockGetListTestCase = getListTestCaseBySearch as jest.Mock;
|
||||
|
||||
expect(mockGetListTestCase).toHaveBeenCalledTimes(1);
|
||||
expect(mockGetListTestCase).toHaveBeenCalledWith({
|
||||
entityLink: 'entityLink',
|
||||
fields: ['testCaseResult', 'incidentId'],
|
||||
includeAllTests: true,
|
||||
limit: 10,
|
||||
include: 'deleted',
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@ -35,6 +35,7 @@ import { TabSpecificField } from '../../../../enums/entity.enum';
|
||||
import { Table } from '../../../../generated/entity/data/table';
|
||||
import { ProfileSampleType } from '../../../../generated/metadataIngestion/databaseServiceProfilerPipeline';
|
||||
import { TestCase } from '../../../../generated/tests/testCase';
|
||||
import { Include } from '../../../../generated/type/include';
|
||||
import { usePaging } from '../../../../hooks/paging/usePaging';
|
||||
import useCustomLocation from '../../../../hooks/useCustomLocation/useCustomLocation';
|
||||
import { useFqn } from '../../../../hooks/useFqn';
|
||||
@ -222,6 +223,7 @@ export const TableProfilerProvider = ({
|
||||
entityLink: generateEntityLink(datasetFQN ?? ''),
|
||||
includeAllTests: true,
|
||||
limit: testCasePaging.pageSize,
|
||||
include: isTableDeleted ? Include.Deleted : Include.NonDeleted,
|
||||
});
|
||||
|
||||
setAllTestCases(data);
|
||||
|
||||
@ -35,6 +35,7 @@ import {
|
||||
TestCaseResolutionStatus,
|
||||
TestCaseResolutionStatusTypes,
|
||||
} from '../../generated/tests/testCaseResolutionStatus';
|
||||
import { Include } from '../../generated/type/include';
|
||||
import { usePaging } from '../../hooks/paging/usePaging';
|
||||
import useCustomLocation from '../../hooks/useCustomLocation/useCustomLocation';
|
||||
import {
|
||||
@ -154,6 +155,7 @@ const IncidentManager = ({
|
||||
const { data, paging } = await getListTestCaseIncidentStatus({
|
||||
limit: pageSize,
|
||||
latest: true,
|
||||
include: tableDetails?.deleted ? Include.Deleted : Include.NonDeleted,
|
||||
originEntityFQN: tableDetails?.fullyQualifiedName,
|
||||
...params,
|
||||
});
|
||||
@ -463,7 +465,7 @@ const IncidentManager = ({
|
||||
return (
|
||||
<TestCaseIncidentManagerStatus
|
||||
data={record}
|
||||
hasPermission={hasPermission?.EditAll}
|
||||
hasPermission={hasPermission?.EditAll && !tableDetails?.deleted}
|
||||
onSubmit={handleStatusSubmit}
|
||||
/>
|
||||
);
|
||||
@ -487,7 +489,7 @@ const IncidentManager = ({
|
||||
|
||||
return (
|
||||
<Severity
|
||||
hasPermission={hasPermission?.EditAll}
|
||||
hasPermission={hasPermission?.EditAll && !tableDetails?.deleted}
|
||||
severity={value}
|
||||
onSubmit={(severity) => handleSeveritySubmit(severity, record)}
|
||||
/>
|
||||
@ -507,7 +509,12 @@ const IncidentManager = ({
|
||||
),
|
||||
},
|
||||
],
|
||||
[testCaseListData.data, testCasePermissions, isPermissionLoading]
|
||||
[
|
||||
tableDetails?.deleted,
|
||||
testCaseListData.data,
|
||||
testCasePermissions,
|
||||
isPermissionLoading,
|
||||
]
|
||||
);
|
||||
|
||||
if (
|
||||
|
||||
@ -13,6 +13,7 @@
|
||||
import { act, fireEvent, render, screen } from '@testing-library/react';
|
||||
import QueryString from 'qs';
|
||||
import React from 'react';
|
||||
import { Table } from '../../generated/entity/data/table';
|
||||
import { MOCK_PERMISSIONS } from '../../mocks/Glossary.mock';
|
||||
import { getListTestCaseIncidentStatus } from '../../rest/incidentManagerAPI';
|
||||
import IncidentManager from './IncidentManager.component';
|
||||
@ -153,6 +154,29 @@ describe('IncidentManagerPage', () => {
|
||||
latest: true,
|
||||
limit: 10,
|
||||
startTs: 1709556624254,
|
||||
include: 'non-deleted',
|
||||
});
|
||||
});
|
||||
|
||||
it('Incident should be fetch with deleted', async () => {
|
||||
const mockGetListTestCaseIncidentStatus =
|
||||
getListTestCaseIncidentStatus as jest.Mock;
|
||||
await act(async () => {
|
||||
render(<IncidentManager tableDetails={{ deleted: true } as Table} />);
|
||||
});
|
||||
|
||||
const timeFilterButton = await screen.findByTestId('time-filter');
|
||||
|
||||
await act(async () => {
|
||||
fireEvent.click(timeFilterButton);
|
||||
});
|
||||
|
||||
expect(mockGetListTestCaseIncidentStatus).toHaveBeenCalledWith({
|
||||
endTs: 1710161424255,
|
||||
latest: true,
|
||||
limit: 10,
|
||||
startTs: 1709556624254,
|
||||
include: 'deleted',
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@ -20,6 +20,7 @@ import {
|
||||
} from '../../generated/tests/testDefinition';
|
||||
import { ListTestCaseParamsBySearch } from '../../rest/testAPI';
|
||||
import {
|
||||
buildDataQualityDashboardFilters,
|
||||
buildMustEsFilterForOwner,
|
||||
buildMustEsFilterForTags,
|
||||
buildTestCaseParams,
|
||||
@ -738,4 +739,45 @@ describe('DataQualityUtils', () => {
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('buildDataQualityDashboardFilters', () => {
|
||||
it('should include deleted:false filter by default', () => {
|
||||
const result = buildDataQualityDashboardFilters({});
|
||||
|
||||
expect(result).toEqual([
|
||||
{
|
||||
term: {
|
||||
deleted: false,
|
||||
},
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
it('should include deleted:false filter along with other filters', () => {
|
||||
const result = buildDataQualityDashboardFilters({
|
||||
filters: {
|
||||
serviceName: 'test-service',
|
||||
testPlatforms: ['DBT'],
|
||||
},
|
||||
});
|
||||
|
||||
expect(result).toEqual([
|
||||
{
|
||||
term: {
|
||||
'service.name.keyword': 'test-service',
|
||||
},
|
||||
},
|
||||
{
|
||||
terms: {
|
||||
testPlatforms: ['DBT'],
|
||||
},
|
||||
},
|
||||
{
|
||||
term: {
|
||||
deleted: false,
|
||||
},
|
||||
},
|
||||
]);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@ -325,6 +325,13 @@ export const buildDataQualityDashboardFilters = (data: {
|
||||
}
|
||||
}
|
||||
|
||||
// Add the deleted filter to the mustFilter array
|
||||
mustFilter.push({
|
||||
term: {
|
||||
deleted: false,
|
||||
},
|
||||
});
|
||||
|
||||
return mustFilter;
|
||||
};
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user