Cypress: Added cypress test for update display name feature and delete service issue (#11643)

* Cypress: Added cypress test for update display name feature and delete service issue

* cypress for datamodel

* rename cypress file

* improve test for update displayName
This commit is contained in:
Shailesh Parmar 2023-05-19 10:37:40 +05:30 committed by GitHub
parent 2369c782f8
commit fc4f955b9f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 459 additions and 12 deletions

View File

@ -564,7 +564,12 @@ export const searchEntity = (term, suggestionOverly = true) => {
}
};
export const visitEntityDetailsPage = (term, serviceName, entity) => {
export const visitEntityDetailsPage = (
term,
serviceName,
entity,
dataTestId
) => {
interceptURL('GET', '/api/v1/*/name/*', 'getEntityDetails');
interceptURL(
'GET',
@ -573,7 +578,7 @@ export const visitEntityDetailsPage = (term, serviceName, entity) => {
);
interceptURL('GET', `/api/v1/search/suggest?q=*&index=*`, 'searchQuery');
interceptURL('GET', `/api/v1/search/*`, 'explorePageSearch');
const id = dataTestId ?? `${serviceName}-${term}`;
// searching term in search box
cy.get('[data-testid="searchBox"]').scrollIntoView().should('be.visible');
cy.get('[data-testid="searchBox"]').type(term);
@ -581,13 +586,9 @@ export const visitEntityDetailsPage = (term, serviceName, entity) => {
cy.get('[data-testid="suggestion-overlay"]').should('exist');
cy.get('body').then(($body) => {
// checking if requested term is available in search suggestion
if (
$body.find(
`[data-testid="${serviceName}-${term}"] [data-testid="data-name"]`
).length
) {
if ($body.find(`[data-testid="${id}"] [data-testid="data-name"]`).length) {
// if term is available in search suggestion, redirecting to entity details page
cy.get(`[data-testid="${serviceName}-${term}"] [data-testid="data-name"]`)
cy.get(`[data-testid="${id}"] [data-testid="data-name"]`)
.should('be.visible')
.first()
.click();
@ -601,7 +602,7 @@ export const visitEntityDetailsPage = (term, serviceName, entity) => {
cy.get(`[data-testid="${entity}-tab"]`).should('be.visible');
verifyResponseStatusCode('@explorePageTabSearch', 200);
cy.get(`[data-testid="${serviceName}-${term}"]`)
cy.get(`[data-testid="${id}"]`)
.scrollIntoView()
.should('be.visible')
.click();

View File

@ -0,0 +1,64 @@
/*
* 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.
*/
import { interceptURL, verifyResponseStatusCode } from './common';
export const visitServiceDetailsPage = (service, verifyHeader = true) => {
// Click on settings page
interceptURL(
'GET',
'api/v1/teams/name/Organization?fields=*',
'getSettingsPage'
);
cy.get('[data-testid="appbar-item-settings"]').should('be.visible').click();
verifyResponseStatusCode('@getSettingsPage', 200);
// Services page
interceptURL('GET', '/api/v1/services/*', 'getServices');
cy.get('.ant-menu-title-content')
.contains(service.type)
.should('be.visible')
.click();
verifyResponseStatusCode('@getServices', 200);
// click on created service
cy.get(`[data-testid="service-name-${service.name}"]`)
.should('exist')
.should('be.visible')
.click();
if (verifyHeader) {
cy.get(`[data-testid="entity-header-name"]`)
.should('exist')
.should('be.visible')
.invoke('text')
.then((text) => {
expect(text).to.equal(service.name);
});
}
verifyResponseStatusCode('@getServices', 200);
};
export const createDataWithApi = (data, token) => {
data.map(({ method, url, body }) => {
cy.request({
method,
url,
auth: {
bearer: token,
},
body,
});
});
};

View File

@ -295,6 +295,7 @@ export const SERVICE_TYPE = {
Dashboard: 'Dashboard',
Pipelines: 'Pipelines',
MLModels: 'ML Models',
Storage: 'Storages',
};
export const ENTITIES = {

View File

@ -0,0 +1,125 @@
/*
* 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.
*/
import { MYDATA_SUMMARY_OPTIONS, SERVICE_TYPE } from './constants';
export const SERVICES = {
databaseServices: {
type: SERVICE_TYPE.Database,
name: 'sample_data',
displayName: 'Sample Data',
},
messagingServices: {
type: SERVICE_TYPE.Messaging,
name: 'sample_kafka',
displayName: 'Sample Kafka',
},
dashboardServices: {
type: SERVICE_TYPE.Dashboard,
name: 'sample_looker',
displayName: 'Sample Looker',
},
pipelineServices: {
type: SERVICE_TYPE.Pipelines,
name: 'sample_airflow',
displayName: 'Sample Airflow',
},
mlmodelServices: {
type: SERVICE_TYPE.MLModels,
name: 'mlflow_svc',
displayName: 'ML Flow Service',
},
storageServices: {
type: SERVICE_TYPE.Storage,
name: 's3_storage_sample',
displayName: 'Storage Sample Service',
},
};
const DB_SERVICE = SERVICES.databaseServices.name;
const DATABASE_AND_SCHEMA = {
schema: 'shopify',
schemaDisplayName: 'Shopify Schema',
database: 'ecommerce_db',
databaseDisplayName: 'E-Commerce Database',
};
export const ENTITIES_DISPLAY_NAME = {
table: {
name: 'dim(shop)',
oldDisplayName: 'dim(shop)',
displayName: 'Dim Shop Test',
entity: MYDATA_SUMMARY_OPTIONS.tables,
serviceName: DB_SERVICE,
breadcrumb: [
DATABASE_AND_SCHEMA.schemaDisplayName,
DATABASE_AND_SCHEMA.databaseDisplayName,
SERVICES.databaseServices.displayName,
],
},
topic: {
name: 'address_book',
oldDisplayName: 'address_book',
displayName: 'Kafka Address Book',
entity: MYDATA_SUMMARY_OPTIONS.topics,
serviceName: SERVICES.messagingServices.name,
breadcrumb: [SERVICES.messagingServices.displayName],
},
dashboard: {
name: 'Customers dashboard',
oldDisplayName: 'Customers dashboard',
displayName: 'Looker Customers Dashboard',
entity: MYDATA_SUMMARY_OPTIONS.dashboards,
serviceName: SERVICES.dashboardServices.name,
breadcrumb: [SERVICES.dashboardServices.displayName],
},
pipeline: {
name: 'dim_address_etl',
oldDisplayName: 'dim_address_etl',
displayName: 'Dim Address ETL',
entity: MYDATA_SUMMARY_OPTIONS.pipelines,
serviceName: SERVICES.pipelineServices.name,
breadcrumb: [SERVICES.pipelineServices.displayName],
},
mlmodel: {
name: 'eta_predictions',
oldDisplayName: 'ETA Predictions',
displayName: 'Predictions ETA',
entity: MYDATA_SUMMARY_OPTIONS.mlmodels,
serviceName: SERVICES.mlmodelServices.name,
breadcrumb: [SERVICES.mlmodelServices.displayName],
},
container: {
name: 'departments',
oldDisplayName: 'Company departments',
displayName: 'Company Departments Test',
entity: MYDATA_SUMMARY_OPTIONS.containers,
serviceName: SERVICES.storageServices.name,
breadcrumb: [SERVICES.storageServices.displayName],
},
};
export const DASHBOARD_DATA_MODEL = {
service: SERVICES.dashboardServices,
name: 'Operations View',
displayName: 'Operations View Dashboard',
breadcrumb: [SERVICES.dashboardServices.displayName],
};
export const SCHEMA_AND_DATABASE_DISPLAY_NAME = {
...ENTITIES_DISPLAY_NAME.table,
...DATABASE_AND_SCHEMA,
schemaBreadcrumb: [
DATABASE_AND_SCHEMA.databaseDisplayName,
SERVICES.databaseServices.displayName,
],
databaseBreadcrumb: [SERVICES.databaseServices.displayName],
};

View File

@ -0,0 +1,256 @@
/*
* 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 {
interceptURL,
verifyResponseStatusCode,
visitEntityDetailsPage,
} from '../../common/common';
import { visitServiceDetailsPage } from '../../common/serviceUtils';
import { MYDATA_SUMMARY_OPTIONS } from '../../constants/constants';
import {
DASHBOARD_DATA_MODEL,
ENTITIES_DISPLAY_NAME,
SCHEMA_AND_DATABASE_DISPLAY_NAME,
SERVICES,
} from '../../constants/updateDisplayName.constant';
const updateDisplayName = (displayName, apiPath) => {
if (apiPath) {
interceptURL('PATCH', apiPath, 'patchDisplayName');
}
cy.get('[data-testid="manage-button"]')
.should('exist')
.should('be.visible')
.click();
cy.get('[data-menu-id*="delete-button"]')
.should('exist')
.should('be.visible');
cy.get('[data-testid="rename-button"]').should('be.visible').click();
cy.get('#name').should('be.visible').should('be.disabled');
cy.get('#displayName').should('be.visible').should('not.be.disabled').clear();
cy.get('.ant-modal-footer').should('contain', 'Cancel');
cy.get('[data-testid="save-button"]').should('be.visible').click();
cy.get('.ant-modal-body').should('contain', 'Display Name is required');
cy.get('#displayName').type(displayName);
cy.get('[data-testid="save-button"]').should('be.visible').click();
if (apiPath) {
verifyResponseStatusCode('@patchDisplayName', 200);
}
cy.get('[data-testid="entity-header-display-name"]').should(
'contain',
displayName
);
};
describe('Edit displayName for all the entities, services and verify breadcrumb', () => {
beforeEach(() => {
cy.login();
});
Object.entries(SERVICES).map(([serviceType, service]) => {
it(`${service.type}`, () => {
visitServiceDetailsPage(service);
updateDisplayName(
service.displayName,
`/api/v1/services/${serviceType}/*`
);
});
});
it(`dataModel`, () => {
interceptURL(
'GET',
'/api/v1/dashboard/datamodels?service=*',
'dashboardDataModel'
);
interceptURL(
'GET',
'/api/v1/dashboard/datamodels/name/*',
'dataModelDetails'
);
visitServiceDetailsPage(
{
type: DASHBOARD_DATA_MODEL.service.type,
name: DASHBOARD_DATA_MODEL.service.displayName,
},
false
);
verifyResponseStatusCode('@dashboardDataModel', 200);
cy.get('[data-testid="Data Model"]').should('be.visible').click();
cy.get('[data-testid="data-models-table"]')
.contains(DASHBOARD_DATA_MODEL.name)
.click();
verifyResponseStatusCode('@dataModelDetails', 200);
updateDisplayName(
DASHBOARD_DATA_MODEL.displayName,
`/api/v1/dashboard/datamodels/*`
);
DASHBOARD_DATA_MODEL.breadcrumb.map((value) => {
cy.get('[data-testid="breadcrumb"]').should('contain', value);
});
});
it(`database`, () => {
interceptURL('GET', 'api/v1/databases/name/*', 'database');
visitEntityDetailsPage(
SCHEMA_AND_DATABASE_DISPLAY_NAME.name,
SCHEMA_AND_DATABASE_DISPLAY_NAME.serviceName,
SCHEMA_AND_DATABASE_DISPLAY_NAME.entity
);
cy.get('[data-testid="breadcrumb"]')
.contains(SCHEMA_AND_DATABASE_DISPLAY_NAME.database)
.click();
verifyResponseStatusCode('@database', 200);
updateDisplayName(
SCHEMA_AND_DATABASE_DISPLAY_NAME.databaseDisplayName,
`/api/v1/databases/*`
);
SCHEMA_AND_DATABASE_DISPLAY_NAME.databaseBreadcrumb.map((value) => {
cy.get('[data-testid="breadcrumb"]').should('contain', value);
});
});
it(`databaseSchema`, () => {
interceptURL('GET', 'api/v1/databaseSchemas/name/*', 'databaseSchemas');
visitEntityDetailsPage(
SCHEMA_AND_DATABASE_DISPLAY_NAME.name,
SCHEMA_AND_DATABASE_DISPLAY_NAME.serviceName,
SCHEMA_AND_DATABASE_DISPLAY_NAME.entity
);
cy.get('[data-testid="breadcrumb"]')
.contains(SCHEMA_AND_DATABASE_DISPLAY_NAME.schema)
.click();
verifyResponseStatusCode('@databaseSchemas', 200);
updateDisplayName(
SCHEMA_AND_DATABASE_DISPLAY_NAME.schemaDisplayName,
`/api/v1/databaseSchemas/*`
);
SCHEMA_AND_DATABASE_DISPLAY_NAME.schemaBreadcrumb.map((value) => {
cy.get('[data-testid="breadcrumb"]').should('contain', value);
});
});
Object.values(ENTITIES_DISPLAY_NAME).map((entity) => {
it(`${entity.entity}`, () => {
visitEntityDetailsPage(entity.name, entity.serviceName, entity.entity);
updateDisplayName(entity.displayName, `/api/v1/${entity.entity}/*`);
entity.breadcrumb.map((value) => {
cy.get('[data-testid="breadcrumb"]').should('contain', value);
});
});
});
});
describe('Cleanup', () => {
beforeEach(() => {
cy.login();
});
Object.values(ENTITIES_DISPLAY_NAME).map((entity) => {
it(`${entity.entity}`, () => {
if (entity.entity === MYDATA_SUMMARY_OPTIONS.dashboards) {
visitEntityDetailsPage(
entity.displayName,
entity.serviceName,
entity.entity
);
} else {
visitEntityDetailsPage(entity.name, entity.serviceName, entity.entity);
}
updateDisplayName(entity.oldDisplayName, `/api/v1/${entity.entity}/*`);
});
});
it(`databaseSchema`, () => {
interceptURL('GET', 'api/v1/databaseSchemas/name/*', 'databaseSchemas');
visitEntityDetailsPage(
SCHEMA_AND_DATABASE_DISPLAY_NAME.name,
SCHEMA_AND_DATABASE_DISPLAY_NAME.serviceName,
SCHEMA_AND_DATABASE_DISPLAY_NAME.entity
);
cy.get('[data-testid="breadcrumb"]')
.contains(SCHEMA_AND_DATABASE_DISPLAY_NAME.schemaDisplayName)
.click();
verifyResponseStatusCode('@databaseSchemas', 200);
updateDisplayName(
SCHEMA_AND_DATABASE_DISPLAY_NAME.schema,
`/api/v1/databaseSchemas/*`
);
});
it(`database`, () => {
interceptURL('GET', 'api/v1/databases/name/*', 'database');
visitEntityDetailsPage(
SCHEMA_AND_DATABASE_DISPLAY_NAME.name,
SCHEMA_AND_DATABASE_DISPLAY_NAME.serviceName,
SCHEMA_AND_DATABASE_DISPLAY_NAME.entity
);
cy.get('[data-testid="breadcrumb"]')
.contains(SCHEMA_AND_DATABASE_DISPLAY_NAME.databaseDisplayName)
.click();
verifyResponseStatusCode('@database', 200);
updateDisplayName(
SCHEMA_AND_DATABASE_DISPLAY_NAME.database,
`/api/v1/databases/*`
);
});
it(`dataModel`, () => {
interceptURL(
'GET',
'/api/v1/dashboard/datamodels?service=*',
'dashboardDataModel'
);
interceptURL(
'GET',
'/api/v1/dashboard/datamodels/name/*',
'dataModelDetails'
);
visitServiceDetailsPage(
{
type: DASHBOARD_DATA_MODEL.service.type,
name: DASHBOARD_DATA_MODEL.service.displayName,
},
false
);
verifyResponseStatusCode('@dashboardDataModel', 200);
cy.get('[data-testid="Data Model"]').should('be.visible').click();
cy.get('[data-testid="data-models-table"]')
.contains(DASHBOARD_DATA_MODEL.name)
.click();
verifyResponseStatusCode('@dataModelDetails', 200);
updateDisplayName(
DASHBOARD_DATA_MODEL.displayName,
`/api/v1/dashboard/datamodels/*`
);
});
Object.entries(SERVICES).map(([serviceType, service]) => {
it(`${service.type}`, () => {
visitServiceDetailsPage(
{
type: service.type,
name: service.displayName,
},
false
);
updateDisplayName(service.name, `/api/v1/services/${serviceType}/*`);
});
});
});

View File

@ -68,7 +68,7 @@ const EntityNameModal: React.FC<EntityNameModalProps> = ({
onCancel={onCancel}>
<Form form={form} layout="vertical" onFinish={handleSave}>
<Form.Item
label={`${t('label.name')}:`}
label={t('label.name')}
name="name"
rules={[
{
@ -86,13 +86,13 @@ const EntityNameModal: React.FC<EntityNameModalProps> = ({
/>
</Form.Item>
<Form.Item
label={`${t('label.display-name')}:`}
label={t('label.display-name')}
name="displayName"
rules={[
{
required: true,
message: `${t('label.field-required', {
field: t('label.name'),
field: t('label.display-name'),
})}`,
},
]}>