Skip to content

Commit

Permalink
open-metadata#14067: Recursive true while soft deletion and deleted e…
Browse files Browse the repository at this point in the history
…ntity version page bug fixes (open-metadata#14162)

* Fixed bug where database, schema, service version page not showing for deleted entities
UI changes for soft deletion and restore flow

* fixed version not updating after deletion and restoration of assets.

* fixed stored procedures not listing for name with special characters

* added checks for deleted assets version page

* added cypress for soft delete and restore with different flows for services and child assets

* fixed failing unit test

* fixed failing unit test

* Fixed cypress tests
  • Loading branch information
aniketkatkar97 authored and Shiyang Xiao committed Dec 12, 2023
1 parent c013b4b commit 2a04627
Show file tree
Hide file tree
Showing 67 changed files with 1,066 additions and 286 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ export const createSingleLevelEntity = ({
export const hardDeleteService = ({ serviceFqn, token, serviceType }) => {
cy.request({
method: 'GET',
url: `/api/v1/services/${serviceType}/name/${serviceFqn}`,
url: `/api/v1/services/${serviceType}/name/${serviceFqn}?include=all`,
headers: { Authorization: `Bearer ${token}` },
}).then((response) => {
cy.request({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,21 @@
/// <reference types="cypress" />

import { DATA_ASSETS } from '../constants/constants';
import { DATABASE_SERVICE } from '../constants/EntityConstant';
import { SERVICE_CATEGORIES } from '../constants/service.constants';
import {
CUSTOM_ATTRIBUTE_NAME,
DATABASE_SCHEMA_SOFT_DELETE_TEST,
ENTITIES_WITHOUT_FOLLOWING_BUTTON,
LIST_OF_FIELDS_TO_EDIT_NOT_TO_BE_PRESENT,
LIST_OF_FIELDS_TO_EDIT_TO_BE_DISABLED,
} from '../constants/SoftDeleteFlow.constants';
import { interceptURL, verifyResponseStatusCode } from './common';
import {
interceptURL,
verifyResponseStatusCode,
visitDatabaseSchemaDetailsPage,
visitServiceDetailsPage,
} from './common';

export const checkCustomPropertyEditButton = ({
verifyAPIResponse = false,
Expand Down Expand Up @@ -62,7 +70,7 @@ export const checkForEditActions = ({
return !ENTITIES_WITHOUT_FOLLOWING_BUTTON.includes(entityType);
}

return entityType !== 'services/databaseServices';
return !entityType.startsWith('services/');
}).map(({ containerSelector, elementSelector }) => {
cy.get(`${containerSelector} ${elementSelector}`).should(
`${checkIsActionEnabled ? 'not.' : ''}be.disabled`
Expand Down Expand Up @@ -251,6 +259,142 @@ export const softDeletedEntityCommonChecks = ({
}
};

export const softDeletedEntityChecksForServices = ({
serviceName,
serviceCategory,
settingsMenuId,
childName,
createdEntityIds,
}) => {
const entityType = `services/${serviceCategory}`;

// Check if all the edit actions are available for the service
checkForEditActions({
entityType,
verifyAPIResponse: true,
});

// Soft delete the service
cy.get('[data-testid="manage-button"]').click();
cy.get('[data-testid="delete-button-title"]').click();
cy.get('[data-testid="confirmation-text-input"]').type('DELETE');
cy.get('[data-testid="confirm-button"]').click();
cy.get('.Toastify__close-button').click();
cy.get('[data-testid="deleted-badge"]').should('be.visible');

checkForEditActions({
entityType,
checkIsActionEnabled: false,
});

// For database services follow restoring chronologically as
// table - schema - database(service child asset) - service
if (serviceCategory === SERVICE_CATEGORIES.DATABASE_SERVICES) {
// Restoring table
visitDatabaseSchemaDetailsPage({
settingsMenuId: DATABASE_SCHEMA_SOFT_DELETE_TEST.settingsMenuId,
serviceCategory: DATABASE_SCHEMA_SOFT_DELETE_TEST.serviceCategory,
serviceName: DATABASE_SCHEMA_SOFT_DELETE_TEST.serviceName,
databaseRowKey: createdEntityIds.databaseId,
databaseName: DATABASE_SCHEMA_SOFT_DELETE_TEST.databaseName,
databaseSchemaRowKey: createdEntityIds.databaseSchemaId,
databaseSchemaName: DATABASE_SCHEMA_SOFT_DELETE_TEST.databaseSchemaName,
isDeleted: true,
});

cy.get('[data-testid="table-name-link"]')
.should('contain', DATABASE_SERVICE.entity.name)
.click();

cy.get('[data-testid="manage-button"]').click();
cy.get('[data-testid="restore-button-title"]').click();

interceptURL('PUT', '/api/v1/tables/restore', 'restoreTable');

cy.get('.ant-modal-footer .ant-btn-primary').contains('Restore').click();

verifyResponseStatusCode('@restoreTable', 200);
cy.get('.Toastify__close-button').click();

// Restoring schema
visitDatabaseSchemaDetailsPage({
settingsMenuId: DATABASE_SCHEMA_SOFT_DELETE_TEST.settingsMenuId,
serviceCategory: DATABASE_SCHEMA_SOFT_DELETE_TEST.serviceCategory,
serviceName: DATABASE_SCHEMA_SOFT_DELETE_TEST.serviceName,
databaseRowKey: createdEntityIds.databaseId,
databaseName: DATABASE_SCHEMA_SOFT_DELETE_TEST.databaseName,
databaseSchemaRowKey: createdEntityIds.databaseSchemaId,
databaseSchemaName: DATABASE_SCHEMA_SOFT_DELETE_TEST.databaseSchemaName,
isDeleted: true,
});

cy.get('[data-testid="manage-button"]').click();
cy.get('[data-testid="restore-button-title"]').click();

interceptURL('PUT', '/api/v1/databaseSchemas/restore', 'restoreSchema');

cy.get('.ant-modal-footer .ant-btn-primary').contains('Restore').click();

verifyResponseStatusCode('@restoreSchema', 200);
cy.get('.Toastify__close-button').click();

visitServiceDetailsPage(settingsMenuId, serviceCategory, serviceName, true);
}

// Restore child asset
interceptURL('GET', '/api/v1/*include=deleted*', 'fetchDeletedChildren');

cy.get('[data-testid="show-deleted"]').click();

verifyResponseStatusCode('@fetchDeletedChildren', 200);

cy.get(`[data-testid="child-asset-name-link"]`)
.should('contain', childName)
.click();

cy.get('[data-testid="manage-button"]').click();
cy.get('[data-testid="restore-button-title"]').click();

interceptURL('PUT', '/api/v1/*/restore', 'restoreChild');

cy.get('.ant-modal-footer .ant-btn-primary').contains('Restore').click();

verifyResponseStatusCode('@restoreChild', 200);
cy.get('.Toastify__close-button').click();

visitServiceDetailsPage(settingsMenuId, serviceCategory, serviceName, true);

cy.get('[data-testid="manage-button"]').click();

// only two menu options (restore and delete) should be present
cy.get(
'[data-testid="manage-dropdown-list-container"] [data-testid="announcement-button"]'
).should('not.exist');
cy.get(
'[data-testid="manage-dropdown-list-container"] [data-testid="rename-button"]'
).should('not.exist');
cy.get(
'[data-testid="manage-dropdown-list-container"] [data-testid="profiler-setting-button"]'
).should('not.exist');
cy.get(
'[data-testid="manage-dropdown-list-container"] [data-testid="restore-button"]'
).should('be.visible');
cy.get(
'[data-testid="manage-dropdown-list-container"] [data-testid="delete-button"]'
).should('be.visible');

// Restore service
cy.get('[data-testid="restore-button-title"]').click();

interceptURL('PUT', '/api/v1/*/*/restore', 'restoreEntity');

cy.get('.ant-modal-footer .ant-btn-primary').contains('Restore').click();

verifyResponseStatusCode('@restoreEntity', 200);

checkForEditActions({ entityType });
};

export const nonDeletedTeamChecks = () => {
cy.get('[data-testid="manage-button"]').scrollIntoView().click();
cy.get('[data-testid="import-button-title"]').should('be.visible');
Expand Down
40 changes: 35 additions & 5 deletions openmetadata-ui/src/main/resources/ui/cypress/common/common.js
Original file line number Diff line number Diff line change
Expand Up @@ -1191,6 +1191,7 @@ export const addOwner = (
cy.get('[data-testid="edit-owner"]').click();
}

cy.log('/api/v1/users?limit=*&isBot=false*');
cy.get('.ant-tabs [id*=tab-users]').click();
verifyResponseStatusCode('@getUsers', 200);

Expand Down Expand Up @@ -1286,7 +1287,7 @@ export const deleteEntity = (

interceptURL(
'DELETE',
`api/v1/${entity}/*?hardDelete=${deletionType === 'hard'}&recursive=false`,
`api/v1/${entity}/*?hardDelete=${deletionType === 'hard'}&recursive=true`,
`${deletionType}DeleteTable`
);
cy.get('[data-testid="confirm-button"]').should('not.be.disabled');
Expand All @@ -1299,11 +1300,12 @@ export const deleteEntity = (
export const visitServiceDetailsPage = (
settingsMenuId,
serviceCategory,
serviceName
serviceName,
isServiceDeleted = false
) => {
interceptURL(
'GET',
'api/v1/search/query?q=*&from=0&size=15&index=*',
`/api/v1/search/query?q=*${isServiceDeleted ? 'deleted=true' : ''}`,
'searchService'
);
interceptURL('GET', '/api/v1/teams/name/*', 'getOrganization');
Expand All @@ -1318,9 +1320,13 @@ export const visitServiceDetailsPage = (

verifyResponseStatusCode('@getServices', 200);

if (isServiceDeleted) {
cy.get('[data-testid="show-deleted-switch"]').click();
}

interceptURL(
'GET',
`api/v1/services/${serviceCategory}/name/${serviceName}?fields=*`,
`api/v1/services/${serviceCategory}/name/${serviceName}*`,
'getServiceDetails'
);

Expand Down Expand Up @@ -1703,8 +1709,20 @@ export const visitDatabaseDetailsPage = ({
serviceName,
databaseRowKey,
databaseName,
isDeleted = false,
}) => {
visitServiceDetailsPage(settingsMenuId, serviceCategory, serviceName);
visitServiceDetailsPage(
settingsMenuId,
serviceCategory,
serviceName,
isDeleted
);

if (isDeleted) {
interceptURL('GET', `/api/v1/databases*include=deleted*`, 'getDatabases');
cy.get('[data-testid="show-deleted"]').click();
verifyResponseStatusCode('@getDatabases', 200);
}

cy.get(`[data-row-key="${databaseRowKey}"]`).contains(databaseName).click();
};
Expand All @@ -1717,15 +1735,27 @@ export const visitDatabaseSchemaDetailsPage = ({
databaseName,
databaseSchemaRowKey,
databaseSchemaName,
isDeleted = false,
}) => {
visitDatabaseDetailsPage({
settingsMenuId,
serviceCategory,
serviceName,
databaseRowKey,
databaseName,
isDeleted,
});

if (isDeleted) {
interceptURL(
'GET',
`/api/v1/databaseSchemas*include=deleted*`,
'getDatabaseSchemas'
);
cy.get('[data-testid="show-deleted"]').click();
verifyResponseStatusCode('@getDatabaseSchemas', 200);
}

cy.get(`[data-row-key="${databaseSchemaRowKey}"]`)
.contains(databaseSchemaName)
.click();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ export const TIER = 'Tier1';

export const POLICY_NAME = `soft_del_policy_${uuid()}`;
export const ROLE_NAME = `soft_del_role_${uuid()}`;
export const TEST_CASE_NAME = `soft_del_test_case_${uuid()}`;
export const TEAM_1_NAME = `soft_del_team_1_${uuid()}`;
export const TEAM_2_NAME = `soft_del_team_2_${uuid()}`;
export const CUSTOM_ATTRIBUTE_NAME = `softDeleteTestProperty${uuid()}`;
Expand All @@ -43,8 +44,61 @@ export const DATABASE_SERVICE_DETAILS_SOFT_DELETE_TEST = {
settingsMenuId: 'services.databases',
serviceCategory: SERVICE_CATEGORIES.DATABASE_SERVICES,
serviceName: DATABASE_SERVICE.service.name,
childName: DATABASE_SERVICE.database.name,
};

export const MESSAGING_SERVICE_DETAILS_SOFT_DELETE_TEST = {
settingsMenuId: 'services.messaging',
serviceCategory: SERVICE_CATEGORIES.MESSAGING_SERVICES,
serviceName: MESSAGING_SERVICE.service.name,
childName: MESSAGING_SERVICE.entity.name,
};

export const DASHBOARD_SERVICE_DETAILS_SOFT_DELETE_TEST = {
settingsMenuId: 'services.dashboards',
serviceCategory: SERVICE_CATEGORIES.DASHBOARD_SERVICES,
serviceName: DASHBOARD_SERVICE.service.name,
childName: DASHBOARD_SERVICE.entity.name,
};

export const PIPELINE_SERVICE_DETAILS_SOFT_DELETE_TEST = {
settingsMenuId: 'services.pipelines',
serviceCategory: SERVICE_CATEGORIES.PIPELINE_SERVICES,
serviceName: PIPELINE_SERVICE.service.name,
childName: PIPELINE_SERVICE.entity.name,
};

export const ML_MODEL_SERVICE_DETAILS_SOFT_DELETE_TEST = {
settingsMenuId: 'services.mlModels',
serviceCategory: SERVICE_CATEGORIES.ML_MODEL_SERVICES,
serviceName: ML_MODEL_SERVICE.service.name,
childName: ML_MODEL_SERVICE.entity.name,
};

export const STORAGE_SERVICE_DETAILS_SOFT_DELETE_TEST = {
settingsMenuId: 'services.storages',
serviceCategory: SERVICE_CATEGORIES.STORAGE_SERVICES,
serviceName: STORAGE_SERVICE.service.name,
childName: STORAGE_SERVICE.entity.name,
};

export const SEARCH_SERVICE_DETAILS_SOFT_DELETE_TEST = {
settingsMenuId: 'services.search',
serviceCategory: SERVICE_CATEGORIES.SEARCH_SERVICES,
serviceName: SEARCH_SERVICE.service.name,
childName: SEARCH_SERVICE.entity.name,
};

export const SERVICES_LIST = [
DATABASE_SERVICE_DETAILS_SOFT_DELETE_TEST,
MESSAGING_SERVICE_DETAILS_SOFT_DELETE_TEST,
DASHBOARD_SERVICE_DETAILS_SOFT_DELETE_TEST,
PIPELINE_SERVICE_DETAILS_SOFT_DELETE_TEST,
ML_MODEL_SERVICE_DETAILS_SOFT_DELETE_TEST,
STORAGE_SERVICE_DETAILS_SOFT_DELETE_TEST,
SEARCH_SERVICE_DETAILS_SOFT_DELETE_TEST,
];

export const DATABASE_SOFT_DELETE_TEST = {
...DATABASE_SERVICE_DETAILS_SOFT_DELETE_TEST,
databaseName: DATABASE_SERVICE.database.name,
Expand Down Expand Up @@ -183,6 +237,13 @@ export const ENTITIES_WITHOUT_FOLLOWING_BUTTON = [
'databases',
'databaseSchemas',
'services/databaseServices',
'services/messagingServices',
'services/pipelineServices',
'services/dashboardServices',
'services/mlmodelServices',
'services/storageServices',
'services/metadataServices',
'services/searchServices',
];

export const TEAM_1_DETAILS_SOFT_DELETE_TEST = {
Expand All @@ -196,3 +257,19 @@ export const TEAM_2_DETAILS_SOFT_DELETE_TEST = {
displayName: TEAM_2_NAME,
teamType: 'Group',
};

// eslint-disable-next-line max-len
export const TABLE_FQN = `${DATABASE_SERVICE_SOFT_DELETE_TEST.service.name}.${DATABASE_SERVICE_SOFT_DELETE_TEST.database.name}.${DATABASE_SERVICE_SOFT_DELETE_TEST.schema.name}.${DATABASE_SERVICE_SOFT_DELETE_TEST.entity.name}`;

export const TEST_CASE_DETAILS = {
name: TEST_CASE_NAME,
entityLink: `<#E::table::${TABLE_FQN}>`,
testDefinition: 'tableColumnCountToEqual',
testSuite: `${TABLE_FQN}.testSuite`,
parameterValues: [
{
name: 'columnCount',
value: 5,
},
],
};
Loading

0 comments on commit 2a04627

Please sign in to comment.