mirror of
https://github.com/open-metadata/OpenMetadata.git
synced 2025-12-10 23:05:55 +00:00
chore(ui): added cypress tests for version pages and related bug fixes (#12943)
* Fixed version page flaky no data placeholder removed code duplication in DataModelVersion component * fixed clear tier functionality for containers and data models * Added cypress tests for version pages * fixed unit tests
This commit is contained in:
parent
f6fc2e3b0c
commit
4fa5a1d8bb
@ -0,0 +1,96 @@
|
||||
/*
|
||||
* Copyright 2023 Collate.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
// / <reference types="Cypress" />
|
||||
|
||||
import { isUndefined } from 'lodash';
|
||||
import {
|
||||
interceptURL,
|
||||
verifyResponseStatusCode,
|
||||
visitDataModelPage,
|
||||
visitEntityDetailsPage,
|
||||
} from './common';
|
||||
|
||||
export const visitEntityDetailsVersionPage = (
|
||||
entityDetails,
|
||||
id,
|
||||
entityFQN,
|
||||
version
|
||||
) => {
|
||||
visitEntityDetailsPage(
|
||||
entityDetails.term,
|
||||
entityDetails.serviceName,
|
||||
entityDetails.entity,
|
||||
undefined,
|
||||
entityDetails.entityType
|
||||
);
|
||||
|
||||
interceptURL(
|
||||
'GET',
|
||||
`/api/v1/${entityDetails.entity}/name/${entityFQN}?*include=all`,
|
||||
'getTableDetails'
|
||||
);
|
||||
interceptURL(
|
||||
'GET',
|
||||
`/api/v1/${entityDetails.entity}/${id}/versions`,
|
||||
'getVersionsList'
|
||||
);
|
||||
interceptURL(
|
||||
'GET',
|
||||
`/api/v1/${entityDetails.entity}/${id}/versions/${version ?? '*'}`,
|
||||
'getSelectedVersionDetails'
|
||||
);
|
||||
|
||||
cy.get('[data-testid="version-button"]').as('versionButton');
|
||||
|
||||
if (!isUndefined(version)) {
|
||||
cy.get('@versionButton').contains(version);
|
||||
}
|
||||
|
||||
cy.get('@versionButton').click();
|
||||
|
||||
verifyResponseStatusCode('@getTableDetails', 200);
|
||||
verifyResponseStatusCode('@getVersionsList', 200);
|
||||
verifyResponseStatusCode('@getSelectedVersionDetails', 200);
|
||||
};
|
||||
|
||||
export const visitDataModelVersionPage = (
|
||||
dataModelFQN,
|
||||
dataModelId,
|
||||
dataModelName,
|
||||
version
|
||||
) => {
|
||||
visitDataModelPage(dataModelFQN, dataModelName);
|
||||
|
||||
interceptURL(
|
||||
'GET',
|
||||
`/api/v1/dashboard/datamodels/${dataModelId}/versions`,
|
||||
'getVersionsList'
|
||||
);
|
||||
interceptURL(
|
||||
'GET',
|
||||
`/api/v1/dashboard/datamodels/${dataModelId}/versions/${version ?? '*'}`,
|
||||
'getSelectedVersionDetails'
|
||||
);
|
||||
|
||||
cy.get('[data-testid="version-button"]').as('versionButton');
|
||||
|
||||
if (!isUndefined(version)) {
|
||||
cy.get('@versionButton').contains(version);
|
||||
}
|
||||
|
||||
cy.get('@versionButton').click();
|
||||
|
||||
verifyResponseStatusCode('@getDataModelDetails', 200);
|
||||
verifyResponseStatusCode('@getVersionsList', 200);
|
||||
verifyResponseStatusCode('@getSelectedVersionDetails', 200);
|
||||
};
|
||||
@ -1090,71 +1090,155 @@ export const updateDescriptionForIngestedTables = (
|
||||
.should('contain', description);
|
||||
};
|
||||
|
||||
export const followAndOwnTheEntity = (termObj) => {
|
||||
// search for the term and redirect to the respective entity tab
|
||||
export const addOwner = (ownerName, entity, isGlossaryPage) => {
|
||||
cy.get('[data-testid="edit-owner"]').click();
|
||||
|
||||
interceptURL('GET', '/api/v1/users?&isBot=false&limit=15', 'getUsers');
|
||||
cy.get('.ant-tabs [id*=tab-users]').click();
|
||||
verifyResponseStatusCode('@getUsers', 200);
|
||||
|
||||
visitEntityDetailsPage(termObj.term, termObj.serviceName, termObj.entity);
|
||||
// go to manage tab and search for logged in user and set the owner
|
||||
interceptURL(
|
||||
'GET',
|
||||
'/api/v1/search/query?q=*%20AND%20teamType:Group&from=0&size=15&index=team_search_index',
|
||||
'getTeams'
|
||||
`api/v1/search/query?q=*${encodeURI(ownerName)}*`,
|
||||
'searchOwner'
|
||||
);
|
||||
cy.get('[data-testid="edit-owner"]').should('be.visible').click();
|
||||
|
||||
verifyResponseStatusCode('@getTeams', 200);
|
||||
// Clicking on users tab
|
||||
cy.get('.user-team-select-popover')
|
||||
.contains('Users')
|
||||
.should('exist')
|
||||
.should('be.visible')
|
||||
.click();
|
||||
cy.get('[data-testid="owner-select-users-search-bar"]').type(ownerName);
|
||||
|
||||
cy.get('[data-testid="selectable-list"]')
|
||||
.eq(1)
|
||||
.should('exist')
|
||||
.should('be.visible')
|
||||
.find('[title="admin"]')
|
||||
.should('be.visible')
|
||||
.click();
|
||||
verifyResponseStatusCode('@searchOwner', 200);
|
||||
|
||||
cy.get('[data-testid="owner-link"]')
|
||||
.scrollIntoView()
|
||||
.invoke('text')
|
||||
.then((text) => {
|
||||
expect(text).equal('admin');
|
||||
});
|
||||
interceptURL('PATCH', `/api/v1/${entity}/*`, 'patchOwner');
|
||||
|
||||
interceptURL('PUT', '/api/v1/*/*/followers', 'waitAfterFollow');
|
||||
cy.get('[data-testid="follow-button"]')
|
||||
.scrollIntoView()
|
||||
.should('be.visible')
|
||||
.click();
|
||||
verifyResponseStatusCode('@waitAfterFollow', 200);
|
||||
|
||||
cy.clickOnLogo();
|
||||
|
||||
cy.get('[data-testid="message-container"]')
|
||||
.first()
|
||||
.contains(`Followed ${termObj.entity.slice(0, -1)}`)
|
||||
.should('be.visible');
|
||||
|
||||
// checks newly generated feed for follow and setting owner
|
||||
cy.get('[data-testid="message-container"]')
|
||||
.eq(1)
|
||||
.scrollIntoView()
|
||||
.contains('Added owner: admin')
|
||||
.should('be.visible');
|
||||
|
||||
// Check followed entity on mydata page
|
||||
cy.get('[data-testid="following-data-container"]')
|
||||
.find(`[data-testid="following-${termObj.displayName}"]`)
|
||||
.should('be.visible');
|
||||
|
||||
// Check owned entity
|
||||
cy.get('[data-testid="my-data-container"]')
|
||||
.find(`[data-testid="My data-${termObj.displayName}"]`)
|
||||
.should('be.visible');
|
||||
|
||||
cy.clickOnLogo();
|
||||
cy.get(`.ant-popover [title="${ownerName}"]`).click();
|
||||
verifyResponseStatusCode('@patchOwner', 200);
|
||||
if (isGlossaryPage) {
|
||||
cy.get('[data-testid="glossary-owner-name"]').should('contain', ownerName);
|
||||
} else {
|
||||
cy.get('[data-testid="owner-link"]').should('contain', ownerName);
|
||||
}
|
||||
};
|
||||
|
||||
export const removeOwner = (entity, isGlossaryPage) => {
|
||||
interceptURL('PATCH', `/api/v1/${entity}/*`, 'patchOwner');
|
||||
|
||||
cy.get('[data-testid="edit-owner"]').click();
|
||||
|
||||
cy.get('[data-testid="remove-owner"]').click();
|
||||
verifyResponseStatusCode('@patchOwner', 200);
|
||||
if (isGlossaryPage) {
|
||||
cy.get('[data-testid="glossary-owner-name"] > [data-testid="Add"]').should(
|
||||
'be.visible'
|
||||
);
|
||||
} else {
|
||||
cy.get('[data-testid="owner-link"]').should('contain', 'No Owner');
|
||||
}
|
||||
};
|
||||
|
||||
export const addTier = (tier, entity) => {
|
||||
interceptURL('PATCH', `/api/v1/${entity}/*`, 'patchTier');
|
||||
|
||||
interceptURL('GET', '/api/v1/tags?parent=Tier&limit=10', 'fetchTier');
|
||||
cy.get('[data-testid="edit-tier"]').click();
|
||||
verifyResponseStatusCode('@fetchTier', 200);
|
||||
cy.get('[data-testid="radio-btn-Tier1"]').click({ waitForAnimations: true });
|
||||
verifyResponseStatusCode('@patchTier', 200);
|
||||
cy.get('[data-testid="radio-btn-Tier1"]').should('be.checked');
|
||||
|
||||
cy.clickOutside();
|
||||
cy.get('[data-testid="Tier"]').should('contain', tier);
|
||||
};
|
||||
|
||||
export const removeTier = (entity) => {
|
||||
interceptURL('PATCH', `/api/v1/${entity}/*`, 'patchTier');
|
||||
|
||||
cy.get('[data-testid="edit-tier"]').click();
|
||||
cy.get('[data-testid="clear-tier"]').should('be.visible').click();
|
||||
|
||||
verifyResponseStatusCode('@patchTier', 200);
|
||||
cy.get('[data-testid="Tier"]').should('contain', 'No Tier');
|
||||
};
|
||||
|
||||
export const deleteEntity = (
|
||||
entityName,
|
||||
serviceName,
|
||||
entity,
|
||||
entityType,
|
||||
successMessageEntityName,
|
||||
deletionType = 'hard'
|
||||
) => {
|
||||
visitEntityDetailsPage(
|
||||
entityName,
|
||||
serviceName,
|
||||
entity,
|
||||
undefined,
|
||||
entityType
|
||||
);
|
||||
|
||||
cy.get('[data-testid="manage-button"]').click();
|
||||
|
||||
cy.get('[data-testid="delete-button-title"]').click();
|
||||
|
||||
cy.get('.ant-modal-header').should('contain', `Delete ${entityName}`);
|
||||
|
||||
cy.get(`[data-testid="${deletionType}-delete-option"]`).click();
|
||||
|
||||
cy.get('[data-testid="confirm-button"]').should('be.disabled');
|
||||
cy.get('[data-testid="confirmation-text-input"]').type(DELETE_TERM);
|
||||
|
||||
interceptURL(
|
||||
'DELETE',
|
||||
`api/v1/${entity}/*?hardDelete=${deletionType === 'hard'}&recursive=false`,
|
||||
`${deletionType}DeleteTable`
|
||||
);
|
||||
cy.get('[data-testid="confirm-button"]').should('not.be.disabled');
|
||||
cy.get('[data-testid="confirm-button"]').click();
|
||||
verifyResponseStatusCode(`@${deletionType}DeleteTable`, 200);
|
||||
|
||||
toastNotification(`${successMessageEntityName} deleted successfully!`, false);
|
||||
};
|
||||
|
||||
export const visitDataModelPage = (dataModelFQN, dataModelName) => {
|
||||
interceptURL('GET', '/api/v1/teams/name/*', 'getOrganization');
|
||||
|
||||
cy.get('[data-testid="appbar-item-settings"]').click();
|
||||
|
||||
verifyResponseStatusCode('@getOrganization', 200);
|
||||
|
||||
interceptURL('GET', '/api/v1/services/dashboardServices*', 'getServices');
|
||||
|
||||
cy.get('[data-menu-id*="services.dashboards"]').scrollIntoView().click();
|
||||
|
||||
verifyResponseStatusCode('@getServices', 200);
|
||||
|
||||
interceptURL(
|
||||
'GET',
|
||||
'api/v1/services/dashboardServices/name/sample_looker?fields=*',
|
||||
'getDashboardDetails'
|
||||
);
|
||||
interceptURL(
|
||||
'GET',
|
||||
'/api/v1/dashboard/datamodels?service=sample_looker&fields=*',
|
||||
'getDataModels'
|
||||
);
|
||||
|
||||
cy.get('[data-testid="service-name-sample_looker"]').scrollIntoView().click();
|
||||
|
||||
verifyResponseStatusCode('@getDashboardDetails', 200);
|
||||
verifyResponseStatusCode('@getDataModels', 200);
|
||||
|
||||
cy.get('[data-testid="data-model"]').scrollIntoView().click();
|
||||
|
||||
verifyResponseStatusCode('@getDataModels', 200);
|
||||
|
||||
interceptURL(
|
||||
'GET',
|
||||
`/api/v1/dashboard/datamodels/name/${dataModelFQN}*`,
|
||||
'getDataModelDetails'
|
||||
);
|
||||
|
||||
cy.get(`[data-testid="data-model-${dataModelName}"]`)
|
||||
.scrollIntoView()
|
||||
.click();
|
||||
|
||||
verifyResponseStatusCode('@getDataModelDetails', 200);
|
||||
};
|
||||
|
||||
@ -0,0 +1,677 @@
|
||||
/*
|
||||
* Copyright 2023 Collate.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
export const OWNER = 'Amber Green';
|
||||
export const TIER = 'Tier1';
|
||||
|
||||
const TABLE_DETAILS_FOR_VERSION_TEST = {
|
||||
name: 'cypress_version_test_table',
|
||||
columns: [
|
||||
{
|
||||
name: 'user_id',
|
||||
dataType: 'NUMERIC',
|
||||
dataTypeDisplay: 'numeric',
|
||||
description:
|
||||
'Unique identifier for the user of your Shopify POS or your Shopify admin.',
|
||||
},
|
||||
{
|
||||
name: 'shop_id',
|
||||
dataType: 'NUMERIC',
|
||||
dataTypeDisplay: 'numeric',
|
||||
description:
|
||||
'The ID of the store. This column is a foreign key reference to the shop_id column in the dim.shop table.',
|
||||
},
|
||||
{
|
||||
name: 'name',
|
||||
dataType: 'VARCHAR',
|
||||
dataLength: 100,
|
||||
dataTypeDisplay: 'varchar',
|
||||
description: 'Name of the staff member.',
|
||||
children: [
|
||||
{
|
||||
name: 'first_name',
|
||||
dataType: 'VARCHAR',
|
||||
dataLength: 100,
|
||||
dataTypeDisplay: 'varchar',
|
||||
description: 'First name of the staff member.',
|
||||
},
|
||||
{
|
||||
name: 'last_name',
|
||||
dataType: 'VARCHAR',
|
||||
dataLength: 100,
|
||||
dataTypeDisplay: 'varchar',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'email',
|
||||
dataType: 'VARCHAR',
|
||||
dataLength: 100,
|
||||
dataTypeDisplay: 'varchar',
|
||||
description: 'Email address of the staff member.',
|
||||
},
|
||||
],
|
||||
databaseSchema: 'sample_data.ecommerce_db.shopify',
|
||||
};
|
||||
|
||||
export const TABLE_PATCH_PAYLOAD = [
|
||||
{
|
||||
op: 'add',
|
||||
path: '/tags/0',
|
||||
value: {
|
||||
labelType: 'Manual',
|
||||
state: 'Confirmed',
|
||||
source: 'Classification',
|
||||
tagFQN: 'PersonalData.SpecialCategory',
|
||||
},
|
||||
},
|
||||
{
|
||||
op: 'add',
|
||||
path: '/columns/2/children/1/description',
|
||||
value: 'Last name of the staff member.',
|
||||
},
|
||||
{
|
||||
op: 'remove',
|
||||
path: '/columns/2/children/0/description',
|
||||
},
|
||||
{
|
||||
op: 'add',
|
||||
path: '/columns/0/tags/0',
|
||||
value: {
|
||||
labelType: 'Manual',
|
||||
state: 'Confirmed',
|
||||
source: 'Classification',
|
||||
tagFQN: 'PersonalData.Personal',
|
||||
},
|
||||
},
|
||||
{
|
||||
op: 'add',
|
||||
path: '/columns/0/tags/1',
|
||||
value: {
|
||||
labelType: 'Manual',
|
||||
state: 'Confirmed',
|
||||
source: 'Classification',
|
||||
tagFQN: 'PII.Sensitive',
|
||||
},
|
||||
},
|
||||
{
|
||||
op: 'add',
|
||||
path: '/description',
|
||||
value: 'Description for cypress_version_test_table',
|
||||
},
|
||||
];
|
||||
|
||||
const TOPIC_DETAILS_FOR_VERSION_TEST = {
|
||||
name: 'cypress_version_test_topic',
|
||||
service: 'sample_kafka',
|
||||
messageSchema: {
|
||||
schemaText: `{"type":"object","required":["name","age","club_name"],"properties":{"name":{"type":"object","required":["first_name","last_name"],
|
||||
"properties":{"first_name":{"type":"string"},"last_name":{"type":"string"}}},"age":{"type":"integer"},"club_name":{"type":"string"}}}`,
|
||||
schemaType: 'JSON',
|
||||
schemaFields: [
|
||||
{
|
||||
name: 'default',
|
||||
dataType: 'RECORD',
|
||||
fullyQualifiedName: 'sample_kafka.cypress_version_test_topic.default',
|
||||
tags: [],
|
||||
children: [
|
||||
{
|
||||
name: 'name',
|
||||
dataType: 'RECORD',
|
||||
fullyQualifiedName:
|
||||
'sample_kafka.cypress_version_test_topic.default.name',
|
||||
tags: [],
|
||||
children: [
|
||||
{
|
||||
name: 'first_name',
|
||||
dataType: 'STRING',
|
||||
description: 'Description for schema field first_name',
|
||||
fullyQualifiedName:
|
||||
'sample_kafka.cypress_version_test_topic.default.name.first_name',
|
||||
tags: [],
|
||||
},
|
||||
{
|
||||
name: 'last_name',
|
||||
dataType: 'STRING',
|
||||
fullyQualifiedName:
|
||||
'sample_kafka.cypress_version_test_topic.default.name.last_name',
|
||||
tags: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'age',
|
||||
dataType: 'INT',
|
||||
fullyQualifiedName:
|
||||
'sample_kafka.cypress_version_test_topic.default.age',
|
||||
tags: [],
|
||||
},
|
||||
{
|
||||
name: 'club_name',
|
||||
dataType: 'STRING',
|
||||
fullyQualifiedName:
|
||||
'sample_kafka.cypress_version_test_topic.default.club_name',
|
||||
tags: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
partitions: 128,
|
||||
};
|
||||
|
||||
export const TOPIC_PATCH_PAYLOAD = [
|
||||
{
|
||||
op: 'add',
|
||||
path: '/tags/0',
|
||||
value: {
|
||||
labelType: 'Manual',
|
||||
state: 'Confirmed',
|
||||
source: 'Classification',
|
||||
tagFQN: 'PersonalData.SpecialCategory',
|
||||
},
|
||||
},
|
||||
{
|
||||
op: 'add',
|
||||
path: '/messageSchema/schemaFields/0/children/0/children/1/description',
|
||||
value: 'Description for schema field last_name',
|
||||
},
|
||||
{
|
||||
op: 'remove',
|
||||
path: '/messageSchema/schemaFields/0/children/0/children/0/description',
|
||||
},
|
||||
{
|
||||
op: 'add',
|
||||
path: '/messageSchema/schemaFields/0/tags/0',
|
||||
value: {
|
||||
labelType: 'Manual',
|
||||
state: 'Confirmed',
|
||||
source: 'Classification',
|
||||
tagFQN: 'PersonalData.Personal',
|
||||
},
|
||||
},
|
||||
{
|
||||
op: 'add',
|
||||
path: '/messageSchema/schemaFields/0/tags/1',
|
||||
value: {
|
||||
labelType: 'Manual',
|
||||
state: 'Confirmed',
|
||||
source: 'Classification',
|
||||
tagFQN: 'PII.Sensitive',
|
||||
},
|
||||
},
|
||||
{
|
||||
op: 'add',
|
||||
path: '/description',
|
||||
value: 'Description for cypress_version_test_topic',
|
||||
},
|
||||
];
|
||||
|
||||
const DASHBOARD_DETAILS_FOR_VERSION_TEST = {
|
||||
name: 'cypress_version_test_dashboard',
|
||||
service: 'sample_superset',
|
||||
};
|
||||
|
||||
const DASHBOARD_PATCH_PAYLOAD = [
|
||||
{
|
||||
op: 'add',
|
||||
path: '/tags/0',
|
||||
value: {
|
||||
labelType: 'Manual',
|
||||
state: 'Confirmed',
|
||||
source: 'Classification',
|
||||
tagFQN: 'PersonalData.SpecialCategory',
|
||||
},
|
||||
},
|
||||
{
|
||||
op: 'add',
|
||||
path: '/description',
|
||||
value: 'Description for cypress_version_test_dashboard',
|
||||
},
|
||||
];
|
||||
|
||||
const PIPELINE_DETAILS_FOR_VERSION_TEST = {
|
||||
name: 'cypress_version_test_pipeline',
|
||||
tasks: [
|
||||
{
|
||||
name: 'cypress_task_1',
|
||||
displayName: 'cypress_task_1',
|
||||
fullyQualifiedName:
|
||||
'sample_airflow.cypress_version_test_pipeline.cypress_task_1',
|
||||
sourceUrl:
|
||||
'http://localhost:8080/taskinstance/list/?flt1_dag_id_equals=assert_table_exists',
|
||||
downstreamTasks: [],
|
||||
taskType: 'SnowflakeOperator',
|
||||
tags: [],
|
||||
},
|
||||
{
|
||||
name: 'cypress_task_2',
|
||||
displayName: 'cypress_task_2',
|
||||
fullyQualifiedName:
|
||||
'sample_airflow.cypress_version_test_pipeline.cypress_task_2',
|
||||
description: 'Description for task cypress_task_2',
|
||||
sourceUrl:
|
||||
'http://localhost:8080/taskinstance/list/?flt1_dag_id_equals=assert_table_exists',
|
||||
downstreamTasks: [],
|
||||
taskType: 'HiveOperator',
|
||||
tags: [],
|
||||
},
|
||||
{
|
||||
name: 'cypress_task_3',
|
||||
displayName: 'cypress_task_3',
|
||||
fullyQualifiedName:
|
||||
'sample_airflow.cypress_version_test_pipeline.cypress_task_3',
|
||||
sourceUrl:
|
||||
'http://localhost:8080/taskinstance/list/?flt1_dag_id_equals=assert_table_exists',
|
||||
downstreamTasks: [],
|
||||
taskType: 'HiveOperator',
|
||||
tags: [],
|
||||
},
|
||||
],
|
||||
service: 'sample_airflow',
|
||||
};
|
||||
|
||||
const PIPELINE_PATCH_PAYLOAD = [
|
||||
{
|
||||
op: 'add',
|
||||
path: '/tags/0',
|
||||
value: {
|
||||
labelType: 'Manual',
|
||||
state: 'Confirmed',
|
||||
source: 'Classification',
|
||||
tagFQN: 'PersonalData.SpecialCategory',
|
||||
},
|
||||
},
|
||||
{
|
||||
op: 'add',
|
||||
path: '/tasks/2/description',
|
||||
value: 'Description for task cypress_task_3',
|
||||
},
|
||||
{
|
||||
op: 'remove',
|
||||
path: '/tasks/1/description',
|
||||
},
|
||||
{
|
||||
op: 'add',
|
||||
path: '/tasks/0/tags/0',
|
||||
value: {
|
||||
labelType: 'Manual',
|
||||
state: 'Confirmed',
|
||||
source: 'Classification',
|
||||
tagFQN: 'PersonalData.Personal',
|
||||
},
|
||||
},
|
||||
{
|
||||
op: 'add',
|
||||
path: '/tasks/0/tags/1',
|
||||
value: {
|
||||
labelType: 'Manual',
|
||||
state: 'Confirmed',
|
||||
source: 'Classification',
|
||||
tagFQN: 'PII.Sensitive',
|
||||
},
|
||||
},
|
||||
{
|
||||
op: 'add',
|
||||
path: '/description',
|
||||
value: 'Description for cypress_version_test_pipeline',
|
||||
},
|
||||
];
|
||||
|
||||
const ML_MODEL_DETAILS_FOR_VERSION_TEST = {
|
||||
name: 'cypress_version_test_ml_model',
|
||||
algorithm: 'Neural Network',
|
||||
mlFeatures: [
|
||||
{
|
||||
name: 'feature_1',
|
||||
dataType: 'numerical',
|
||||
fullyQualifiedName: 'mlflow_svc.cypress_version_test_ml_model.feature_1',
|
||||
featureSources: [],
|
||||
tags: [],
|
||||
},
|
||||
{
|
||||
name: 'feature_2',
|
||||
dataType: 'numerical',
|
||||
description: 'Description for mlFeature feature_2',
|
||||
fullyQualifiedName: 'mlflow_svc.cypress_version_test_ml_model.feature_2',
|
||||
featureSources: [],
|
||||
},
|
||||
{
|
||||
name: 'feature_3',
|
||||
dataType: 'numerical',
|
||||
fullyQualifiedName: 'mlflow_svc.cypress_version_test_ml_model.feature_3',
|
||||
featureSources: [],
|
||||
},
|
||||
],
|
||||
tags: [],
|
||||
service: 'mlflow_svc',
|
||||
};
|
||||
|
||||
const ML_MODEL_PATCH_PAYLOAD = [
|
||||
{
|
||||
op: 'add',
|
||||
path: '/tags/0',
|
||||
value: {
|
||||
labelType: 'Manual',
|
||||
state: 'Confirmed',
|
||||
source: 'Classification',
|
||||
tagFQN: 'PersonalData.SpecialCategory',
|
||||
},
|
||||
},
|
||||
{
|
||||
op: 'add',
|
||||
path: '/mlFeatures/2/description',
|
||||
value: 'Description for mlFeature feature_3',
|
||||
},
|
||||
{
|
||||
op: 'remove',
|
||||
path: '/mlFeatures/1/description',
|
||||
},
|
||||
{
|
||||
op: 'add',
|
||||
path: '/mlFeatures/0/tags/0',
|
||||
value: {
|
||||
labelType: 'Manual',
|
||||
state: 'Confirmed',
|
||||
source: 'Classification',
|
||||
tagFQN: 'PersonalData.Personal',
|
||||
},
|
||||
},
|
||||
{
|
||||
op: 'add',
|
||||
path: '/mlFeatures/0/tags/1',
|
||||
value: {
|
||||
labelType: 'Manual',
|
||||
state: 'Confirmed',
|
||||
source: 'Classification',
|
||||
tagFQN: 'PII.Sensitive',
|
||||
},
|
||||
},
|
||||
{
|
||||
op: 'add',
|
||||
path: '/description',
|
||||
value: 'Description for cypress_version_test_ml_model',
|
||||
},
|
||||
];
|
||||
|
||||
const CONTAINER_DETAILS_FOR_VERSION_TEST = {
|
||||
name: 'cypress_version_test_container',
|
||||
service: 's3_storage_sample',
|
||||
dataModel: {
|
||||
isPartitioned: false,
|
||||
columns: [
|
||||
{
|
||||
name: 'column_1',
|
||||
dataType: 'NUMERIC',
|
||||
dataTypeDisplay: 'numeric',
|
||||
fullyQualifiedName:
|
||||
's3_storage_sample.departments.finance.cypress_version_test_container.column_1',
|
||||
tags: [],
|
||||
ordinalPosition: 1,
|
||||
},
|
||||
{
|
||||
name: 'column_2',
|
||||
dataType: 'BOOLEAN',
|
||||
dataTypeDisplay: 'boolean',
|
||||
description: 'Description for column column_2',
|
||||
fullyQualifiedName:
|
||||
's3_storage_sample.departments.finance.cypress_version_test_container.column_2',
|
||||
tags: [],
|
||||
ordinalPosition: 2,
|
||||
},
|
||||
{
|
||||
name: 'column_3',
|
||||
dataType: 'BOOLEAN',
|
||||
dataTypeDisplay: 'boolean',
|
||||
fullyQualifiedName:
|
||||
's3_storage_sample.departments.finance.cypress_version_test_container.column_3',
|
||||
tags: [],
|
||||
ordinalPosition: 3,
|
||||
},
|
||||
{
|
||||
name: 'column_4',
|
||||
dataType: 'NUMERIC',
|
||||
dataTypeDisplay: 'numeric',
|
||||
fullyQualifiedName:
|
||||
's3_storage_sample.departments.finance.cypress_version_test_container.column_4',
|
||||
tags: [],
|
||||
ordinalPosition: 4,
|
||||
},
|
||||
],
|
||||
},
|
||||
tags: [],
|
||||
};
|
||||
|
||||
const CONTAINER_PATCH_PAYLOAD = [
|
||||
{
|
||||
op: 'add',
|
||||
path: '/tags/0',
|
||||
value: {
|
||||
labelType: 'Manual',
|
||||
state: 'Confirmed',
|
||||
source: 'Classification',
|
||||
tagFQN: 'PersonalData.SpecialCategory',
|
||||
},
|
||||
},
|
||||
{
|
||||
op: 'add',
|
||||
path: '/dataModel/columns/2/description',
|
||||
value: 'Description for column column_3',
|
||||
},
|
||||
{
|
||||
op: 'remove',
|
||||
path: '/dataModel/columns/1/description',
|
||||
},
|
||||
{
|
||||
op: 'add',
|
||||
path: '/dataModel/columns/0/tags/0',
|
||||
value: {
|
||||
labelType: 'Manual',
|
||||
state: 'Confirmed',
|
||||
source: 'Classification',
|
||||
tagFQN: 'PersonalData.Personal',
|
||||
},
|
||||
},
|
||||
{
|
||||
op: 'add',
|
||||
path: '/dataModel/columns/0/tags/1',
|
||||
value: {
|
||||
labelType: 'Manual',
|
||||
state: 'Confirmed',
|
||||
source: 'Classification',
|
||||
tagFQN: 'PII.Sensitive',
|
||||
},
|
||||
},
|
||||
{
|
||||
op: 'add',
|
||||
path: '/description',
|
||||
value: 'Description for cypress_version_test_container',
|
||||
},
|
||||
];
|
||||
|
||||
export const ENTITY_DETAILS_FOR_VERSION_TEST = {
|
||||
Table: {
|
||||
name: 'cypress_version_test_table',
|
||||
term: 'cypress_version_test_table',
|
||||
serviceName: 'sample_data',
|
||||
entity: 'tables',
|
||||
entityCreationDetails: TABLE_DETAILS_FOR_VERSION_TEST,
|
||||
entityPatchPayload: TABLE_PATCH_PAYLOAD,
|
||||
isChildrenExist: true,
|
||||
childSelector: 'data-row-key',
|
||||
entityAddedDescription: 'Description for cypress_version_test_table',
|
||||
updatedTagEntityChildName: 'user_id',
|
||||
entityChildRemovedDescription: 'First name of the staff member.',
|
||||
entityChildAddedDescription: 'Last name of the staff member.',
|
||||
},
|
||||
Topic: {
|
||||
name: 'cypress_version_test_topic',
|
||||
term: 'cypress_version_test_topic',
|
||||
serviceName: 'sample_kafka',
|
||||
entity: 'topics',
|
||||
entityCreationDetails: TOPIC_DETAILS_FOR_VERSION_TEST,
|
||||
entityPatchPayload: TOPIC_PATCH_PAYLOAD,
|
||||
isChildrenExist: true,
|
||||
childSelector: 'data-row-key',
|
||||
entityAddedDescription: 'Description for cypress_version_test_topic',
|
||||
updatedTagEntityChildName: 'default',
|
||||
entityChildRemovedDescription: 'Description for schema field first_name',
|
||||
entityChildAddedDescription: 'Description for schema field last_name',
|
||||
},
|
||||
// TODO - Remove the comment after this issue is resolved https://github.com/open-metadata/OpenMetadata/issues/12924
|
||||
// Dashboard: {
|
||||
// name: 'cypress_version_test_dashboard',
|
||||
// term: 'cypress_version_test_dashboard',
|
||||
// serviceName: 'sample_superset',
|
||||
// entity: 'dashboards',
|
||||
// entityCreationDetails: DASHBOARD_DETAILS_FOR_VERSION_TEST,
|
||||
// entityPatchPayload: DASHBOARD_PATCH_PAYLOAD,
|
||||
// isChildrenExist: false,
|
||||
// entityAddedDescription: 'Description for cypress_version_test_dashboard',
|
||||
// },
|
||||
Pipeline: {
|
||||
name: 'cypress_version_test_pipeline',
|
||||
term: 'cypress_version_test_pipeline',
|
||||
serviceName: 'sample_airflow',
|
||||
entity: 'pipelines',
|
||||
entityCreationDetails: PIPELINE_DETAILS_FOR_VERSION_TEST,
|
||||
entityPatchPayload: PIPELINE_PATCH_PAYLOAD,
|
||||
isChildrenExist: true,
|
||||
childSelector: 'data-row-key',
|
||||
entityAddedDescription: 'Description for cypress_version_test_pipeline',
|
||||
updatedTagEntityChildName: 'cypress_task_1',
|
||||
entityChildRemovedDescription: 'Description for task cypress_task_2',
|
||||
entityChildAddedDescription: 'Description for task cypress_task_3',
|
||||
},
|
||||
'ML Model': {
|
||||
name: 'cypress_version_test_ml_model',
|
||||
term: 'cypress_version_test_ml_model',
|
||||
serviceName: 'mlflow_svc',
|
||||
entity: 'mlmodels',
|
||||
entityCreationDetails: ML_MODEL_DETAILS_FOR_VERSION_TEST,
|
||||
entityPatchPayload: ML_MODEL_PATCH_PAYLOAD,
|
||||
isChildrenExist: true,
|
||||
childSelector: 'data-testid',
|
||||
entityAddedDescription: 'Description for cypress_version_test_ml_model',
|
||||
updatedTagEntityChildName: 'feature-card-feature_1',
|
||||
entityChildRemovedDescription: 'Description for mlFeature feature_2',
|
||||
entityChildAddedDescription: 'Description for mlFeature feature_3',
|
||||
},
|
||||
Container: {
|
||||
name: 'cypress_version_test_container',
|
||||
term: 'cypress_version_test_container',
|
||||
serviceName: 's3_storage_sample',
|
||||
entity: 'containers',
|
||||
entityCreationDetails: CONTAINER_DETAILS_FOR_VERSION_TEST,
|
||||
entityPatchPayload: CONTAINER_PATCH_PAYLOAD,
|
||||
isChildrenExist: true,
|
||||
childSelector: 'data-row-key',
|
||||
entityAddedDescription: 'Description for cypress_version_test_container',
|
||||
updatedTagEntityChildName: 'column_1',
|
||||
entityChildRemovedDescription: 'Description for column column_2',
|
||||
entityChildAddedDescription: 'Description for column column_3',
|
||||
},
|
||||
};
|
||||
|
||||
export const DATA_MODEL_DETAILS_FOR_VERSION_TEST = {
|
||||
name: 'cypress_version_test_data_model',
|
||||
service: 'sample_looker',
|
||||
dataModelType: 'LookMlExplore',
|
||||
columns: [
|
||||
{
|
||||
name: 'column_1',
|
||||
dataType: 'VARCHAR',
|
||||
dataLength: 256,
|
||||
dataTypeDisplay: 'varchar',
|
||||
fullyQualifiedName:
|
||||
'sample_looker.model.cypress_version_test_data_model.column_1',
|
||||
tags: [],
|
||||
ordinalPosition: 1,
|
||||
},
|
||||
{
|
||||
name: 'column_2',
|
||||
dataType: 'NUMERIC',
|
||||
dataTypeDisplay: 'numeric',
|
||||
description: 'Description for column column_2',
|
||||
fullyQualifiedName:
|
||||
'sample_looker.model.cypress_version_test_data_model.column_2',
|
||||
tags: [],
|
||||
ordinalPosition: 2,
|
||||
},
|
||||
{
|
||||
name: 'column_3',
|
||||
dataType: 'NUMERIC',
|
||||
dataTypeDisplay: 'numeric',
|
||||
fullyQualifiedName:
|
||||
'sample_looker.model.cypress_version_test_data_model.column_3',
|
||||
tags: [],
|
||||
ordinalPosition: 3,
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
export const DATA_MODEL_PATCH_PAYLOAD = [
|
||||
{
|
||||
op: 'add',
|
||||
path: '/tags/0',
|
||||
value: {
|
||||
labelType: 'Manual',
|
||||
state: 'Confirmed',
|
||||
source: 'Classification',
|
||||
tagFQN: 'PersonalData.SpecialCategory',
|
||||
},
|
||||
},
|
||||
{
|
||||
op: 'add',
|
||||
path: '/columns/2/description',
|
||||
value: 'Description for column column_3',
|
||||
},
|
||||
{
|
||||
op: 'remove',
|
||||
path: '/columns/1/description',
|
||||
},
|
||||
{
|
||||
op: 'add',
|
||||
path: '/columns/0/tags/0',
|
||||
value: {
|
||||
labelType: 'Manual',
|
||||
state: 'Confirmed',
|
||||
source: 'Classification',
|
||||
tagFQN: 'PersonalData.Personal',
|
||||
},
|
||||
},
|
||||
{
|
||||
op: 'add',
|
||||
path: '/columns/0/tags/1',
|
||||
value: {
|
||||
labelType: 'Manual',
|
||||
state: 'Confirmed',
|
||||
source: 'Classification',
|
||||
tagFQN: 'PII.Sensitive',
|
||||
},
|
||||
},
|
||||
{
|
||||
op: 'add',
|
||||
path: '/description',
|
||||
value: 'Description for cypress_version_test_data_model',
|
||||
},
|
||||
];
|
||||
|
||||
export const DATA_MODEL_DETAILS = {
|
||||
name: 'cypress_version_test_data_model',
|
||||
entity: 'containers',
|
||||
entityAddedDescription: 'Description for cypress_version_test_data_model',
|
||||
updatedTagEntityChildName: 'column_1',
|
||||
entityChildRemovedDescription: 'Description for column column_2',
|
||||
entityChildAddedDescription: 'Description for column column_3',
|
||||
};
|
||||
@ -13,8 +13,12 @@
|
||||
// / <reference types="Cypress" />
|
||||
|
||||
import {
|
||||
addOwner,
|
||||
addTier,
|
||||
descriptionBox,
|
||||
interceptURL,
|
||||
removeOwner,
|
||||
removeTier,
|
||||
verifyResponseStatusCode,
|
||||
visitEntityDetailsPage,
|
||||
} from '../../common/common';
|
||||
@ -44,58 +48,15 @@ const glossaryTerm = 'GlossaryTermOwnerTest';
|
||||
const OWNER = 'Amber Green';
|
||||
const TIER = 'Tier1';
|
||||
|
||||
const addRemoveOwner = (isGlossaryPage) => {
|
||||
cy.get('[data-testid="edit-owner"]').click();
|
||||
|
||||
cy.get('.ant-tabs [id*=tab-users]').click();
|
||||
verifyResponseStatusCode('@getUsers', 200);
|
||||
|
||||
interceptURL(
|
||||
'GET',
|
||||
`api/v1/search/query?q=*${encodeURI(OWNER)}*`,
|
||||
'searchOwner'
|
||||
);
|
||||
|
||||
cy.get('[data-testid="owner-select-users-search-bar"]').type(OWNER);
|
||||
|
||||
verifyResponseStatusCode('@searchOwner', 200);
|
||||
|
||||
cy.get(`.ant-popover [title="${OWNER}"]`).click();
|
||||
verifyResponseStatusCode('@patchOwner', 200);
|
||||
if (isGlossaryPage) {
|
||||
cy.get('[data-testid="glossary-owner-name"]').should('contain', OWNER);
|
||||
} else {
|
||||
cy.get('[data-testid="owner-link"]').should('contain', OWNER);
|
||||
}
|
||||
cy.get('[data-testid="edit-owner"]').click();
|
||||
|
||||
cy.get('[data-testid="remove-owner"]').click();
|
||||
verifyResponseStatusCode('@patchOwner', 200);
|
||||
if (isGlossaryPage) {
|
||||
cy.get('[data-testid="glossary-owner-name"] > [data-testid="Add"]').should(
|
||||
'be.visible'
|
||||
);
|
||||
} else {
|
||||
cy.get('[data-testid="owner-link"]').should('contain', 'No Owner');
|
||||
}
|
||||
const addRemoveOwner = (ownerName, entity, isGlossaryPage) => {
|
||||
addOwner(ownerName, entity, isGlossaryPage);
|
||||
removeOwner(entity, isGlossaryPage);
|
||||
};
|
||||
|
||||
const addRemoveTier = () => {
|
||||
interceptURL('GET', '/api/v1/tags?parent=Tier&limit=10', 'fetchTier');
|
||||
cy.get('[data-testid="edit-tier"]').click();
|
||||
verifyResponseStatusCode('@fetchTier', 200);
|
||||
cy.get('[data-testid="radio-btn-Tier1"]').click({ waitForAnimations: true });
|
||||
verifyResponseStatusCode('@patchOwner', 200);
|
||||
cy.get('[data-testid="radio-btn-Tier1"]').should('be.checked');
|
||||
const addRemoveTier = (tier, entity) => {
|
||||
addTier(tier, entity);
|
||||
|
||||
cy.clickOutside();
|
||||
cy.get('[data-testid="Tier"]').should('contain', TIER);
|
||||
|
||||
cy.get('[data-testid="edit-tier"]').click();
|
||||
cy.get('[data-testid="clear-tier"]').should('be.visible').click();
|
||||
|
||||
verifyResponseStatusCode('@patchOwner', 200);
|
||||
cy.get('[data-testid="Tier"]').should('contain', 'No Tier');
|
||||
removeTier(entity);
|
||||
};
|
||||
|
||||
describe('Add and Remove Owner', () => {
|
||||
@ -113,8 +74,6 @@ describe('Add and Remove Owner', () => {
|
||||
|
||||
Object.entries(ENTITIES).map(([key, value]) => {
|
||||
it(`${key} details page`, () => {
|
||||
interceptURL('PATCH', `/api/v1/${value.entity}/*`, 'patchOwner');
|
||||
|
||||
visitEntityDetailsPage(
|
||||
value.term,
|
||||
value.serviceName,
|
||||
@ -125,7 +84,7 @@ describe('Add and Remove Owner', () => {
|
||||
verifyResponseStatusCode('@entityPermission', 200);
|
||||
verifyResponseStatusCode('@activityFeed', 200);
|
||||
|
||||
addRemoveOwner();
|
||||
addRemoveOwner(OWNER, value.entity);
|
||||
});
|
||||
});
|
||||
|
||||
@ -144,7 +103,7 @@ describe('Add and Remove Owner', () => {
|
||||
verifyResponseStatusCode('@entityPermission', 200);
|
||||
verifyResponseStatusCode('@schemaDetails', 200);
|
||||
verifyResponseStatusCode('@activityFeed', 200);
|
||||
addRemoveOwner();
|
||||
addRemoveOwner(OWNER, 'databaseSchemas');
|
||||
});
|
||||
|
||||
it('database details page', () => {
|
||||
@ -162,7 +121,7 @@ describe('Add and Remove Owner', () => {
|
||||
verifyResponseStatusCode('@entityPermission', 200);
|
||||
verifyResponseStatusCode('@databaseDetails', 200);
|
||||
verifyResponseStatusCode('@activityFeed', 200);
|
||||
addRemoveOwner();
|
||||
addRemoveOwner(OWNER, 'databases');
|
||||
});
|
||||
|
||||
it('service details page', () => {
|
||||
@ -192,7 +151,7 @@ describe('Add and Remove Owner', () => {
|
||||
verifyResponseStatusCode('@serviceDetails', 200);
|
||||
verifyResponseStatusCode('@databases', 200);
|
||||
|
||||
addRemoveOwner();
|
||||
addRemoveOwner(OWNER, 'databaseServices');
|
||||
});
|
||||
|
||||
it('Test suite details page', () => {
|
||||
@ -219,7 +178,7 @@ describe('Add and Remove Owner', () => {
|
||||
verifyResponseStatusCode('@entityPermission', 200);
|
||||
verifyResponseStatusCode('@testSuiteDetails', 200);
|
||||
verifyResponseStatusCode('@testCases', 200);
|
||||
addRemoveOwner();
|
||||
addRemoveOwner(OWNER, 'testSuites');
|
||||
});
|
||||
|
||||
it('Teams details page', () => {
|
||||
@ -235,7 +194,7 @@ describe('Add and Remove Owner', () => {
|
||||
verifyResponseStatusCode('@getOrganization', 200);
|
||||
verifyResponseStatusCode('@teamPermission', 200);
|
||||
|
||||
addRemoveOwner();
|
||||
addRemoveOwner(OWNER, 'teams');
|
||||
});
|
||||
|
||||
it('Glossary details page', () => {
|
||||
@ -259,7 +218,7 @@ describe('Add and Remove Owner', () => {
|
||||
verifyResponseStatusCode('@getGlossaries', 200);
|
||||
verifyResponseStatusCode('@glossaryPermission', 200);
|
||||
|
||||
addRemoveOwner(true);
|
||||
addRemoveOwner(OWNER, 'glossaries', true);
|
||||
});
|
||||
|
||||
it('GlossaryTerm details page', () => {
|
||||
@ -307,7 +266,7 @@ describe('Add and Remove Owner', () => {
|
||||
verifyResponseStatusCode('@glossaryTermPermission', 200);
|
||||
verifyResponseStatusCode('@getGlossaryTerms', 200);
|
||||
|
||||
addRemoveOwner(true);
|
||||
addRemoveOwner(OWNER, 'glossaryTerms', true);
|
||||
});
|
||||
|
||||
it('Delete glossary and glossaryTerm', () => {
|
||||
@ -365,8 +324,6 @@ describe('Add and Remove Tier', () => {
|
||||
|
||||
Object.entries(ENTITIES).map(([key, value]) => {
|
||||
it(`${key} details page`, () => {
|
||||
interceptURL('PATCH', `/api/v1/${value.entity}/*`, 'patchOwner');
|
||||
|
||||
visitEntityDetailsPage(
|
||||
value.term,
|
||||
value.serviceName,
|
||||
@ -377,12 +334,11 @@ describe('Add and Remove Tier', () => {
|
||||
verifyResponseStatusCode('@entityPermission', 200);
|
||||
verifyResponseStatusCode('@activityFeed', 200);
|
||||
|
||||
addRemoveTier();
|
||||
addRemoveTier(TIER, value.entity);
|
||||
});
|
||||
});
|
||||
|
||||
it('database details page', () => {
|
||||
interceptURL('PATCH', '/api/v1/databases/*', 'patchOwner');
|
||||
interceptURL('GET', '/api/v1/databases/name/*', 'databaseDetails');
|
||||
const value = ENTITIES.table;
|
||||
visitEntityDetailsPage(value.term, value.serviceName, value.entity);
|
||||
@ -397,6 +353,6 @@ describe('Add and Remove Tier', () => {
|
||||
verifyResponseStatusCode('@databaseDetails', 200);
|
||||
verifyResponseStatusCode('@activityFeed', 200);
|
||||
|
||||
addRemoveTier();
|
||||
addRemoveTier(TIER, 'databases');
|
||||
});
|
||||
});
|
||||
|
||||
@ -0,0 +1,279 @@
|
||||
/*
|
||||
* Copyright 2023 Collate.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
// / <reference types="Cypress" />
|
||||
|
||||
import {
|
||||
addOwner,
|
||||
addTier,
|
||||
interceptURL,
|
||||
removeOwner,
|
||||
removeTier,
|
||||
toastNotification,
|
||||
verifyResponseStatusCode,
|
||||
visitDataModelPage,
|
||||
} from '../../common/common';
|
||||
import { visitDataModelVersionPage } from '../../common/VersionUtils';
|
||||
import { DELETE_TERM } from '../../constants/constants';
|
||||
import {
|
||||
DATA_MODEL_DETAILS,
|
||||
DATA_MODEL_DETAILS_FOR_VERSION_TEST,
|
||||
DATA_MODEL_PATCH_PAYLOAD,
|
||||
OWNER,
|
||||
TIER,
|
||||
} from '../../constants/Version.constants';
|
||||
|
||||
describe('Data model version page should work properly', () => {
|
||||
const dataModelName = DATA_MODEL_DETAILS.name;
|
||||
let dataModelId;
|
||||
let dataModelFQN;
|
||||
|
||||
beforeEach(() => {
|
||||
cy.login();
|
||||
});
|
||||
|
||||
it('Prerequisite for data model version page tests', () => {
|
||||
const token = localStorage.getItem('oidcIdToken');
|
||||
|
||||
cy.request({
|
||||
method: 'PUT',
|
||||
url: `/api/v1/dashboard/datamodels`,
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
body: DATA_MODEL_DETAILS_FOR_VERSION_TEST,
|
||||
}).then((response) => {
|
||||
expect(response.status).to.eq(201);
|
||||
|
||||
dataModelId = response.body.id;
|
||||
dataModelFQN = response.body.fullyQualifiedName;
|
||||
|
||||
cy.request({
|
||||
method: 'PATCH',
|
||||
url: `/api/v1/dashboard/datamodels/${dataModelId}`,
|
||||
headers: {
|
||||
Authorization: `Bearer ${token}`,
|
||||
'Content-Type': 'application/json-patch+json',
|
||||
},
|
||||
body: DATA_MODEL_PATCH_PAYLOAD,
|
||||
}).then((response) => {
|
||||
expect(response.status).to.eq(200);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('Data model version page should show description and tag changes properly', () => {
|
||||
visitDataModelVersionPage(dataModelFQN, dataModelId, dataModelName, '0.2');
|
||||
|
||||
cy.get(
|
||||
`[data-testid="diff-added-${DATA_MODEL_DETAILS.entityAddedDescription}"]`
|
||||
)
|
||||
.scrollIntoView()
|
||||
.should('be.visible');
|
||||
|
||||
cy.get(
|
||||
`[data-testid="entity-right-panel"] .diff-added [data-testid="tag-PersonalData.SpecialCategory"]`
|
||||
)
|
||||
.scrollIntoView()
|
||||
.should('be.visible');
|
||||
|
||||
cy.get(
|
||||
`[data-row-key="${DATA_MODEL_DETAILS.updatedTagEntityChildName}"] .diff-added [data-testid="tag-PersonalData.Personal"]`
|
||||
)
|
||||
.scrollIntoView()
|
||||
.should('be.visible');
|
||||
|
||||
cy.get(
|
||||
`[data-row-key="${DATA_MODEL_DETAILS.updatedTagEntityChildName}"] .diff-added [data-testid="tag-PII.Sensitive"]`
|
||||
)
|
||||
.scrollIntoView()
|
||||
.should('be.visible');
|
||||
|
||||
cy.get(
|
||||
`[data-testid="diff-removed-${DATA_MODEL_DETAILS.entityChildRemovedDescription}"]`
|
||||
)
|
||||
.scrollIntoView()
|
||||
.should('be.visible');
|
||||
|
||||
cy.get(
|
||||
`[data-testid="diff-added-${DATA_MODEL_DETAILS.entityChildAddedDescription}"]`
|
||||
)
|
||||
.scrollIntoView()
|
||||
.should('be.visible');
|
||||
});
|
||||
|
||||
it(`Data model version page should show removed tags changes properly`, () => {
|
||||
visitDataModelPage(dataModelFQN, dataModelName);
|
||||
|
||||
cy.get(
|
||||
'[data-testid="entity-right-panel"] [data-testid="edit-button"]'
|
||||
).click();
|
||||
|
||||
cy.get(
|
||||
'[data-testid="selected-tag-PersonalData.SpecialCategory"] [data-testid="remove-tags"]'
|
||||
).click();
|
||||
|
||||
interceptURL(
|
||||
'PATCH',
|
||||
`/api/v1/dashboard/datamodels/${dataModelId}`,
|
||||
`patchDataModel`
|
||||
);
|
||||
|
||||
cy.get('[data-testid="saveAssociatedTag"]').click();
|
||||
|
||||
verifyResponseStatusCode(`@patchDataModel`, 200);
|
||||
|
||||
cy.get('[data-testid="version-button"]').contains('0.3').click();
|
||||
|
||||
cy.get(
|
||||
`[data-testid="entity-right-panel"] .diff-removed [data-testid="tag-PersonalData.SpecialCategory"]`
|
||||
)
|
||||
.scrollIntoView()
|
||||
.should('be.visible');
|
||||
});
|
||||
|
||||
it(`Data model version page should show owner changes properly`, () => {
|
||||
visitDataModelPage(dataModelFQN, dataModelName);
|
||||
|
||||
cy.get('[data-testid="version-button"]').as('versionButton');
|
||||
|
||||
cy.get('@versionButton').contains('0.3');
|
||||
|
||||
addOwner(OWNER, 'dashboard/datamodels');
|
||||
|
||||
interceptURL(
|
||||
'GET',
|
||||
`/api/v1/dashboard/datamodels/name/${dataModelFQN}*`,
|
||||
`getDataModelDetails`
|
||||
);
|
||||
interceptURL(
|
||||
'GET',
|
||||
`/api/v1/dashboard/datamodels/${dataModelId}/versions`,
|
||||
'getVersionsList'
|
||||
);
|
||||
interceptURL(
|
||||
'GET',
|
||||
`/api/v1/dashboard/datamodels/${dataModelId}/versions/0.4`,
|
||||
'getSelectedVersionDetails'
|
||||
);
|
||||
|
||||
cy.get('@versionButton').contains('0.4').click();
|
||||
|
||||
verifyResponseStatusCode(`@getDataModelDetails`, 200);
|
||||
verifyResponseStatusCode('@getVersionsList', 200);
|
||||
verifyResponseStatusCode('@getSelectedVersionDetails', 200);
|
||||
|
||||
cy.get(`[data-testid="diff-added-${OWNER}"]`)
|
||||
.scrollIntoView()
|
||||
.should('be.visible');
|
||||
|
||||
cy.get('@versionButton').contains('0.4').click();
|
||||
|
||||
removeOwner('dashboard/datamodels');
|
||||
|
||||
interceptURL(
|
||||
'GET',
|
||||
`/api/v1/dashboard/datamodels/${dataModelId}/versions/0.5`,
|
||||
'getSelectedVersionDetails'
|
||||
);
|
||||
|
||||
cy.get('@versionButton').contains('0.5').click();
|
||||
|
||||
verifyResponseStatusCode(`@getDataModelDetails`, 200);
|
||||
verifyResponseStatusCode('@getVersionsList', 200);
|
||||
verifyResponseStatusCode('@getSelectedVersionDetails', 200);
|
||||
|
||||
cy.get(`[data-testid="diff-removed-${OWNER}"]`)
|
||||
.scrollIntoView()
|
||||
.should('be.visible');
|
||||
});
|
||||
|
||||
it(`Data model version page should show tier changes properly`, () => {
|
||||
visitDataModelPage(dataModelFQN, dataModelName);
|
||||
|
||||
cy.get('[data-testid="version-button"]').as('versionButton');
|
||||
|
||||
cy.get('@versionButton').contains('0.5');
|
||||
|
||||
addTier(TIER, 'dashboard/datamodels');
|
||||
|
||||
interceptURL(
|
||||
'GET',
|
||||
`/api/v1/dashboard/datamodels/name/${dataModelFQN}*`,
|
||||
`getDataModelDetails`
|
||||
);
|
||||
interceptURL(
|
||||
'GET',
|
||||
`/api/v1/dashboard/datamodels/${dataModelId}/versions`,
|
||||
'getVersionsList'
|
||||
);
|
||||
interceptURL(
|
||||
'GET',
|
||||
`/api/v1/dashboard/datamodels/${dataModelId}/versions/0.6`,
|
||||
'getSelectedVersionDetails'
|
||||
);
|
||||
|
||||
cy.get('@versionButton').contains('0.6').click();
|
||||
|
||||
verifyResponseStatusCode(`@getDataModelDetails`, 200);
|
||||
verifyResponseStatusCode('@getVersionsList', 200);
|
||||
verifyResponseStatusCode('@getSelectedVersionDetails', 200);
|
||||
|
||||
cy.get(`[data-testid="diff-added-${TIER}"]`)
|
||||
.scrollIntoView()
|
||||
.should('be.visible');
|
||||
|
||||
cy.get('@versionButton').contains('0.6').click();
|
||||
|
||||
removeTier('dashboard/datamodels');
|
||||
|
||||
interceptURL(
|
||||
'GET',
|
||||
`/api/v1/dashboard/datamodels/${dataModelId}/versions/0.7`,
|
||||
'getSelectedVersionDetails'
|
||||
);
|
||||
|
||||
cy.get('@versionButton').contains('0.7').click();
|
||||
|
||||
verifyResponseStatusCode(`@getDataModelDetails`, 200);
|
||||
verifyResponseStatusCode('@getVersionsList', 200);
|
||||
verifyResponseStatusCode('@getSelectedVersionDetails', 200);
|
||||
|
||||
cy.get(`[data-testid="diff-removed-${TIER}"]`)
|
||||
.scrollIntoView()
|
||||
.should('be.visible');
|
||||
});
|
||||
|
||||
it(`Cleanup for data model version page test`, () => {
|
||||
visitDataModelPage(dataModelFQN, dataModelName);
|
||||
|
||||
cy.get('[data-testid="manage-button"]').click();
|
||||
|
||||
cy.get('[data-testid="delete-button-title"]').click();
|
||||
|
||||
cy.get('.ant-modal-header').should('contain', `Delete ${dataModelName}`);
|
||||
|
||||
cy.get(`[data-testid="hard-delete-option"]`).click();
|
||||
|
||||
cy.get('[data-testid="confirm-button"]').should('be.disabled');
|
||||
cy.get('[data-testid="confirmation-text-input"]').type(DELETE_TERM);
|
||||
|
||||
interceptURL(
|
||||
'DELETE',
|
||||
`api/v1/dashboard/datamodels/*?hardDelete=true&recursive=false`,
|
||||
`hardDeleteTable`
|
||||
);
|
||||
cy.get('[data-testid="confirm-button"]').should('not.be.disabled');
|
||||
cy.get('[data-testid="confirm-button"]').click();
|
||||
verifyResponseStatusCode(`@hardDeleteTable`, 200);
|
||||
|
||||
toastNotification(`Dashboard Data Model deleted successfully!`, false);
|
||||
});
|
||||
});
|
||||
@ -0,0 +1,289 @@
|
||||
/*
|
||||
* Copyright 2023 Collate.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
// / <reference types="Cypress" />
|
||||
|
||||
import {
|
||||
addOwner,
|
||||
addTier,
|
||||
deleteEntity,
|
||||
interceptURL,
|
||||
removeOwner,
|
||||
removeTier,
|
||||
verifyResponseStatusCode,
|
||||
visitEntityDetailsPage,
|
||||
} from '../../common/common';
|
||||
import { visitEntityDetailsVersionPage } from '../../common/VersionUtils';
|
||||
import {
|
||||
ENTITY_DETAILS_FOR_VERSION_TEST,
|
||||
OWNER,
|
||||
TIER,
|
||||
} from '../../constants/Version.constants';
|
||||
|
||||
Object.entries(ENTITY_DETAILS_FOR_VERSION_TEST).map(
|
||||
([entityType, entityDetails]) => {
|
||||
describe(`${entityType} version page should work properly`, () => {
|
||||
const successMessageEntityName =
|
||||
entityType === 'ML Model' ? 'Mlmodel' : entityType;
|
||||
let entityId;
|
||||
let entityFQN;
|
||||
|
||||
beforeEach(() => {
|
||||
cy.login();
|
||||
});
|
||||
|
||||
it(`Prerequisite for ${entityType} version page test`, () => {
|
||||
const token = localStorage.getItem('oidcIdToken');
|
||||
|
||||
cy.request({
|
||||
method: 'PUT',
|
||||
url: `/api/v1/${entityDetails.entity}`,
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
body: entityDetails.entityCreationDetails,
|
||||
}).then((response) => {
|
||||
expect(response.status).to.eq(201);
|
||||
|
||||
entityId = response.body.id;
|
||||
entityFQN = response.body.fullyQualifiedName;
|
||||
|
||||
cy.request({
|
||||
method: 'PATCH',
|
||||
url: `/api/v1/${entityDetails.entity}/${entityId}`,
|
||||
headers: {
|
||||
Authorization: `Bearer ${token}`,
|
||||
'Content-Type': 'application/json-patch+json',
|
||||
},
|
||||
body: entityDetails.entityPatchPayload,
|
||||
}).then((response) => {
|
||||
expect(response.status).to.eq(200);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it(`${entityType} version page should show description and tag changes properly`, () => {
|
||||
visitEntityDetailsVersionPage(
|
||||
entityDetails,
|
||||
entityId,
|
||||
entityFQN,
|
||||
'0.2'
|
||||
);
|
||||
cy.get(
|
||||
`[data-testid="diff-added-${entityDetails.entityAddedDescription}"]`
|
||||
)
|
||||
.scrollIntoView()
|
||||
.should('be.visible');
|
||||
|
||||
cy.get(
|
||||
`[data-testid="entity-right-panel"] .diff-added [data-testid="tag-PersonalData.SpecialCategory"]`
|
||||
)
|
||||
.scrollIntoView()
|
||||
.should('be.visible');
|
||||
|
||||
if (entityDetails.isChildrenExist) {
|
||||
cy.get(
|
||||
`[${entityDetails.childSelector}="${entityDetails.updatedTagEntityChildName}"] .diff-added [data-testid="tag-PersonalData.Personal"]`
|
||||
)
|
||||
.scrollIntoView()
|
||||
.should('be.visible');
|
||||
|
||||
cy.get(
|
||||
`[${entityDetails.childSelector}="${entityDetails.updatedTagEntityChildName}"] .diff-added [data-testid="tag-PII.Sensitive"]`
|
||||
)
|
||||
.scrollIntoView()
|
||||
.should('be.visible');
|
||||
|
||||
cy.get(
|
||||
`[data-testid="diff-removed-${entityDetails.entityChildRemovedDescription}"]`
|
||||
)
|
||||
.scrollIntoView()
|
||||
.should('be.visible');
|
||||
|
||||
cy.get(
|
||||
`[data-testid="diff-added-${entityDetails.entityChildAddedDescription}"]`
|
||||
)
|
||||
.scrollIntoView()
|
||||
.should('be.visible');
|
||||
}
|
||||
});
|
||||
|
||||
it(`${entityType} version page should show removed tags changes properly`, () => {
|
||||
visitEntityDetailsPage(
|
||||
entityDetails.term,
|
||||
entityDetails.serviceName,
|
||||
entityDetails.entity,
|
||||
undefined,
|
||||
entityType
|
||||
);
|
||||
|
||||
cy.get(
|
||||
'[data-testid="entity-right-panel"] [data-testid="edit-button"]'
|
||||
).click();
|
||||
|
||||
cy.get(
|
||||
'[data-testid="selected-tag-PersonalData.SpecialCategory"] [data-testid="remove-tags"]'
|
||||
).click();
|
||||
|
||||
interceptURL(
|
||||
'PATCH',
|
||||
`/api/v1/${entityDetails.entity}/${entityId}`,
|
||||
`patch${entityType}`
|
||||
);
|
||||
|
||||
cy.get('[data-testid="saveAssociatedTag"]').click();
|
||||
|
||||
verifyResponseStatusCode(`@patch${entityType}`, 200);
|
||||
|
||||
cy.get('[data-testid="version-button"]').contains('0.3').click();
|
||||
|
||||
cy.get(
|
||||
`[data-testid="entity-right-panel"] .diff-removed [data-testid="tag-PersonalData.SpecialCategory"]`
|
||||
)
|
||||
.scrollIntoView()
|
||||
.should('be.visible');
|
||||
});
|
||||
|
||||
it(`${entityType} version page should show owner changes properly`, () => {
|
||||
visitEntityDetailsPage(
|
||||
entityDetails.term,
|
||||
entityDetails.serviceName,
|
||||
entityDetails.entity,
|
||||
undefined,
|
||||
entityType
|
||||
);
|
||||
|
||||
cy.get('[data-testid="version-button"]').as('versionButton');
|
||||
|
||||
cy.get('@versionButton').contains('0.3');
|
||||
|
||||
addOwner(OWNER, entityDetails.entity);
|
||||
|
||||
interceptURL(
|
||||
'GET',
|
||||
`/api/v1/${entityDetails.entity}/name/${entityFQN}?*include=all`,
|
||||
`get${entityType}Details`
|
||||
);
|
||||
interceptURL(
|
||||
'GET',
|
||||
`/api/v1/${entityDetails.entity}/${entityId}/versions`,
|
||||
'getVersionsList'
|
||||
);
|
||||
interceptURL(
|
||||
'GET',
|
||||
`/api/v1/${entityDetails.entity}/${entityId}/versions/0.4`,
|
||||
'getSelectedVersionDetails'
|
||||
);
|
||||
|
||||
cy.get('@versionButton').contains('0.4').click();
|
||||
|
||||
verifyResponseStatusCode(`@get${entityType}Details`, 200);
|
||||
verifyResponseStatusCode('@getVersionsList', 200);
|
||||
verifyResponseStatusCode('@getSelectedVersionDetails', 200);
|
||||
|
||||
cy.get(`[data-testid="diff-added-${OWNER}"]`)
|
||||
.scrollIntoView()
|
||||
.should('be.visible');
|
||||
|
||||
cy.get('@versionButton').contains('0.4').click();
|
||||
|
||||
removeOwner(entityDetails.entity);
|
||||
|
||||
interceptURL(
|
||||
'GET',
|
||||
`/api/v1/${entityDetails.entity}/${entityId}/versions/0.5`,
|
||||
'getSelectedVersionDetails'
|
||||
);
|
||||
|
||||
cy.get('@versionButton').contains('0.5').click();
|
||||
|
||||
verifyResponseStatusCode(`@get${entityType}Details`, 200);
|
||||
verifyResponseStatusCode('@getVersionsList', 200);
|
||||
verifyResponseStatusCode('@getSelectedVersionDetails', 200);
|
||||
|
||||
cy.get(`[data-testid="diff-removed-${OWNER}"]`)
|
||||
.scrollIntoView()
|
||||
.should('be.visible');
|
||||
});
|
||||
|
||||
it(`${entityType} version page should show tier changes properly`, () => {
|
||||
visitEntityDetailsPage(
|
||||
entityDetails.term,
|
||||
entityDetails.serviceName,
|
||||
entityDetails.entity,
|
||||
undefined,
|
||||
entityType
|
||||
);
|
||||
|
||||
cy.get('[data-testid="version-button"]').as('versionButton');
|
||||
|
||||
cy.get('@versionButton').contains('0.5');
|
||||
|
||||
addTier(TIER, entityDetails.entity);
|
||||
|
||||
interceptURL(
|
||||
'GET',
|
||||
`/api/v1/${entityDetails.entity}/name/${entityFQN}?*include=all`,
|
||||
`get${entityType}Details`
|
||||
);
|
||||
interceptURL(
|
||||
'GET',
|
||||
`/api/v1/${entityDetails.entity}/${entityId}/versions`,
|
||||
'getVersionsList'
|
||||
);
|
||||
interceptURL(
|
||||
'GET',
|
||||
`/api/v1/${entityDetails.entity}/${entityId}/versions/0.6`,
|
||||
'getSelectedVersionDetails'
|
||||
);
|
||||
|
||||
cy.get('@versionButton').contains('0.6').click();
|
||||
|
||||
verifyResponseStatusCode(`@get${entityType}Details`, 200);
|
||||
verifyResponseStatusCode('@getVersionsList', 200);
|
||||
verifyResponseStatusCode('@getSelectedVersionDetails', 200);
|
||||
|
||||
cy.get(`[data-testid="diff-added-${TIER}"]`)
|
||||
.scrollIntoView()
|
||||
.should('be.visible');
|
||||
|
||||
cy.get('@versionButton').contains('0.6').click();
|
||||
|
||||
removeTier(entityDetails.entity);
|
||||
|
||||
interceptURL(
|
||||
'GET',
|
||||
`/api/v1/${entityDetails.entity}/${entityId}/versions/0.7`,
|
||||
'getSelectedVersionDetails'
|
||||
);
|
||||
|
||||
cy.get('@versionButton').contains('0.7').click();
|
||||
|
||||
verifyResponseStatusCode(`@get${entityType}Details`, 200);
|
||||
verifyResponseStatusCode('@getVersionsList', 200);
|
||||
verifyResponseStatusCode('@getSelectedVersionDetails', 200);
|
||||
|
||||
cy.get(`[data-testid="diff-removed-${TIER}"]`)
|
||||
.scrollIntoView()
|
||||
.should('be.visible');
|
||||
});
|
||||
|
||||
it(`Cleanup for ${entityType} version page test`, () => {
|
||||
deleteEntity(
|
||||
entityDetails.name,
|
||||
entityDetails.serviceName,
|
||||
entityDetails.entity,
|
||||
entityType,
|
||||
successMessageEntityName
|
||||
);
|
||||
});
|
||||
});
|
||||
}
|
||||
);
|
||||
@ -215,10 +215,6 @@ const ContainerVersion: React.FC<ContainerVersionProp> = ({
|
||||
]
|
||||
);
|
||||
|
||||
if (!(entityPermissions.ViewAll || entityPermissions.ViewBasic)) {
|
||||
return <ErrorPlaceHolder type={ERROR_PLACEHOLDER_TYPE.PERMISSION} />;
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
{isVersionLoading ? (
|
||||
|
||||
@ -117,37 +117,6 @@ describe('ContainerVersion tests', () => {
|
||||
expect(versionTable).toBeNull();
|
||||
});
|
||||
|
||||
it('Should display ErrorPlaceholder if no viewing permission', async () => {
|
||||
await act(async () => {
|
||||
render(
|
||||
<ContainerVersion
|
||||
{...containerVersionMockProps}
|
||||
entityPermissions={DEFAULT_ENTITY_PERMISSION}
|
||||
/>
|
||||
);
|
||||
});
|
||||
|
||||
const errorPlaceHolder = screen.getByText('ErrorPlaceHolder');
|
||||
const loader = screen.queryByText('Loader');
|
||||
const dataAssetsVersionHeader = screen.queryByText(
|
||||
'DataAssetsVersionHeader'
|
||||
);
|
||||
const schemaTabLabel = screen.queryByText('label.schema');
|
||||
const customPropertyTabLabel = screen.queryByText(
|
||||
'label.custom-property-plural'
|
||||
);
|
||||
const entityVersionTimeLine = screen.queryByText('EntityVersionTimeLine');
|
||||
const versionTable = screen.queryByText('VersionTable');
|
||||
|
||||
expect(errorPlaceHolder).toBeInTheDocument();
|
||||
expect(loader).toBeNull();
|
||||
expect(entityVersionTimeLine).toBeNull();
|
||||
expect(dataAssetsVersionHeader).toBeNull();
|
||||
expect(schemaTabLabel).toBeNull();
|
||||
expect(customPropertyTabLabel).toBeNull();
|
||||
expect(versionTable).toBeNull();
|
||||
});
|
||||
|
||||
it('Should update url on click of tab', async () => {
|
||||
await act(async () => {
|
||||
render(<ContainerVersion {...containerVersionMockProps} />);
|
||||
|
||||
@ -234,10 +234,6 @@ const DashboardVersion: FC<DashboardVersionProp> = ({
|
||||
[description, tableColumn, currentVersionData, entityPermissions]
|
||||
);
|
||||
|
||||
if (!(entityPermissions.ViewAll || entityPermissions.ViewBasic)) {
|
||||
return <ErrorPlaceHolder type={ERROR_PLACEHOLDER_TYPE.PERMISSION} />;
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
{isVersionLoading ? (
|
||||
|
||||
@ -16,7 +16,6 @@ import userEvent from '@testing-library/user-event';
|
||||
import { ENTITY_PERMISSIONS } from 'mocks/Permissions.mock';
|
||||
import React from 'react';
|
||||
import { MemoryRouter } from 'react-router-dom';
|
||||
import { DEFAULT_ENTITY_PERMISSION } from 'utils/PermissionsUtils';
|
||||
import {
|
||||
dashboardVersionProps,
|
||||
mockNoChartData,
|
||||
@ -222,39 +221,4 @@ describe('DashboardVersion tests', () => {
|
||||
'/dashboard/sample_superset.eta_predictions_performance/versions/0.3/custom_properties'
|
||||
);
|
||||
});
|
||||
|
||||
it('Should display ErrorPlaceholder if no viewing permission', async () => {
|
||||
await act(async () => {
|
||||
render(
|
||||
<DashboardVersion
|
||||
{...dashboardVersionProps}
|
||||
entityPermissions={DEFAULT_ENTITY_PERMISSION}
|
||||
/>,
|
||||
{
|
||||
wrapper: MemoryRouter,
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
const versionData = screen.queryByTestId('version-data');
|
||||
const schemaTable = screen.queryByTestId('schema-table');
|
||||
|
||||
const tabs = screen.queryByTestId('tabs');
|
||||
const description = screen.queryByText('Description.component');
|
||||
const richTextEditorPreviewer = screen.queryByText(
|
||||
'RichTextEditorPreviewer.component'
|
||||
);
|
||||
const entityVersionTimeLine = screen.queryByText(
|
||||
'EntityVersionTimeLine.component'
|
||||
);
|
||||
const errorPlaceHolder = screen.getByText('ErrorPlaceHolder');
|
||||
|
||||
expect(entityVersionTimeLine).toBeNull();
|
||||
expect(versionData).toBeNull();
|
||||
expect(schemaTable).toBeNull();
|
||||
expect(tabs).toBeNull();
|
||||
expect(description).toBeNull();
|
||||
expect(richTextEditorPreviewer).toBeNull();
|
||||
expect(errorPlaceHolder).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
@ -14,13 +14,11 @@
|
||||
import { Col, Row, Space, Tabs, TabsProps } from 'antd';
|
||||
import classNames from 'classnames';
|
||||
import DescriptionV1 from 'components/common/description/DescriptionV1';
|
||||
import ErrorPlaceHolder from 'components/common/error-with-placeholder/ErrorPlaceHolder';
|
||||
import DataAssetsVersionHeader from 'components/DataAssets/DataAssetsVersionHeader/DataAssetsVersionHeader';
|
||||
import EntityVersionTimeLine from 'components/Entity/EntityVersionTimeLine/EntityVersionTimeLine';
|
||||
import TabsLabel from 'components/TabsLabel/TabsLabel.component';
|
||||
import TagsContainerV2 from 'components/Tag/TagsContainerV2/TagsContainerV2';
|
||||
import VersionTable from 'components/VersionTable/VersionTable.component';
|
||||
import { ERROR_PLACEHOLDER_TYPE } from 'enums/common.enum';
|
||||
import { EntityTabs, EntityType, FqnPart } from 'enums/entity.enum';
|
||||
import {
|
||||
ChangeDescription,
|
||||
@ -28,27 +26,18 @@ import {
|
||||
DashboardDataModel,
|
||||
} from 'generated/entity/data/dashboardDataModel';
|
||||
import { TagSource } from 'generated/type/schema';
|
||||
import { EntityDiffProps } from 'interface/EntityVersion.interface';
|
||||
import { cloneDeep, isEqual } from 'lodash';
|
||||
import { cloneDeep } from 'lodash';
|
||||
import React, { FC, useEffect, useMemo, useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { getPartialNameFromTableFQN } from 'utils/CommonUtils';
|
||||
import { FQN_SEPARATOR_CHAR } from '../../constants/char.constants';
|
||||
import { EntityField } from '../../constants/Feeds.constants';
|
||||
import { TagLabel } from '../../generated/type/tagLabel';
|
||||
import {
|
||||
getChangedEntityName,
|
||||
getChangedEntityNewValue,
|
||||
getChangedEntityOldValue,
|
||||
getColumnsDataWithVersionChanges,
|
||||
getCommonExtraInfoForVersionDetails,
|
||||
getDiffByFieldName,
|
||||
getEntityVersionByField,
|
||||
getEntityVersionTags,
|
||||
getTagsDiff,
|
||||
getTextDiff,
|
||||
isEndsWithField,
|
||||
} from '../../utils/EntityVersionUtils';
|
||||
import { TagLabelWithStatus } from '../../utils/EntityVersionUtils.interface';
|
||||
import Loader from '../Loader/Loader';
|
||||
import { DataModelVersionProp } from './DataModelVersion.interface';
|
||||
|
||||
@ -64,181 +53,24 @@ const DataModelVersion: FC<DataModelVersionProp> = ({
|
||||
backHandler,
|
||||
versionHandler,
|
||||
dataModelFQN,
|
||||
entityPermissions,
|
||||
}: DataModelVersionProp) => {
|
||||
const { t } = useTranslation();
|
||||
const [changeDescription, setChangeDescription] = useState<ChangeDescription>(
|
||||
currentVersionData.changeDescription as ChangeDescription
|
||||
);
|
||||
|
||||
const getChangeColName = (name: string | undefined) => {
|
||||
const nameArr = name?.split(FQN_SEPARATOR_CHAR);
|
||||
|
||||
if (nameArr?.length === 3) {
|
||||
return nameArr.slice(-2, -1)[0];
|
||||
} else {
|
||||
return nameArr?.slice(-3, -1)?.join('.');
|
||||
}
|
||||
};
|
||||
|
||||
const { ownerDisplayName, ownerRef, tierDisplayName } = useMemo(
|
||||
() => getCommonExtraInfoForVersionDetails(changeDescription, owner, tier),
|
||||
[changeDescription, owner, tier]
|
||||
);
|
||||
|
||||
const handleColumnDescriptionChangeDiff = (
|
||||
colList: DashboardDataModel['columns'],
|
||||
columnsDiff: EntityDiffProps,
|
||||
changedColName: string | undefined
|
||||
) => {
|
||||
const oldDescription = getChangedEntityOldValue(columnsDiff);
|
||||
const newDescription = getChangedEntityNewValue(columnsDiff);
|
||||
|
||||
const formatColumnData = (arr: DashboardDataModel['columns']) => {
|
||||
arr?.forEach((i) => {
|
||||
if (isEqual(i.name, changedColName)) {
|
||||
i.description = getTextDiff(
|
||||
oldDescription ?? '',
|
||||
newDescription ?? '',
|
||||
i.description
|
||||
);
|
||||
} else {
|
||||
formatColumnData(i?.children as DashboardDataModel['columns']);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
formatColumnData(colList);
|
||||
};
|
||||
|
||||
const handleColumnTagChangeDiff = (
|
||||
colList: DashboardDataModel['columns'],
|
||||
columnsDiff: EntityDiffProps,
|
||||
changedColName: string | undefined
|
||||
) => {
|
||||
const oldTags: Array<TagLabel> = JSON.parse(
|
||||
getChangedEntityOldValue(columnsDiff) ?? '[]'
|
||||
);
|
||||
const newTags: Array<TagLabel> = JSON.parse(
|
||||
getChangedEntityNewValue(columnsDiff) ?? '[]'
|
||||
);
|
||||
|
||||
const formatColumnData = (arr: DashboardDataModel['columns']) => {
|
||||
arr?.forEach((i) => {
|
||||
if (isEqual(i.name, changedColName)) {
|
||||
const flag: { [x: string]: boolean } = {};
|
||||
const uniqueTags: Array<TagLabelWithStatus> = [];
|
||||
const tagsDiff = getTagsDiff(oldTags, newTags);
|
||||
[...tagsDiff, ...(i.tags as Array<TagLabelWithStatus>)].forEach(
|
||||
(elem: TagLabelWithStatus) => {
|
||||
if (!flag[elem.tagFQN]) {
|
||||
flag[elem.tagFQN] = true;
|
||||
uniqueTags.push(elem);
|
||||
}
|
||||
}
|
||||
);
|
||||
i.tags = uniqueTags;
|
||||
} else {
|
||||
formatColumnData(i?.children as DashboardDataModel['columns']);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
formatColumnData(colList);
|
||||
};
|
||||
|
||||
const handleColumnDiffAdded = (
|
||||
colList: DashboardDataModel['columns'],
|
||||
columnsDiff: EntityDiffProps
|
||||
) => {
|
||||
const newCol: Array<Column> = JSON.parse(
|
||||
columnsDiff.added?.newValue ?? '[]'
|
||||
);
|
||||
newCol.forEach((col) => {
|
||||
const formatColumnData = (arr: DashboardDataModel['columns']) => {
|
||||
arr?.forEach((i) => {
|
||||
if (isEqual(i.name, col.name)) {
|
||||
i.tags = col.tags?.map((tag) => ({ ...tag, added: true }));
|
||||
i.description = getTextDiff('', col.description ?? '');
|
||||
i.dataTypeDisplay = getTextDiff('', col.dataTypeDisplay ?? '');
|
||||
i.name = getTextDiff('', col.name);
|
||||
} else {
|
||||
formatColumnData(i?.children as DashboardDataModel['columns']);
|
||||
}
|
||||
});
|
||||
};
|
||||
formatColumnData(colList);
|
||||
});
|
||||
};
|
||||
|
||||
const handleColumnDiffDeleted = (columnsDiff: EntityDiffProps) => {
|
||||
const newCol: Array<Column> = JSON.parse(
|
||||
columnsDiff.deleted?.oldValue ?? '[]'
|
||||
);
|
||||
|
||||
return newCol.map((col) => ({
|
||||
...col,
|
||||
tags: col.tags?.map((tag) => ({ ...tag, removed: true })),
|
||||
description: getTextDiff(col.description ?? '', ''),
|
||||
dataTypeDisplay: getTextDiff(col.dataTypeDisplay ?? '', ''),
|
||||
name: getTextDiff(col.name, ''),
|
||||
}));
|
||||
};
|
||||
|
||||
const columns: DashboardDataModel['columns'] = useMemo(() => {
|
||||
const colList = cloneDeep(
|
||||
(currentVersionData as DashboardDataModel).columns || []
|
||||
);
|
||||
const columnsDiff = getDiffByFieldName(
|
||||
EntityField.COLUMNS,
|
||||
changeDescription
|
||||
);
|
||||
const changedColName = getChangeColName(getChangedEntityName(columnsDiff));
|
||||
const colNameWithoutQuotes = changedColName?.replaceAll(/(^")|("$)/g, '');
|
||||
|
||||
if (
|
||||
isEndsWithField(
|
||||
EntityField.DESCRIPTION,
|
||||
getChangedEntityName(columnsDiff)
|
||||
)
|
||||
) {
|
||||
handleColumnDescriptionChangeDiff(
|
||||
colList,
|
||||
columnsDiff,
|
||||
colNameWithoutQuotes
|
||||
);
|
||||
|
||||
return colList;
|
||||
} else if (
|
||||
isEndsWithField(EntityField.TAGS, getChangedEntityName(columnsDiff))
|
||||
) {
|
||||
handleColumnTagChangeDiff(colList, columnsDiff, colNameWithoutQuotes);
|
||||
|
||||
return colList;
|
||||
} else {
|
||||
const columnsDiff = getDiffByFieldName(
|
||||
EntityField.COLUMNS,
|
||||
changeDescription,
|
||||
true
|
||||
);
|
||||
let newColumns: Column[] = [];
|
||||
if (columnsDiff.added) {
|
||||
handleColumnDiffAdded(colList, columnsDiff);
|
||||
}
|
||||
if (columnsDiff.deleted) {
|
||||
newColumns = handleColumnDiffDeleted(columnsDiff);
|
||||
} else {
|
||||
return colList;
|
||||
}
|
||||
|
||||
return [...newColumns, ...colList];
|
||||
}
|
||||
}, [
|
||||
currentVersionData,
|
||||
changeDescription,
|
||||
getChangeColName,
|
||||
handleColumnDescriptionChangeDiff,
|
||||
]);
|
||||
return getColumnsDataWithVersionChanges<Column>(changeDescription, colList);
|
||||
}, [currentVersionData, changeDescription]);
|
||||
|
||||
useEffect(() => {
|
||||
setChangeDescription(
|
||||
@ -319,10 +151,6 @@ const DataModelVersion: FC<DataModelVersionProp> = ({
|
||||
[description, dataModelFQN, columns]
|
||||
);
|
||||
|
||||
if (!(entityPermissions.ViewAll || entityPermissions.ViewBasic)) {
|
||||
return <ErrorPlaceHolder type={ERROR_PLACEHOLDER_TYPE.PERMISSION} />;
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<div data-testid="data-model-version-container">
|
||||
|
||||
@ -11,7 +11,6 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { OperationPermission } from 'components/PermissionProvider/PermissionProvider.interface';
|
||||
import { DashboardDataModel } from 'generated/entity/data/dashboardDataModel';
|
||||
import { VersionData } from 'pages/EntityVersionPage/EntityVersionPage.component';
|
||||
import { EntityHistory } from '../../generated/type/entityHistory';
|
||||
@ -31,5 +30,4 @@ export interface DataModelVersionProp {
|
||||
deleted?: boolean;
|
||||
backHandler: () => void;
|
||||
versionHandler: (v: string) => void;
|
||||
entityPermissions: OperationPermission;
|
||||
}
|
||||
|
||||
@ -43,9 +43,13 @@ const DataModelTable = ({
|
||||
key: 'displayName',
|
||||
width: 350,
|
||||
render: (_, record: ServicePageData) => {
|
||||
const dataModelDisplayName = getEntityName(record);
|
||||
|
||||
return (
|
||||
<Link to={getDataModelDetailsPath(record.fullyQualifiedName || '')}>
|
||||
{getEntityName(record)}
|
||||
<Link
|
||||
data-testid={`data-model-${dataModelDisplayName}`}
|
||||
to={getDataModelDetailsPath(record.fullyQualifiedName || '')}>
|
||||
{dataModelDisplayName}
|
||||
</Link>
|
||||
);
|
||||
},
|
||||
|
||||
@ -123,7 +123,7 @@ const ExploreSearchCard: React.FC<ExploreSearchCardProps> = forwardRef<
|
||||
</div>
|
||||
</Col>
|
||||
)}
|
||||
<Col span={24}>
|
||||
<Col data-testid={`${source.service?.name}-${source.name}`} span={24}>
|
||||
{isTourOpen ? (
|
||||
<Button data-testid={source.fullyQualifiedName} type="link">
|
||||
<Typography.Text
|
||||
|
||||
@ -17,7 +17,6 @@ import { Mlmodel } from '../../generated/entity/data/mlmodel';
|
||||
|
||||
export interface MlModelDetailProp extends HTMLAttributes<HTMLDivElement> {
|
||||
mlModelDetail: Mlmodel;
|
||||
version?: string;
|
||||
fetchMlModel: () => void;
|
||||
followMlModelHandler: () => Promise<void>;
|
||||
unFollowMlModelHandler: () => Promise<void>;
|
||||
|
||||
@ -163,7 +163,7 @@ const MlModelVersion: FC<MlModelVersionProp> = ({
|
||||
<Card
|
||||
bordered
|
||||
className="m-b-xlg"
|
||||
data-testid="feature-card"
|
||||
data-testid={`feature-card-${feature.name ?? ''}`}
|
||||
key={feature.fullyQualifiedName}>
|
||||
<Row>
|
||||
<Col className="m-b-xs" span={24}>
|
||||
@ -319,10 +319,6 @@ const MlModelVersion: FC<MlModelVersionProp> = ({
|
||||
[description, mlFeaturesData, currentVersionData, entityPermissions]
|
||||
);
|
||||
|
||||
if (!(entityPermissions.ViewAll || entityPermissions.ViewBasic)) {
|
||||
return <ErrorPlaceHolder type={ERROR_PLACEHOLDER_TYPE.PERMISSION} />;
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
{isVersionLoading ? (
|
||||
|
||||
@ -114,35 +114,6 @@ describe('MlModelVersion tests', () => {
|
||||
expect(customPropertyTabLabel).toBeNull();
|
||||
});
|
||||
|
||||
it('Should display ErrorPlaceholder if no viewing permission', async () => {
|
||||
await act(async () => {
|
||||
render(
|
||||
<MlModelVersion
|
||||
{...mlModelVersionMockProps}
|
||||
entityPermissions={DEFAULT_ENTITY_PERMISSION}
|
||||
/>
|
||||
);
|
||||
});
|
||||
|
||||
const errorPlaceHolder = screen.getByText('ErrorPlaceHolder');
|
||||
const loader = screen.queryByText('Loader');
|
||||
const dataAssetsVersionHeader = screen.queryByText(
|
||||
'DataAssetsVersionHeader'
|
||||
);
|
||||
const featureTabLabel = screen.queryByText('label.feature-plural');
|
||||
const customPropertyTabLabel = screen.queryByText(
|
||||
'label.custom-property-plural'
|
||||
);
|
||||
const entityVersionTimeLine = screen.queryByText('EntityVersionTimeLine');
|
||||
|
||||
expect(errorPlaceHolder).toBeInTheDocument();
|
||||
expect(loader).toBeNull();
|
||||
expect(entityVersionTimeLine).toBeNull();
|
||||
expect(dataAssetsVersionHeader).toBeNull();
|
||||
expect(featureTabLabel).toBeNull();
|
||||
expect(customPropertyTabLabel).toBeNull();
|
||||
});
|
||||
|
||||
it('No data placeholder should be displayed if no mlFeatures are present in the mlModel data', async () => {
|
||||
await act(async () => {
|
||||
render(
|
||||
|
||||
@ -251,10 +251,6 @@ const PipelineVersion: FC<PipelineVersionProp> = ({
|
||||
]
|
||||
);
|
||||
|
||||
if (!(entityPermissions.ViewAll || entityPermissions.ViewBasic)) {
|
||||
return <ErrorPlaceHolder type={ERROR_PLACEHOLDER_TYPE.PERMISSION} />;
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
{isVersionLoading ? (
|
||||
|
||||
@ -131,37 +131,6 @@ describe('PipelineVersion tests', () => {
|
||||
expect(schemaTable).toBeNull();
|
||||
});
|
||||
|
||||
it('Should display ErrorPlaceholder if no viewing permission', async () => {
|
||||
await act(async () => {
|
||||
render(
|
||||
<PipelineVersion
|
||||
{...pipelineVersionMockProps}
|
||||
entityPermissions={DEFAULT_ENTITY_PERMISSION}
|
||||
/>
|
||||
);
|
||||
});
|
||||
|
||||
const errorPlaceHolder = screen.getByText('ErrorPlaceHolder');
|
||||
const loader = screen.queryByText('Loader');
|
||||
const dataAssetsVersionHeader = screen.queryByText(
|
||||
'DataAssetsVersionHeader'
|
||||
);
|
||||
const schemaTabLabel = screen.queryByText('label.schema');
|
||||
const customPropertyTabLabel = screen.queryByText(
|
||||
'label.custom-property-plural'
|
||||
);
|
||||
const entityVersionTimeLine = screen.queryByText('EntityVersionTimeLine');
|
||||
const schemaTable = screen.queryByTestId('schema-table');
|
||||
|
||||
expect(errorPlaceHolder).toBeInTheDocument();
|
||||
expect(loader).toBeNull();
|
||||
expect(entityVersionTimeLine).toBeNull();
|
||||
expect(dataAssetsVersionHeader).toBeNull();
|
||||
expect(schemaTabLabel).toBeNull();
|
||||
expect(customPropertyTabLabel).toBeNull();
|
||||
expect(schemaTable).toBeNull();
|
||||
});
|
||||
|
||||
it('Should update url on click of tab', async () => {
|
||||
await act(async () => {
|
||||
render(<PipelineVersion {...pipelineVersionMockProps} />, {
|
||||
|
||||
@ -226,10 +226,6 @@ const TableVersion: React.FC<TableVersionProp> = ({
|
||||
]
|
||||
);
|
||||
|
||||
if (!(entityPermissions.ViewAll || entityPermissions.ViewBasic)) {
|
||||
return <ErrorPlaceHolder type={ERROR_PLACEHOLDER_TYPE.PERMISSION} />;
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
{isVersionLoading ? (
|
||||
|
||||
@ -115,37 +115,6 @@ describe('TableVersion tests', () => {
|
||||
expect(versionTable).toBeNull();
|
||||
});
|
||||
|
||||
it('Should display ErrorPlaceholder if no viewing permission', async () => {
|
||||
await act(async () => {
|
||||
render(
|
||||
<TableVersion
|
||||
{...tableVersionMockProps}
|
||||
entityPermissions={DEFAULT_ENTITY_PERMISSION}
|
||||
/>
|
||||
);
|
||||
});
|
||||
|
||||
const errorPlaceHolder = screen.getByText('ErrorPlaceHolder');
|
||||
const loader = screen.queryByText('Loader');
|
||||
const dataAssetsVersionHeader = screen.queryByText(
|
||||
'DataAssetsVersionHeader'
|
||||
);
|
||||
const schemaTabLabel = screen.queryByText('label.schema');
|
||||
const customPropertyTabLabel = screen.queryByText(
|
||||
'label.custom-property-plural'
|
||||
);
|
||||
const entityVersionTimeLine = screen.queryByText('EntityVersionTimeLine');
|
||||
const versionTable = screen.queryByText('VersionTable');
|
||||
|
||||
expect(errorPlaceHolder).toBeInTheDocument();
|
||||
expect(loader).toBeNull();
|
||||
expect(entityVersionTimeLine).toBeNull();
|
||||
expect(dataAssetsVersionHeader).toBeNull();
|
||||
expect(schemaTabLabel).toBeNull();
|
||||
expect(customPropertyTabLabel).toBeNull();
|
||||
expect(versionTable).toBeNull();
|
||||
});
|
||||
|
||||
it('Should update url on click of tab', async () => {
|
||||
await act(async () => {
|
||||
render(<TableVersion {...tableVersionMockProps} />);
|
||||
|
||||
@ -205,10 +205,6 @@ const TopicVersion: FC<TopicVersionProp> = ({
|
||||
]
|
||||
);
|
||||
|
||||
if (!(entityPermissions.ViewAll || entityPermissions.ViewBasic)) {
|
||||
return <ErrorPlaceHolder type={ERROR_PLACEHOLDER_TYPE.PERMISSION} />;
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
{isVersionLoading ? (
|
||||
|
||||
@ -116,37 +116,6 @@ describe('TopicVersion tests', () => {
|
||||
expect(topicSchema).toBeNull();
|
||||
});
|
||||
|
||||
it('Should display ErrorPlaceholder if no viewing permission', async () => {
|
||||
await act(async () => {
|
||||
render(
|
||||
<TopicVersion
|
||||
{...topicVersionMockProps}
|
||||
entityPermissions={DEFAULT_ENTITY_PERMISSION}
|
||||
/>
|
||||
);
|
||||
});
|
||||
|
||||
const errorPlaceHolder = screen.getByText('ErrorPlaceHolder');
|
||||
const loader = screen.queryByText('Loader');
|
||||
const dataAssetsVersionHeader = screen.queryByText(
|
||||
'DataAssetsVersionHeader'
|
||||
);
|
||||
const schemaTabLabel = screen.queryByText('label.schema');
|
||||
const customPropertyTabLabel = screen.queryByText(
|
||||
'label.custom-property-plural'
|
||||
);
|
||||
const entityVersionTimeLine = screen.queryByText('EntityVersionTimeLine');
|
||||
const topicSchema = screen.queryByText('TopicSchema');
|
||||
|
||||
expect(errorPlaceHolder).toBeInTheDocument();
|
||||
expect(loader).toBeNull();
|
||||
expect(entityVersionTimeLine).toBeNull();
|
||||
expect(dataAssetsVersionHeader).toBeNull();
|
||||
expect(schemaTabLabel).toBeNull();
|
||||
expect(customPropertyTabLabel).toBeNull();
|
||||
expect(topicSchema).toBeNull();
|
||||
});
|
||||
|
||||
it('Should display ErrorPlaceholder in Custom Property tab if no "viewAll" permission', async () => {
|
||||
await act(async () => {
|
||||
render(
|
||||
@ -200,29 +169,4 @@ describe('TopicVersion tests', () => {
|
||||
'/topic/sample_kafka.sales/versions/0.3/custom_properties'
|
||||
);
|
||||
});
|
||||
|
||||
it('ErrorPlaceholder should be displayed in case of no view permissions', async () => {
|
||||
await act(async () => {
|
||||
render(
|
||||
<TopicVersion
|
||||
{...topicVersionMockProps}
|
||||
entityPermissions={DEFAULT_ENTITY_PERMISSION}
|
||||
/>
|
||||
);
|
||||
});
|
||||
|
||||
const topicSchema = screen.queryByText('TopicSchema');
|
||||
|
||||
const description = screen.queryByText('Description.component');
|
||||
|
||||
const entityVersionTimeLine = screen.queryByText(
|
||||
'EntityVersionTimeLine.component'
|
||||
);
|
||||
const errorPlaceHolder = screen.getByText('ErrorPlaceHolder');
|
||||
|
||||
expect(entityVersionTimeLine).toBeNull();
|
||||
expect(topicSchema).toBeNull();
|
||||
expect(description).toBeNull();
|
||||
expect(errorPlaceHolder).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
@ -339,27 +339,29 @@ const ContainerPage = () => {
|
||||
|
||||
const handleUpdateTier = async (updatedTier?: string) => {
|
||||
try {
|
||||
if (updatedTier) {
|
||||
const { tags: newTags, version } = await handleUpdateContainerData({
|
||||
...(containerData as Container),
|
||||
tags: [
|
||||
...getTagsWithoutTier(containerData?.tags ?? []),
|
||||
{
|
||||
tagFQN: updatedTier,
|
||||
labelType: LabelType.Manual,
|
||||
state: State.Confirmed,
|
||||
source: TagSource.Classification,
|
||||
},
|
||||
],
|
||||
});
|
||||
const { tags: newTags, version } = await handleUpdateContainerData({
|
||||
...(containerData as Container),
|
||||
tags: [
|
||||
...getTagsWithoutTier(containerData?.tags ?? []),
|
||||
...(updatedTier
|
||||
? [
|
||||
{
|
||||
tagFQN: updatedTier,
|
||||
labelType: LabelType.Manual,
|
||||
state: State.Confirmed,
|
||||
source: TagSource.Classification,
|
||||
},
|
||||
]
|
||||
: []),
|
||||
],
|
||||
});
|
||||
|
||||
setContainerData((prev) => ({
|
||||
...(prev as Container),
|
||||
tags: newTags,
|
||||
version,
|
||||
}));
|
||||
getEntityFeedCount();
|
||||
}
|
||||
setContainerData((prev) => ({
|
||||
...(prev as Container),
|
||||
tags: newTags,
|
||||
version,
|
||||
}));
|
||||
getEntityFeedCount();
|
||||
} catch (error) {
|
||||
showErrorToast(error as AxiosError);
|
||||
}
|
||||
|
||||
@ -228,26 +228,28 @@ const DataModelsPage = () => {
|
||||
|
||||
const handleUpdateTier = async (updatedTier?: string) => {
|
||||
try {
|
||||
if (updatedTier) {
|
||||
const { tags: newTags, version } = await handleUpdateDataModelData({
|
||||
...(dataModelData as DashboardDataModel),
|
||||
tags: [
|
||||
...getTagsWithoutTier(dataModelData?.tags ?? []),
|
||||
{
|
||||
tagFQN: updatedTier,
|
||||
labelType: LabelType.Manual,
|
||||
state: State.Confirmed,
|
||||
source: TagSource.Classification,
|
||||
},
|
||||
],
|
||||
});
|
||||
const { tags: newTags, version } = await handleUpdateDataModelData({
|
||||
...(dataModelData as DashboardDataModel),
|
||||
tags: [
|
||||
...getTagsWithoutTier(dataModelData?.tags ?? []),
|
||||
...(updatedTier
|
||||
? [
|
||||
{
|
||||
tagFQN: updatedTier,
|
||||
labelType: LabelType.Manual,
|
||||
state: State.Confirmed,
|
||||
source: TagSource.Classification,
|
||||
},
|
||||
]
|
||||
: []),
|
||||
],
|
||||
});
|
||||
|
||||
setDataModelData((prev) => ({
|
||||
...(prev as DashboardDataModel),
|
||||
tags: newTags,
|
||||
version,
|
||||
}));
|
||||
}
|
||||
setDataModelData((prev) => ({
|
||||
...(prev as DashboardDataModel),
|
||||
tags: newTags,
|
||||
version,
|
||||
}));
|
||||
} catch (error) {
|
||||
showErrorToast(error as AxiosError);
|
||||
}
|
||||
|
||||
@ -27,6 +27,7 @@ import React, {
|
||||
FunctionComponent,
|
||||
useCallback,
|
||||
useEffect,
|
||||
useMemo,
|
||||
useState,
|
||||
} from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
@ -88,12 +89,14 @@ import { EntityHistory } from '../../generated/type/entityHistory';
|
||||
import { TagLabel } from '../../generated/type/tagLabel';
|
||||
import { getPartialNameFromFQN } from '../../utils/CommonUtils';
|
||||
|
||||
import ErrorPlaceHolder from 'components/common/error-with-placeholder/ErrorPlaceHolder';
|
||||
import PageLayoutV1 from 'components/containers/PageLayoutV1';
|
||||
import { usePermissionProvider } from 'components/PermissionProvider/PermissionProvider';
|
||||
import {
|
||||
OperationPermission,
|
||||
ResourceEntity,
|
||||
} from 'components/PermissionProvider/PermissionProvider.interface';
|
||||
import { ERROR_PLACEHOLDER_TYPE } from 'enums/common.enum';
|
||||
import { isEmpty } from 'lodash';
|
||||
import { DEFAULT_ENTITY_PERMISSION } from 'utils/PermissionsUtils';
|
||||
import { getTierTags } from '../../utils/TableUtils';
|
||||
@ -127,11 +130,11 @@ const EntityVersionPage: FunctionComponent = () => {
|
||||
const { getEntityPermissionByFqn } = usePermissionProvider();
|
||||
const [entityPermissions, setEntityPermissions] =
|
||||
useState<OperationPermission>(DEFAULT_ENTITY_PERMISSION);
|
||||
const [isLoading, setIsLoading] = useState<boolean>(false);
|
||||
const [isLoading, setIsLoading] = useState<boolean>(true);
|
||||
const [versionList, setVersionList] = useState<EntityHistory>(
|
||||
{} as EntityHistory
|
||||
);
|
||||
const [isVersionLoading, setIsVersionLoading] = useState<boolean>(false);
|
||||
const [isVersionLoading, setIsVersionLoading] = useState<boolean>(true);
|
||||
const [slashedEntityName, setSlashedEntityName] = useState<
|
||||
TitleBreadcrumbProps['titleLinks']
|
||||
>([]);
|
||||
@ -207,11 +210,11 @@ const EntityVersionPage: FunctionComponent = () => {
|
||||
|
||||
const fetchResourcePermission = useCallback(
|
||||
async (resourceEntity: ResourceEntity) => {
|
||||
if (!isEmpty(currentVersionData)) {
|
||||
if (!isEmpty(entityFQN)) {
|
||||
try {
|
||||
const permission = await getEntityPermissionByFqn(
|
||||
resourceEntity,
|
||||
currentVersionData.id ?? ''
|
||||
entityFQN
|
||||
);
|
||||
|
||||
setEntityPermissions(permission);
|
||||
@ -220,7 +223,7 @@ const EntityVersionPage: FunctionComponent = () => {
|
||||
}
|
||||
}
|
||||
},
|
||||
[currentVersionData.id, getEntityPermissionByFqn, setEntityPermissions]
|
||||
[entityFQN, getEntityPermissionByFqn, setEntityPermissions]
|
||||
);
|
||||
|
||||
const fetchEntityPermissions = useCallback(async () => {
|
||||
@ -228,37 +231,37 @@ const EntityVersionPage: FunctionComponent = () => {
|
||||
try {
|
||||
switch (entityType) {
|
||||
case EntityType.TABLE: {
|
||||
fetchResourcePermission(ResourceEntity.TABLE);
|
||||
await fetchResourcePermission(ResourceEntity.TABLE);
|
||||
|
||||
break;
|
||||
}
|
||||
case EntityType.TOPIC: {
|
||||
fetchResourcePermission(ResourceEntity.TOPIC);
|
||||
await fetchResourcePermission(ResourceEntity.TOPIC);
|
||||
|
||||
break;
|
||||
}
|
||||
case EntityType.DASHBOARD: {
|
||||
fetchResourcePermission(ResourceEntity.DASHBOARD);
|
||||
await fetchResourcePermission(ResourceEntity.DASHBOARD);
|
||||
|
||||
break;
|
||||
}
|
||||
case EntityType.PIPELINE: {
|
||||
fetchResourcePermission(ResourceEntity.PIPELINE);
|
||||
await fetchResourcePermission(ResourceEntity.PIPELINE);
|
||||
|
||||
break;
|
||||
}
|
||||
case EntityType.MLMODEL: {
|
||||
fetchResourcePermission(ResourceEntity.ML_MODEL);
|
||||
await fetchResourcePermission(ResourceEntity.ML_MODEL);
|
||||
|
||||
break;
|
||||
}
|
||||
case EntityType.CONTAINER: {
|
||||
fetchResourcePermission(ResourceEntity.CONTAINER);
|
||||
await fetchResourcePermission(ResourceEntity.CONTAINER);
|
||||
|
||||
break;
|
||||
}
|
||||
case EntityType.DASHBOARD_DATA_MODEL: {
|
||||
fetchResourcePermission(ResourceEntity.DASHBOARD_DATA_MODEL);
|
||||
await fetchResourcePermission(ResourceEntity.DASHBOARD_DATA_MODEL);
|
||||
|
||||
break;
|
||||
}
|
||||
@ -266,241 +269,129 @@ const EntityVersionPage: FunctionComponent = () => {
|
||||
break;
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
} catch {
|
||||
// Error
|
||||
}
|
||||
}, [entityType, fetchResourcePermission]);
|
||||
|
||||
const viewVersionPermission = useMemo(
|
||||
() => entityPermissions.ViewAll || entityPermissions.ViewBasic,
|
||||
[entityPermissions]
|
||||
);
|
||||
|
||||
const fetchEntityVersions = useCallback(async () => {
|
||||
setIsLoading(true);
|
||||
try {
|
||||
switch (entityType) {
|
||||
case EntityType.TABLE: {
|
||||
const { id } = await getTableDetailsByFQN(entityFQN, '');
|
||||
|
||||
setEntityId(id);
|
||||
|
||||
const versions = await getTableVersions(id);
|
||||
|
||||
setVersionList(versions);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case EntityType.TOPIC: {
|
||||
const { id } = await getTopicByFqn(
|
||||
getPartialNameFromFQN(
|
||||
entityFQN,
|
||||
['service', 'database'],
|
||||
FQN_SEPARATOR_CHAR
|
||||
),
|
||||
''
|
||||
);
|
||||
|
||||
setEntityId(id);
|
||||
|
||||
const versions = await getTopicVersions(id);
|
||||
|
||||
setVersionList(versions);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case EntityType.DASHBOARD: {
|
||||
const { id } = await getDashboardByFqn(
|
||||
getPartialNameFromFQN(
|
||||
entityFQN,
|
||||
['service', 'database'],
|
||||
FQN_SEPARATOR_CHAR
|
||||
),
|
||||
''
|
||||
);
|
||||
|
||||
setEntityId(id);
|
||||
|
||||
const versions = await getDashboardVersions(id);
|
||||
|
||||
setVersionList(versions);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case EntityType.PIPELINE: {
|
||||
const { id } = await getPipelineByFqn(
|
||||
getPartialNameFromFQN(
|
||||
entityFQN,
|
||||
['service', 'database'],
|
||||
FQN_SEPARATOR_CHAR
|
||||
),
|
||||
''
|
||||
);
|
||||
|
||||
setEntityId(id);
|
||||
|
||||
const versions = await getPipelineVersions(id);
|
||||
|
||||
setVersionList(versions);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case EntityType.MLMODEL: {
|
||||
const { id } = await getMlModelByFQN(
|
||||
getPartialNameFromFQN(
|
||||
entityFQN,
|
||||
['service', 'database'],
|
||||
FQN_SEPARATOR_CHAR
|
||||
),
|
||||
''
|
||||
);
|
||||
|
||||
setEntityId(id);
|
||||
|
||||
const versions = await getMlModelVersions(id);
|
||||
|
||||
setVersionList(versions);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case EntityType.CONTAINER: {
|
||||
const { id } = await getContainerByName(entityFQN, '');
|
||||
|
||||
setEntityId(id);
|
||||
|
||||
const versions = await getContainerVersions(id);
|
||||
|
||||
setVersionList(versions);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case EntityType.DASHBOARD_DATA_MODEL: {
|
||||
const { id } = await getDataModelDetailsByFQN(entityFQN, '');
|
||||
|
||||
setEntityId(id ?? '');
|
||||
|
||||
const versions = await getDataModelVersionsList(id ?? '');
|
||||
|
||||
setVersionList(versions);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} catch (err) {
|
||||
// Error
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
}
|
||||
}, [entityType, entityFQN]);
|
||||
|
||||
const fetchCurrentVersion = useCallback(
|
||||
async (id: string) => {
|
||||
setIsVersionLoading(true);
|
||||
try {
|
||||
if (viewVersionPermission) {
|
||||
switch (entityType) {
|
||||
case EntityType.TABLE: {
|
||||
const currentVersion = await getTableVersion(id, version);
|
||||
const { id } = await getTableDetailsByFQN(entityFQN, '');
|
||||
|
||||
const { owner, tags = [] } = currentVersion;
|
||||
setEntityId(id);
|
||||
|
||||
setEntityState(
|
||||
tags,
|
||||
owner,
|
||||
currentVersion,
|
||||
getEntityBreadcrumbs(currentVersion, EntityType.TABLE)
|
||||
);
|
||||
const versions = await getTableVersions(id);
|
||||
|
||||
setVersionList(versions);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case EntityType.TOPIC: {
|
||||
const currentVersion = await getTopicVersion(id, version);
|
||||
|
||||
const { owner, tags = [] } = currentVersion;
|
||||
|
||||
setEntityState(
|
||||
tags,
|
||||
owner,
|
||||
currentVersion,
|
||||
getEntityBreadcrumbs(currentVersion, EntityType.TOPIC)
|
||||
const { id } = await getTopicByFqn(
|
||||
getPartialNameFromFQN(
|
||||
entityFQN,
|
||||
['service', 'database'],
|
||||
FQN_SEPARATOR_CHAR
|
||||
),
|
||||
''
|
||||
);
|
||||
|
||||
setEntityId(id);
|
||||
|
||||
const versions = await getTopicVersions(id);
|
||||
|
||||
setVersionList(versions);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case EntityType.DASHBOARD: {
|
||||
const currentVersion = await getDashboardVersion(id, version);
|
||||
|
||||
const { owner, tags = [] } = currentVersion;
|
||||
|
||||
setEntityState(
|
||||
tags,
|
||||
owner,
|
||||
currentVersion,
|
||||
getEntityBreadcrumbs(currentVersion, EntityType.DASHBOARD)
|
||||
const { id } = await getDashboardByFqn(
|
||||
getPartialNameFromFQN(
|
||||
entityFQN,
|
||||
['service', 'database'],
|
||||
FQN_SEPARATOR_CHAR
|
||||
),
|
||||
''
|
||||
);
|
||||
|
||||
setEntityId(id);
|
||||
|
||||
const versions = await getDashboardVersions(id);
|
||||
|
||||
setVersionList(versions);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case EntityType.PIPELINE: {
|
||||
const currentVersion = await getPipelineVersion(id, version);
|
||||
|
||||
const { owner, tags = [] } = currentVersion;
|
||||
|
||||
setEntityState(
|
||||
tags,
|
||||
owner,
|
||||
currentVersion,
|
||||
getEntityBreadcrumbs(currentVersion, EntityType.PIPELINE)
|
||||
const { id } = await getPipelineByFqn(
|
||||
getPartialNameFromFQN(
|
||||
entityFQN,
|
||||
['service', 'database'],
|
||||
FQN_SEPARATOR_CHAR
|
||||
),
|
||||
''
|
||||
);
|
||||
|
||||
setEntityId(id);
|
||||
|
||||
const versions = await getPipelineVersions(id);
|
||||
|
||||
setVersionList(versions);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case EntityType.MLMODEL: {
|
||||
const currentVersion = await getMlModelVersion(id, version);
|
||||
|
||||
const { owner, tags = [] } = currentVersion;
|
||||
setEntityState(
|
||||
tags,
|
||||
owner,
|
||||
currentVersion,
|
||||
getEntityBreadcrumbs(currentVersion, EntityType.MLMODEL)
|
||||
const { id } = await getMlModelByFQN(
|
||||
getPartialNameFromFQN(
|
||||
entityFQN,
|
||||
['service', 'database'],
|
||||
FQN_SEPARATOR_CHAR
|
||||
),
|
||||
''
|
||||
);
|
||||
|
||||
setEntityId(id);
|
||||
|
||||
const versions = await getMlModelVersions(id);
|
||||
|
||||
setVersionList(versions);
|
||||
|
||||
break;
|
||||
}
|
||||
case EntityType.CONTAINER: {
|
||||
const currentVersion = await getContainerVersion(id, version);
|
||||
const { owner, tags = [] } = currentVersion;
|
||||
|
||||
setEntityState(
|
||||
tags,
|
||||
owner,
|
||||
currentVersion,
|
||||
getEntityBreadcrumbs(currentVersion, EntityType.CONTAINER)
|
||||
);
|
||||
case EntityType.CONTAINER: {
|
||||
const { id } = await getContainerByName(entityFQN, '');
|
||||
|
||||
setEntityId(id);
|
||||
|
||||
const versions = await getContainerVersions(id);
|
||||
|
||||
setVersionList(versions);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case EntityType.DASHBOARD_DATA_MODEL: {
|
||||
const currentVersion = await getDataModelVersion(id, version);
|
||||
const { id } = await getDataModelDetailsByFQN(entityFQN, '');
|
||||
|
||||
const { owner, tags = [] } = currentVersion;
|
||||
setEntityId(id ?? '');
|
||||
|
||||
setEntityState(
|
||||
tags,
|
||||
owner,
|
||||
currentVersion,
|
||||
getEntityBreadcrumbs(
|
||||
currentVersion,
|
||||
EntityType.DASHBOARD_DATA_MODEL
|
||||
)
|
||||
);
|
||||
const versions = await getDataModelVersionsList(id ?? '');
|
||||
|
||||
setVersionList(versions);
|
||||
|
||||
break;
|
||||
}
|
||||
@ -508,14 +399,143 @@ const EntityVersionPage: FunctionComponent = () => {
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
// Error
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
}
|
||||
}, [entityType, entityFQN, viewVersionPermission]);
|
||||
|
||||
const fetchCurrentVersion = useCallback(
|
||||
async (id: string) => {
|
||||
setIsVersionLoading(true);
|
||||
try {
|
||||
if (viewVersionPermission) {
|
||||
switch (entityType) {
|
||||
case EntityType.TABLE: {
|
||||
const currentVersion = await getTableVersion(id, version);
|
||||
|
||||
const { owner, tags = [] } = currentVersion;
|
||||
|
||||
setEntityState(
|
||||
tags,
|
||||
owner,
|
||||
currentVersion,
|
||||
getEntityBreadcrumbs(currentVersion, EntityType.TABLE)
|
||||
);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case EntityType.TOPIC: {
|
||||
const currentVersion = await getTopicVersion(id, version);
|
||||
|
||||
const { owner, tags = [] } = currentVersion;
|
||||
|
||||
setEntityState(
|
||||
tags,
|
||||
owner,
|
||||
currentVersion,
|
||||
getEntityBreadcrumbs(currentVersion, EntityType.TOPIC)
|
||||
);
|
||||
|
||||
break;
|
||||
}
|
||||
case EntityType.DASHBOARD: {
|
||||
const currentVersion = await getDashboardVersion(id, version);
|
||||
|
||||
const { owner, tags = [] } = currentVersion;
|
||||
|
||||
setEntityState(
|
||||
tags,
|
||||
owner,
|
||||
currentVersion,
|
||||
getEntityBreadcrumbs(currentVersion, EntityType.DASHBOARD)
|
||||
);
|
||||
|
||||
break;
|
||||
}
|
||||
case EntityType.PIPELINE: {
|
||||
const currentVersion = await getPipelineVersion(id, version);
|
||||
|
||||
const { owner, tags = [] } = currentVersion;
|
||||
|
||||
setEntityState(
|
||||
tags,
|
||||
owner,
|
||||
currentVersion,
|
||||
getEntityBreadcrumbs(currentVersion, EntityType.PIPELINE)
|
||||
);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case EntityType.MLMODEL: {
|
||||
const currentVersion = await getMlModelVersion(id, version);
|
||||
|
||||
const { owner, tags = [] } = currentVersion;
|
||||
setEntityState(
|
||||
tags,
|
||||
owner,
|
||||
currentVersion,
|
||||
getEntityBreadcrumbs(currentVersion, EntityType.MLMODEL)
|
||||
);
|
||||
|
||||
break;
|
||||
}
|
||||
case EntityType.CONTAINER: {
|
||||
const currentVersion = await getContainerVersion(id, version);
|
||||
const { owner, tags = [] } = currentVersion;
|
||||
|
||||
setEntityState(
|
||||
tags,
|
||||
owner,
|
||||
currentVersion,
|
||||
getEntityBreadcrumbs(currentVersion, EntityType.CONTAINER)
|
||||
);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case EntityType.DASHBOARD_DATA_MODEL: {
|
||||
const currentVersion = await getDataModelVersion(id, version);
|
||||
|
||||
const { owner, tags = [] } = currentVersion;
|
||||
|
||||
setEntityState(
|
||||
tags,
|
||||
owner,
|
||||
currentVersion,
|
||||
getEntityBreadcrumbs(
|
||||
currentVersion,
|
||||
EntityType.DASHBOARD_DATA_MODEL
|
||||
)
|
||||
);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
setIsVersionLoading(false);
|
||||
}
|
||||
},
|
||||
[entityType, version, setEntityState]
|
||||
[entityType, version, setEntityState, viewVersionPermission]
|
||||
);
|
||||
|
||||
const versionComponent = () => {
|
||||
if (isLoading) {
|
||||
return <Loader />;
|
||||
}
|
||||
|
||||
if (!viewVersionPermission) {
|
||||
return <ErrorPlaceHolder type={ERROR_PLACEHOLDER_TYPE.PERMISSION} />;
|
||||
}
|
||||
|
||||
switch (entityType) {
|
||||
case EntityType.TABLE: {
|
||||
return (
|
||||
@ -635,7 +655,6 @@ const EntityVersionPage: FunctionComponent = () => {
|
||||
currentVersionData={currentVersionData}
|
||||
dataModelFQN={entityFQN}
|
||||
deleted={currentVersionData.deleted}
|
||||
entityPermissions={entityPermissions}
|
||||
isVersionLoading={isVersionLoading}
|
||||
owner={owner}
|
||||
slashedDataModelName={slashedEntityName}
|
||||
@ -654,14 +673,12 @@ const EntityVersionPage: FunctionComponent = () => {
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (currentVersionData) {
|
||||
fetchEntityPermissions();
|
||||
}
|
||||
}, [currentVersionData]);
|
||||
fetchEntityPermissions();
|
||||
}, [entityFQN]);
|
||||
|
||||
useEffect(() => {
|
||||
fetchEntityVersions();
|
||||
}, [entityFQN]);
|
||||
}, [entityFQN, viewVersionPermission]);
|
||||
|
||||
useEffect(() => {
|
||||
if (entityId) {
|
||||
@ -675,7 +692,7 @@ const EntityVersionPage: FunctionComponent = () => {
|
||||
pageTitle={t('label.entity-detail-plural', {
|
||||
entity: getEntityName(currentVersionData),
|
||||
})}>
|
||||
{isLoading ? <Loader /> : versionComponent()}
|
||||
{versionComponent()}
|
||||
</PageLayoutV1>
|
||||
);
|
||||
};
|
||||
|
||||
@ -11,7 +11,8 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { act, findByText, render, screen } from '@testing-library/react';
|
||||
import { act, render, screen } from '@testing-library/react';
|
||||
import { ENTITY_PERMISSIONS } from 'mocks/Permissions.mock';
|
||||
import React from 'react';
|
||||
import { MemoryRouter } from 'react-router-dom';
|
||||
import EntityVersionPage from './EntityVersionPage.component';
|
||||
@ -97,16 +98,25 @@ jest.mock('rest/dataModelsAPI', () => ({
|
||||
.mockImplementation(() => Promise.resolve({})),
|
||||
}));
|
||||
|
||||
jest.mock('components/PermissionProvider/PermissionProvider', () => ({
|
||||
usePermissionProvider: jest.fn().mockImplementation(() => ({
|
||||
getEntityPermissionByFqn: jest
|
||||
.fn()
|
||||
.mockImplementation(() => ENTITY_PERMISSIONS),
|
||||
})),
|
||||
}));
|
||||
|
||||
describe('Test EntityVersionPage component', () => {
|
||||
it('Checks if the TableVersion component renderst if respective data pass', async () => {
|
||||
await act(async () => {
|
||||
render(<EntityVersionPage />, {
|
||||
wrapper: MemoryRouter,
|
||||
});
|
||||
const tableVersion = await screen.findByText(/TableVersion component/i);
|
||||
|
||||
expect(tableVersion).toBeInTheDocument();
|
||||
});
|
||||
|
||||
const tableVersion = await screen.findByText(/TableVersion component/i);
|
||||
|
||||
expect(tableVersion).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('Checks if the DashboardVersion component render if respective data pass', async () => {
|
||||
@ -117,17 +127,16 @@ describe('Test EntityVersionPage component', () => {
|
||||
};
|
||||
|
||||
await act(async () => {
|
||||
const { container } = render(<EntityVersionPage />, {
|
||||
render(<EntityVersionPage />, {
|
||||
wrapper: MemoryRouter,
|
||||
});
|
||||
|
||||
const DashboardVersion = await findByText(
|
||||
container,
|
||||
/DashboardVersion component/i
|
||||
);
|
||||
|
||||
expect(DashboardVersion).toBeInTheDocument();
|
||||
});
|
||||
|
||||
const DashboardVersion = await screen.findByText(
|
||||
/DashboardVersion component/i
|
||||
);
|
||||
|
||||
expect(DashboardVersion).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('Checks if the PipelineVersion component render if respective data pass', async () => {
|
||||
@ -138,17 +147,16 @@ describe('Test EntityVersionPage component', () => {
|
||||
};
|
||||
|
||||
await act(async () => {
|
||||
const { container } = render(<EntityVersionPage />, {
|
||||
render(<EntityVersionPage />, {
|
||||
wrapper: MemoryRouter,
|
||||
});
|
||||
|
||||
const PipelineVersion = await findByText(
|
||||
container,
|
||||
/PipelineVersion component/i
|
||||
);
|
||||
|
||||
expect(PipelineVersion).toBeInTheDocument();
|
||||
});
|
||||
|
||||
const PipelineVersion = await screen.findByText(
|
||||
/PipelineVersion component/i
|
||||
);
|
||||
|
||||
expect(PipelineVersion).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('Checks if the TopicVersion component render if respective data pass', async () => {
|
||||
@ -159,17 +167,14 @@ describe('Test EntityVersionPage component', () => {
|
||||
};
|
||||
|
||||
await act(async () => {
|
||||
const { container } = render(<EntityVersionPage />, {
|
||||
render(<EntityVersionPage />, {
|
||||
wrapper: MemoryRouter,
|
||||
});
|
||||
|
||||
const TopicVersion = await findByText(
|
||||
container,
|
||||
/TopicVersion component/i
|
||||
);
|
||||
|
||||
expect(TopicVersion).toBeInTheDocument();
|
||||
});
|
||||
|
||||
const TopicVersion = await screen.findByText(/TopicVersion component/i);
|
||||
|
||||
expect(TopicVersion).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('Should render the mlModel Version Component', async () => {
|
||||
@ -180,17 +185,14 @@ describe('Test EntityVersionPage component', () => {
|
||||
};
|
||||
|
||||
await act(async () => {
|
||||
const { container } = render(<EntityVersionPage />, {
|
||||
render(<EntityVersionPage />, {
|
||||
wrapper: MemoryRouter,
|
||||
});
|
||||
|
||||
const MlModelVersion = await findByText(
|
||||
container,
|
||||
/MlModelVersion component/i
|
||||
);
|
||||
|
||||
expect(MlModelVersion).toBeInTheDocument();
|
||||
});
|
||||
|
||||
const MlModelVersion = await screen.findByText(/MlModelVersion component/i);
|
||||
|
||||
expect(MlModelVersion).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('Should render the container Version Component', async () => {
|
||||
@ -201,17 +203,16 @@ describe('Test EntityVersionPage component', () => {
|
||||
};
|
||||
|
||||
await act(async () => {
|
||||
const { container } = render(<EntityVersionPage />, {
|
||||
render(<EntityVersionPage />, {
|
||||
wrapper: MemoryRouter,
|
||||
});
|
||||
|
||||
const ContainerVersion = await findByText(
|
||||
container,
|
||||
/ContainerVersion component/i
|
||||
);
|
||||
|
||||
expect(ContainerVersion).toBeInTheDocument();
|
||||
});
|
||||
|
||||
const ContainerVersion = await screen.findByText(
|
||||
/ContainerVersion component/i
|
||||
);
|
||||
|
||||
expect(ContainerVersion).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('Should render the DataModel Version Component', async () => {
|
||||
@ -222,16 +223,15 @@ describe('Test EntityVersionPage component', () => {
|
||||
};
|
||||
|
||||
await act(async () => {
|
||||
const { container } = render(<EntityVersionPage />, {
|
||||
render(<EntityVersionPage />, {
|
||||
wrapper: MemoryRouter,
|
||||
});
|
||||
|
||||
const ContainerVersion = await findByText(
|
||||
container,
|
||||
/DataModelVersion component/i
|
||||
);
|
||||
|
||||
expect(ContainerVersion).toBeInTheDocument();
|
||||
});
|
||||
|
||||
const ContainerVersion = await screen.findByText(
|
||||
/DataModelVersion component/i
|
||||
);
|
||||
|
||||
expect(ContainerVersion).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
@ -19,7 +19,7 @@ import { usePermissionProvider } from 'components/PermissionProvider/PermissionP
|
||||
import { ResourceEntity } from 'components/PermissionProvider/PermissionProvider.interface';
|
||||
import { ERROR_PLACEHOLDER_TYPE } from 'enums/common.enum';
|
||||
import { compare } from 'fast-json-patch';
|
||||
import { isEmpty, isNil, isUndefined, omitBy } from 'lodash';
|
||||
import { isEmpty, isNil, isUndefined, omitBy, toString } from 'lodash';
|
||||
import { observer } from 'mobx-react';
|
||||
import React, { useEffect, useMemo, useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
@ -58,8 +58,6 @@ const MlModelPage = () => {
|
||||
DEFAULT_ENTITY_PERMISSION
|
||||
);
|
||||
|
||||
const [currentVersion, setCurrentVersion] = useState<string>();
|
||||
|
||||
const { getEntityPermissionByFqn } = usePermissionProvider();
|
||||
|
||||
const fetchResourcePermission = async (entityFqn: string) => {
|
||||
@ -103,7 +101,6 @@ const MlModelPage = () => {
|
||||
timestamp: 0,
|
||||
id: res.id,
|
||||
});
|
||||
setCurrentVersion(res.version?.toString());
|
||||
} catch (error) {
|
||||
showErrorToast(error as AxiosError);
|
||||
} finally {
|
||||
@ -127,10 +124,10 @@ const MlModelPage = () => {
|
||||
try {
|
||||
const response = await saveUpdatedMlModelData(updatedMlModel);
|
||||
const { description, version } = response;
|
||||
setCurrentVersion(version?.toString());
|
||||
setMlModelDetail((preVDetail) => ({
|
||||
...preVDetail,
|
||||
description: description,
|
||||
description,
|
||||
version,
|
||||
}));
|
||||
} catch (error) {
|
||||
showErrorToast(error as AxiosError);
|
||||
@ -177,12 +174,12 @@ const MlModelPage = () => {
|
||||
|
||||
const onTagUpdate = async (updatedMlModel: Mlmodel) => {
|
||||
try {
|
||||
const res = await saveUpdatedMlModelData(updatedMlModel);
|
||||
const { tags, version } = await saveUpdatedMlModelData(updatedMlModel);
|
||||
setMlModelDetail((preVDetail) => ({
|
||||
...preVDetail,
|
||||
tags: sortTagsCaseInsensitive(res.tags ?? []),
|
||||
tags: sortTagsCaseInsensitive(tags ?? []),
|
||||
version: version,
|
||||
}));
|
||||
setCurrentVersion(res.version?.toString());
|
||||
} catch (error) {
|
||||
showErrorToast(
|
||||
error as AxiosError,
|
||||
@ -197,14 +194,15 @@ const MlModelPage = () => {
|
||||
updatedMlModel: Mlmodel
|
||||
): Promise<void> => {
|
||||
try {
|
||||
const res = await saveUpdatedMlModelData(updatedMlModel);
|
||||
const { displayName, owner, tags, version } =
|
||||
await saveUpdatedMlModelData(updatedMlModel);
|
||||
setMlModelDetail((preVDetail) => ({
|
||||
...preVDetail,
|
||||
displayName: res.displayName,
|
||||
owner: res.owner,
|
||||
tags: res.tags,
|
||||
displayName,
|
||||
owner,
|
||||
tags,
|
||||
version,
|
||||
}));
|
||||
setCurrentVersion(res.version?.toString());
|
||||
} catch (error) {
|
||||
showErrorToast(
|
||||
error as AxiosError,
|
||||
@ -217,12 +215,14 @@ const MlModelPage = () => {
|
||||
|
||||
const updateMlModelFeatures = async (updatedMlModel: Mlmodel) => {
|
||||
try {
|
||||
const response = await saveUpdatedMlModelData(updatedMlModel);
|
||||
const { mlFeatures, version } = await saveUpdatedMlModelData(
|
||||
updatedMlModel
|
||||
);
|
||||
setMlModelDetail((preVDetail) => ({
|
||||
...preVDetail,
|
||||
mlFeatures: response.mlFeatures,
|
||||
mlFeatures,
|
||||
version,
|
||||
}));
|
||||
setCurrentVersion(response.version?.toString());
|
||||
} catch (error) {
|
||||
showErrorToast(error as AxiosError);
|
||||
}
|
||||
@ -232,7 +232,6 @@ const MlModelPage = () => {
|
||||
try {
|
||||
const data = await saveUpdatedMlModelData(updatedMlModel);
|
||||
setMlModelDetail(data);
|
||||
setCurrentVersion(data.version?.toString());
|
||||
} catch (error) {
|
||||
showErrorToast(
|
||||
error as AxiosError,
|
||||
@ -258,7 +257,11 @@ const MlModelPage = () => {
|
||||
|
||||
const versionHandler = () => {
|
||||
history.push(
|
||||
getVersionPath(EntityType.MLMODEL, mlModelFqn, currentVersion as string)
|
||||
getVersionPath(
|
||||
EntityType.MLMODEL,
|
||||
mlModelFqn,
|
||||
toString(mlModelDetail.version)
|
||||
)
|
||||
);
|
||||
};
|
||||
|
||||
@ -293,7 +296,6 @@ const MlModelPage = () => {
|
||||
tagUpdateHandler={onTagUpdate}
|
||||
unFollowMlModelHandler={unFollowMlModel}
|
||||
updateMlModelFeatures={updateMlModelFeatures}
|
||||
version={currentVersion}
|
||||
versionHandler={versionHandler}
|
||||
onExtensionUpdate={handleExtensionUpdate}
|
||||
/>
|
||||
|
||||
@ -55,7 +55,7 @@ export const getContainers = async (args: {
|
||||
export const getContainerByName = async (
|
||||
name: string,
|
||||
fields: string | string[],
|
||||
include: Include = Include.NonDeleted
|
||||
include: Include = Include.All
|
||||
) => {
|
||||
const response = await APIClient.get<Container>(
|
||||
`containers/name/${name}?fields=${fields}`,
|
||||
|
||||
@ -24,6 +24,7 @@ import {
|
||||
diffWords,
|
||||
diffWordsWithSpace,
|
||||
} from 'diff';
|
||||
import { Column as DataModelColumn } from 'generated/entity/data/dashboardDataModel';
|
||||
import { Glossary } from 'generated/entity/data/glossary';
|
||||
import { GlossaryTerm } from 'generated/entity/data/glossaryTerm';
|
||||
import { Field } from 'generated/entity/data/topic';
|
||||
@ -652,7 +653,7 @@ export const getAllChangedEntityNames = (
|
||||
};
|
||||
|
||||
export function getColumnsDataWithVersionChanges<
|
||||
A extends TableColumn | ContainerColumn
|
||||
A extends TableColumn | ContainerColumn | DataModelColumn
|
||||
>(
|
||||
changeDescription: ChangeDescription,
|
||||
colList?: A[],
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user