mirror of
https://github.com/open-metadata/OpenMetadata.git
synced 2025-08-28 02:46:09 +00:00
UI: Added cypress test for Data quality and profiler (#7463)
* added initial cypress test for profiler * added profiler ingestion workflow * added data-testid for no profiler placeholder * added create test suite and test case cypress * added edit and delete flow for table test case * added test-suite delete test * added cypress for add column test case * added delete and edit cypress test for column test * fixed delete service cypress issue * removed only keyword
This commit is contained in:
parent
e6de43b081
commit
f52f6eccd8
@ -30,7 +30,13 @@ export const verifyResponseStatusCode = (alias, responseCode) => {
|
|||||||
cy.wait(alias).its('response.statusCode').should('eq', responseCode);
|
cy.wait(alias).its('response.statusCode').should('eq', responseCode);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const handleIngestionRetry = (type, testIngestionButton, count = 0) => {
|
export const handleIngestionRetry = (
|
||||||
|
type,
|
||||||
|
testIngestionButton,
|
||||||
|
count = 0,
|
||||||
|
ingestionType = 'metadata'
|
||||||
|
) => {
|
||||||
|
const rowIndex = ingestionType === 'metadata' ? 1 : 2;
|
||||||
// ingestions page
|
// ingestions page
|
||||||
const retryTimes = 25;
|
const retryTimes = 25;
|
||||||
let retryCount = count;
|
let retryCount = count;
|
||||||
@ -38,7 +44,7 @@ export const handleIngestionRetry = (type, testIngestionButton, count = 0) => {
|
|||||||
cy.get('[data-testid="Ingestions"]').should('be.visible');
|
cy.get('[data-testid="Ingestions"]').should('be.visible');
|
||||||
cy.get('[data-testid="Ingestions"] >> [data-testid="filter-count"]').should(
|
cy.get('[data-testid="Ingestions"] >> [data-testid="filter-count"]').should(
|
||||||
'have.text',
|
'have.text',
|
||||||
1
|
rowIndex
|
||||||
);
|
);
|
||||||
// click on the tab only for the first time
|
// click on the tab only for the first time
|
||||||
if (retryCount === 0) {
|
if (retryCount === 0) {
|
||||||
@ -52,25 +58,45 @@ export const handleIngestionRetry = (type, testIngestionButton, count = 0) => {
|
|||||||
testIngestionsTab();
|
testIngestionsTab();
|
||||||
retryCount++;
|
retryCount++;
|
||||||
// the latest run should be success
|
// the latest run should be success
|
||||||
cy.get('.tableBody-row > :nth-child(4)').then(($ingestionStatus) => {
|
cy.get(`.tableBody > :nth-child(${rowIndex}) > :nth-child(4)`).then(
|
||||||
if (
|
($ingestionStatus) => {
|
||||||
($ingestionStatus.text() === 'Running' ||
|
if (
|
||||||
$ingestionStatus.text() === 'Queued') &&
|
($ingestionStatus.text() === 'Running' ||
|
||||||
retryCount <= retryTimes
|
$ingestionStatus.text() === 'Queued') &&
|
||||||
) {
|
retryCount <= retryTimes
|
||||||
// retry after waiting for 20 seconds
|
) {
|
||||||
cy.wait(20000);
|
// retry after waiting for 20 seconds
|
||||||
cy.reload();
|
cy.wait(20000);
|
||||||
checkSuccessState();
|
cy.reload();
|
||||||
} else {
|
checkSuccessState();
|
||||||
cy.get('.tableBody-row > :nth-child(4)').should('have.text', 'Success');
|
} else {
|
||||||
|
cy.get(`.tableBody > :nth-child(${rowIndex}) > :nth-child(4)`).should(
|
||||||
|
'have.text',
|
||||||
|
'Success'
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
checkSuccessState();
|
checkSuccessState();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const scheduleIngestion = () => {
|
||||||
|
// Schedule & Deploy
|
||||||
|
cy.contains('Schedule for Ingestion').should('be.visible');
|
||||||
|
cy.get('[data-testid="ingestion-type"]').should('be.visible').select('hour');
|
||||||
|
cy.get('[data-testid="deploy-button"]').should('be.visible').click();
|
||||||
|
|
||||||
|
// check success
|
||||||
|
cy.get('[data-testid="success-line"]', { timeout: 15000 }).should(
|
||||||
|
'be.visible'
|
||||||
|
);
|
||||||
|
cy.contains('has been created and deployed successfully').should(
|
||||||
|
'be.visible'
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
//Storing the created service name and the type of service for later use
|
//Storing the created service name and the type of service for later use
|
||||||
|
|
||||||
export const testServiceCreationAndIngestion = (
|
export const testServiceCreationAndIngestion = (
|
||||||
@ -142,19 +168,9 @@ export const testServiceCreationAndIngestion = (
|
|||||||
cy.get('[data-testid="submit-btn"]').should('be.visible').click();
|
cy.get('[data-testid="submit-btn"]').should('be.visible').click();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Schedule & Deploy
|
scheduleIngestion();
|
||||||
cy.contains('Schedule for Ingestion').should('be.visible');
|
|
||||||
cy.get('[data-testid="ingestion-type"]').should('be.visible').select('hour');
|
|
||||||
cy.get('[data-testid="deploy-button"]').should('be.visible').click();
|
|
||||||
|
|
||||||
// check success
|
|
||||||
cy.get('[data-testid="success-line"]', { timeout: 15000 }).should(
|
|
||||||
'be.visible'
|
|
||||||
);
|
|
||||||
cy.contains(`${serviceName}_metadata`).should('be.visible');
|
cy.contains(`${serviceName}_metadata`).should('be.visible');
|
||||||
cy.contains('has been created and deployed successfully').should(
|
|
||||||
'be.visible'
|
|
||||||
);
|
|
||||||
// On the Right panel
|
// On the Right panel
|
||||||
cy.contains('Metadata Ingestion Added & Deployed Successfully').should(
|
cy.contains('Metadata Ingestion Added & Deployed Successfully').should(
|
||||||
'be.visible'
|
'be.visible'
|
||||||
@ -216,17 +232,22 @@ export const deleteCreatedService = (typeOfService, service_Name) => {
|
|||||||
cy.get('[data-testid="confirmation-text-input"]')
|
cy.get('[data-testid="confirmation-text-input"]')
|
||||||
.should('be.visible')
|
.should('be.visible')
|
||||||
.type('DELETE');
|
.type('DELETE');
|
||||||
|
interceptURL(
|
||||||
interceptURL('GET', '/api/v1/*', 'homePage');
|
'DELETE',
|
||||||
|
'/api/v1/services/*/*?hardDelete=true&recursive=true',
|
||||||
|
'deleteService'
|
||||||
|
);
|
||||||
|
interceptURL(
|
||||||
|
'GET',
|
||||||
|
'/api/v1/services/*/name/*?fields=owner',
|
||||||
|
'serviceDetails'
|
||||||
|
);
|
||||||
|
|
||||||
cy.get('[data-testid="confirm-button"]').should('be.visible').click();
|
cy.get('[data-testid="confirm-button"]').should('be.visible').click();
|
||||||
|
verifyResponseStatusCode('@deleteService', 200);
|
||||||
cy.get('.Toastify__toast-body')
|
cy.reload();
|
||||||
.should('exist')
|
verifyResponseStatusCode('@serviceDetails', 404);
|
||||||
.should('be.visible')
|
cy.contains(`instance for ${service_Name} not found`);
|
||||||
.should('have.text', `${typeOfService} Service deleted successfully!`);
|
|
||||||
cy.url().should('eq', 'http://localhost:8585/my-data');
|
|
||||||
verifyResponseStatusCode('@homePage', 200);
|
|
||||||
//Checking if the service got deleted successfully
|
//Checking if the service got deleted successfully
|
||||||
//Click on settings page
|
//Click on settings page
|
||||||
cy.get('[data-testid="appbar-item-settings"]').should('be.visible').click();
|
cy.get('[data-testid="appbar-item-settings"]').should('be.visible').click();
|
||||||
@ -362,10 +383,12 @@ export const visitEntityTab = (id) => {
|
|||||||
* Search for entities through the search bar
|
* Search for entities through the search bar
|
||||||
* @param {string} term Entity name
|
* @param {string} term Entity name
|
||||||
*/
|
*/
|
||||||
export const searchEntity = (term) => {
|
export const searchEntity = (term, suggestionOverly = true) => {
|
||||||
cy.get('[data-testid="searchBox"]').scrollIntoView().should('be.visible');
|
cy.get('[data-testid="searchBox"]').scrollIntoView().should('be.visible');
|
||||||
cy.get('[data-testid="searchBox"]').type(`${term}{enter}`);
|
cy.get('[data-testid="searchBox"]').type(`${term}{enter}`);
|
||||||
cy.get('[data-testid="suggestion-overlay"]').click(1, 1);
|
if (suggestionOverly) {
|
||||||
|
cy.get('[data-testid="suggestion-overlay"]').click(1, 1);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// add new tag to entity and its table
|
// add new tag to entity and its table
|
||||||
|
@ -13,6 +13,8 @@
|
|||||||
|
|
||||||
import { uuid } from '../common/common';
|
import { uuid } from '../common/common';
|
||||||
|
|
||||||
|
const id = uuid();
|
||||||
|
|
||||||
export const MYDATA_SUMMARY_OPTIONS = {
|
export const MYDATA_SUMMARY_OPTIONS = {
|
||||||
tables: 'tables',
|
tables: 'tables',
|
||||||
topics: 'topics',
|
topics: 'topics',
|
||||||
@ -81,6 +83,7 @@ export const RECENT_SEARCH_TITLE = 'Recent Search Terms';
|
|||||||
export const RECENT_VIEW_TITLE = 'Recent Views';
|
export const RECENT_VIEW_TITLE = 'Recent Views';
|
||||||
export const MY_DATA_TITLE = 'My Data';
|
export const MY_DATA_TITLE = 'My Data';
|
||||||
export const FOLLOWING_TITLE = 'Following';
|
export const FOLLOWING_TITLE = 'Following';
|
||||||
|
export const TEAM_ENTITY = 'team_entity';
|
||||||
|
|
||||||
export const NO_SEARCHED_TERMS = 'No searched terms';
|
export const NO_SEARCHED_TERMS = 'No searched terms';
|
||||||
export const DELETE_TERM = 'DELETE';
|
export const DELETE_TERM = 'DELETE';
|
||||||
@ -92,6 +95,25 @@ export const TEAMS = {
|
|||||||
Data_Platform: { name: 'Data_Platform', users: 16 },
|
Data_Platform: { name: 'Data_Platform', users: 16 },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const NEW_TEST_SUITE = {
|
||||||
|
name: `mysql_matrix`,
|
||||||
|
description: 'mysql critical matrix',
|
||||||
|
};
|
||||||
|
|
||||||
|
export const NEW_TABLE_TEST_CASE = {
|
||||||
|
type: 'TableColumnNameToExist',
|
||||||
|
field: 'id',
|
||||||
|
description: 'New table test case for TableColumnNameToExist',
|
||||||
|
};
|
||||||
|
|
||||||
|
export const NEW_COLUMN_TEST_CASE = {
|
||||||
|
column: 'id',
|
||||||
|
type: 'columnValueLengthsToBeBetween',
|
||||||
|
min: 3,
|
||||||
|
max: 6,
|
||||||
|
description: 'New table test case for columnValueLengthsToBeBetween',
|
||||||
|
};
|
||||||
|
|
||||||
export const NEW_TEAM = {
|
export const NEW_TEAM = {
|
||||||
team_1: {
|
team_1: {
|
||||||
name: 'account',
|
name: 'account',
|
||||||
@ -104,7 +126,7 @@ export const NEW_TEAM = {
|
|||||||
description: 'Service department',
|
description: 'Service department',
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
const id = uuid();
|
|
||||||
export const NEW_USER = {
|
export const NEW_USER = {
|
||||||
email: `test_${id}@gmail.com`,
|
email: `test_${id}@gmail.com`,
|
||||||
display_name: `Test user ${id}`,
|
display_name: `Test user ${id}`,
|
||||||
|
@ -0,0 +1,388 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2022 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 { descriptionBox, goToAddNewServicePage, handleIngestionRetry, interceptURL, scheduleIngestion, searchEntity, testServiceCreationAndIngestion, uuid, verifyResponseStatusCode } from '../../common/common';
|
||||||
|
import { DELETE_TERM, NEW_COLUMN_TEST_CASE, NEW_TABLE_TEST_CASE, NEW_TEST_SUITE, SERVICE_TYPE, TEAM_ENTITY } from '../../constants/constants';
|
||||||
|
|
||||||
|
const serviceType = 'Mysql';
|
||||||
|
const serviceName = `${serviceType}-ct-test-${uuid()}`;
|
||||||
|
const columnTestName = `${NEW_COLUMN_TEST_CASE.column}_${NEW_COLUMN_TEST_CASE.type}`;
|
||||||
|
|
||||||
|
const goToProfilerTab = () => {
|
||||||
|
// click on the 1st result and go to entity details page and follow the entity
|
||||||
|
interceptURL('GET', '/api/v1/feed*', 'getEntityDetails');
|
||||||
|
cy.get('[data-testid="table-link"]')
|
||||||
|
.first()
|
||||||
|
.contains(TEAM_ENTITY, { matchCase: false })
|
||||||
|
.click();
|
||||||
|
verifyResponseStatusCode('@getEntityDetails', 200);
|
||||||
|
|
||||||
|
cy.get('[data-testid="Profiler & Data Quality"]')
|
||||||
|
.should('be.visible')
|
||||||
|
.click();
|
||||||
|
};
|
||||||
|
|
||||||
|
describe('Data Quality and Profiler should work properly', () => {
|
||||||
|
it('Add and ingest mysql data', () => {
|
||||||
|
goToAddNewServicePage(SERVICE_TYPE.Database);
|
||||||
|
const connectionInput = () => {
|
||||||
|
cy.get('#root_username').type('openmetadata_user');
|
||||||
|
cy.get('#root_password').type('openmetadata_password');
|
||||||
|
cy.get('#root_hostPort').type('mysql:3306');
|
||||||
|
cy.get('#root_databaseSchema').type('openmetadata_db');
|
||||||
|
};
|
||||||
|
|
||||||
|
const addIngestionInput = () => {
|
||||||
|
cy.get('[data-testid="schema-filter-pattern-checkbox"]').check();
|
||||||
|
cy.get('[data-testid="filter-pattern-includes-schema"]')
|
||||||
|
.should('be.visible')
|
||||||
|
.type('openmetadata_db');
|
||||||
|
};
|
||||||
|
|
||||||
|
testServiceCreationAndIngestion(
|
||||||
|
serviceType,
|
||||||
|
connectionInput,
|
||||||
|
addIngestionInput,
|
||||||
|
serviceName
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Add Profiler ingestion', () => {
|
||||||
|
cy.goToHomePage();
|
||||||
|
searchEntity(TEAM_ENTITY);
|
||||||
|
goToProfilerTab();
|
||||||
|
|
||||||
|
cy.get('[data-testid="no-profiler-placeholder"]').should('be.visible');
|
||||||
|
|
||||||
|
cy.clickOnLogo();
|
||||||
|
|
||||||
|
cy.get('[data-testid="service-summary"] [data-testid="service"]')
|
||||||
|
.should('be.visible')
|
||||||
|
.click();
|
||||||
|
cy.intercept('/api/v1/services/ingestionPipelines?*').as('ingestionData');
|
||||||
|
cy.get(`[data-testid="service-name-${serviceName}"]`)
|
||||||
|
.should('exist')
|
||||||
|
.click();
|
||||||
|
cy.get('[data-testid="tabs"]').should('exist');
|
||||||
|
cy.wait('@ingestionData');
|
||||||
|
cy.get('[data-testid="Ingestions"]')
|
||||||
|
.scrollIntoView()
|
||||||
|
.should('be.visible')
|
||||||
|
.click();
|
||||||
|
cy.get('[data-testid="ingestion-details-container"]').should('exist');
|
||||||
|
cy.get('[data-testid="add-new-ingestion-button"]')
|
||||||
|
.should('be.visible')
|
||||||
|
.click();
|
||||||
|
cy.get('#menu-item-1')
|
||||||
|
.scrollIntoView()
|
||||||
|
.contains('Profiler Ingestion')
|
||||||
|
.click();
|
||||||
|
cy.get('[data-testid="next-button"]')
|
||||||
|
.scrollIntoView()
|
||||||
|
.should('be.visible')
|
||||||
|
.click();
|
||||||
|
|
||||||
|
scheduleIngestion();
|
||||||
|
|
||||||
|
// wait for ingestion to run
|
||||||
|
cy.clock();
|
||||||
|
cy.wait(10000);
|
||||||
|
|
||||||
|
cy.get('[data-testid="view-service-button"]')
|
||||||
|
.scrollIntoView()
|
||||||
|
.should('be.visible')
|
||||||
|
.click();
|
||||||
|
|
||||||
|
handleIngestionRetry('database', true, 0, 'profiler');
|
||||||
|
|
||||||
|
// check if profiler is ingested properly
|
||||||
|
searchEntity(TEAM_ENTITY, false);
|
||||||
|
goToProfilerTab();
|
||||||
|
cy.get('[data-testid="no-profiler-placeholder"]').should('not.exist');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Add table test case with new test suite', () => {
|
||||||
|
cy.goToHomePage();
|
||||||
|
|
||||||
|
searchEntity(TEAM_ENTITY);
|
||||||
|
goToProfilerTab();
|
||||||
|
|
||||||
|
cy.get('[data-testid="profiler-add-table-test-btn"]')
|
||||||
|
.scrollIntoView()
|
||||||
|
.should('be.visible')
|
||||||
|
.click();
|
||||||
|
|
||||||
|
cy.get('[data-testid="create-new-test-suite"]')
|
||||||
|
.should('be.visible')
|
||||||
|
.click();
|
||||||
|
|
||||||
|
// creating new test suite
|
||||||
|
cy.get('[data-testid="new-test-title"]')
|
||||||
|
.should('be.visible')
|
||||||
|
.contains('New Test Suite');
|
||||||
|
cy.get('[data-testid="test-suite-name"]')
|
||||||
|
.scrollIntoView()
|
||||||
|
.type(NEW_TEST_SUITE.name);
|
||||||
|
cy.get(descriptionBox).scrollIntoView().type(NEW_TEST_SUITE.description);
|
||||||
|
cy.get('[data-testid="next-button"]').scrollIntoView().click();
|
||||||
|
|
||||||
|
// creating new test case
|
||||||
|
cy.get('#tableTestForm_testTypeId').scrollIntoView().click();
|
||||||
|
cy.contains(NEW_TABLE_TEST_CASE.type).should('be.visible').click();
|
||||||
|
cy.get('#tableTestForm_params_columnName')
|
||||||
|
.should('be.visible')
|
||||||
|
.type(NEW_TABLE_TEST_CASE.field);
|
||||||
|
cy.get(descriptionBox)
|
||||||
|
.scrollIntoView()
|
||||||
|
.type(NEW_TABLE_TEST_CASE.description);
|
||||||
|
|
||||||
|
cy.get('[data-testid="submit-test"]')
|
||||||
|
.scrollIntoView()
|
||||||
|
.should('be.visible')
|
||||||
|
.click();
|
||||||
|
|
||||||
|
cy.get('[data-testid="success-line"]').should('be.visible');
|
||||||
|
cy.get('[data-testid="add-ingestion-button"]').should('be.visible').click();
|
||||||
|
scheduleIngestion();
|
||||||
|
|
||||||
|
cy.get('[data-testid="success-line"]').should('be.visible');
|
||||||
|
|
||||||
|
// wait for ingestion to run
|
||||||
|
cy.clock();
|
||||||
|
cy.wait(10000);
|
||||||
|
|
||||||
|
cy.get('[data-testid="view-service-button"]')
|
||||||
|
.should('be.visible')
|
||||||
|
.click({ force: true });
|
||||||
|
|
||||||
|
cy.contains(`${TEAM_ENTITY}_${NEW_TABLE_TEST_CASE.type}`).should(
|
||||||
|
'be.visible'
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Edit Test Case should work properly', () => {
|
||||||
|
const testName = `${TEAM_ENTITY}_${NEW_TABLE_TEST_CASE.type}`;
|
||||||
|
cy.goToHomePage();
|
||||||
|
|
||||||
|
searchEntity(TEAM_ENTITY);
|
||||||
|
goToProfilerTab();
|
||||||
|
|
||||||
|
cy.get('[data-testid="profiler-switch"] > :nth-child(2)')
|
||||||
|
.contains('Data Quality')
|
||||||
|
.should('be.visible')
|
||||||
|
.click();
|
||||||
|
|
||||||
|
cy.get(`[data-testid="${testName}"]`).should('be.visible');
|
||||||
|
cy.get(`[data-testid="edit-${testName}"]`).should('be.visible').click();
|
||||||
|
cy.get('#tableTestForm_params_columnName')
|
||||||
|
.scrollIntoView()
|
||||||
|
.clear()
|
||||||
|
.wait(200)
|
||||||
|
.type('test');
|
||||||
|
interceptURL('PATCH', '/api/v1/testCase/*', 'updateTest');
|
||||||
|
cy.get('.ant-modal-footer').contains('Submit').click();
|
||||||
|
verifyResponseStatusCode('@updateTest', 200);
|
||||||
|
cy.get('.Toastify__toast-body')
|
||||||
|
.contains('Test case updated successfully!')
|
||||||
|
.should('be.visible')
|
||||||
|
.wait(200);
|
||||||
|
cy.get(`[data-testid="${testName}"]`).should('be.visible').click();
|
||||||
|
cy.contains('columnName: test').scrollIntoView().should('exist');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Delete Test Case should work properly', () => {
|
||||||
|
const testName = `${TEAM_ENTITY}_${NEW_TABLE_TEST_CASE.type}`;
|
||||||
|
cy.goToHomePage();
|
||||||
|
|
||||||
|
searchEntity(TEAM_ENTITY);
|
||||||
|
goToProfilerTab();
|
||||||
|
|
||||||
|
cy.get('[data-testid="profiler-switch"] > :nth-child(2)')
|
||||||
|
.contains('Data Quality')
|
||||||
|
.should('be.visible')
|
||||||
|
.click();
|
||||||
|
|
||||||
|
cy.get(`[data-testid="${testName}"]`).should('be.visible');
|
||||||
|
cy.get(`[data-testid="delete-${testName}"]`).should('be.visible').click();
|
||||||
|
cy.get('[data-testid="hard-delete-option"]').should('be.visible').click();
|
||||||
|
cy.get('[data-testid="confirmation-text-input"]')
|
||||||
|
.should('be.visible')
|
||||||
|
.type(DELETE_TERM);
|
||||||
|
interceptURL(
|
||||||
|
'DELETE',
|
||||||
|
'/api/v1/testCase/*?hardDelete=true&recursive=false',
|
||||||
|
'deleteTest'
|
||||||
|
);
|
||||||
|
interceptURL('GET', '/api/v1/testCase?*', 'getTestCase');
|
||||||
|
cy.get('[data-testid="confirm-button"]')
|
||||||
|
.should('be.visible')
|
||||||
|
.should('not.be.disabled')
|
||||||
|
.click();
|
||||||
|
verifyResponseStatusCode('@deleteTest', 200);
|
||||||
|
verifyResponseStatusCode('@getTestCase', 200);
|
||||||
|
cy.get('.Toastify__toast-body')
|
||||||
|
.contains('Test Case deleted successfully!')
|
||||||
|
.should('be.visible')
|
||||||
|
.wait(200);
|
||||||
|
cy.get('table').contains('No Data').should('be.visible');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Add Column test case should work properly', () => {
|
||||||
|
cy.goToHomePage();
|
||||||
|
searchEntity(TEAM_ENTITY);
|
||||||
|
goToProfilerTab();
|
||||||
|
cy.get('[data-testid="add-test-id"]')
|
||||||
|
.scrollIntoView()
|
||||||
|
.should('be.visible')
|
||||||
|
.click();
|
||||||
|
|
||||||
|
// selecting existing test suite
|
||||||
|
cy.get('#selectTestSuite_testSuiteId').should('exist').click();
|
||||||
|
cy.contains(NEW_TEST_SUITE.name).should('be.visible').click();
|
||||||
|
cy.get('[data-testid="next-button"]')
|
||||||
|
.scrollIntoView()
|
||||||
|
.should('be.visible')
|
||||||
|
.click();
|
||||||
|
|
||||||
|
// creating new test case
|
||||||
|
cy.get('#tableTestForm_testTypeId').scrollIntoView().click();
|
||||||
|
cy.get(`[title="${NEW_COLUMN_TEST_CASE.type}"]`)
|
||||||
|
.scrollIntoView()
|
||||||
|
.should('be.visible')
|
||||||
|
.click();
|
||||||
|
cy.get('#tableTestForm_params_minLength')
|
||||||
|
.scrollIntoView()
|
||||||
|
.should('be.visible')
|
||||||
|
.type(NEW_COLUMN_TEST_CASE.min);
|
||||||
|
cy.get('#tableTestForm_params_maxLength')
|
||||||
|
.scrollIntoView()
|
||||||
|
.should('be.visible')
|
||||||
|
.type(NEW_COLUMN_TEST_CASE.max);
|
||||||
|
cy.get(descriptionBox)
|
||||||
|
.scrollIntoView()
|
||||||
|
.type(NEW_COLUMN_TEST_CASE.description);
|
||||||
|
|
||||||
|
cy.get('[data-testid="submit-test"]')
|
||||||
|
.scrollIntoView()
|
||||||
|
.should('be.visible')
|
||||||
|
.click();
|
||||||
|
|
||||||
|
cy.get('[data-testid="success-line"]')
|
||||||
|
.contains(
|
||||||
|
'has been created successfully. This will be picked up in the next run.'
|
||||||
|
)
|
||||||
|
.should('be.visible');
|
||||||
|
cy.get('[data-testid="view-service-button"]').scrollIntoView().click();
|
||||||
|
|
||||||
|
cy.get('[data-row-key="id_columnValueLengthsToBeBetween"]').should(
|
||||||
|
'be.visible'
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Edit column test case should work properly', () => {
|
||||||
|
cy.goToHomePage();
|
||||||
|
searchEntity(TEAM_ENTITY);
|
||||||
|
interceptURL('GET', '/api/v1/testCase?*', 'testCase');
|
||||||
|
goToProfilerTab();
|
||||||
|
verifyResponseStatusCode('@testCase', 200);
|
||||||
|
cy.get('[data-testid="id-test-count"]').should('be.visible').click();
|
||||||
|
cy.get(`[data-testid="${columnTestName}"]`).should('be.visible');
|
||||||
|
cy.get(`[data-testid="edit-${columnTestName}"]`)
|
||||||
|
.should('be.visible')
|
||||||
|
.click();
|
||||||
|
cy.get('#tableTestForm_params_minLength')
|
||||||
|
.scrollIntoView()
|
||||||
|
.should('be.visible')
|
||||||
|
.clear()
|
||||||
|
.type(4);
|
||||||
|
interceptURL('PATCH', '/api/v1/testCase/*', 'updateTest');
|
||||||
|
cy.get('.ant-modal-footer').contains('Submit').click();
|
||||||
|
verifyResponseStatusCode('@updateTest', 200);
|
||||||
|
cy.get('.Toastify__toast-body')
|
||||||
|
.contains('Test case updated successfully!')
|
||||||
|
.should('be.visible')
|
||||||
|
.wait(200);
|
||||||
|
cy.get(`[data-testid="${columnTestName}"]`).should('be.visible').click();
|
||||||
|
cy.contains('minLength: 4').scrollIntoView().should('exist');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Delete Column Test Case should work properly', () => {
|
||||||
|
cy.goToHomePage();
|
||||||
|
searchEntity(TEAM_ENTITY);
|
||||||
|
interceptURL('GET', '/api/v1/testCase?*', 'testCase');
|
||||||
|
goToProfilerTab();
|
||||||
|
verifyResponseStatusCode('@testCase', 200);
|
||||||
|
cy.get('[data-testid="id-test-count"]').should('be.visible').click();
|
||||||
|
|
||||||
|
cy.get(`[data-testid="${columnTestName}"]`).should('be.visible');
|
||||||
|
cy.get(`[data-testid="delete-${columnTestName}"]`)
|
||||||
|
.should('be.visible')
|
||||||
|
.click();
|
||||||
|
cy.get('[data-testid="hard-delete-option"]').should('be.visible').click();
|
||||||
|
cy.get('[data-testid="confirmation-text-input"]')
|
||||||
|
.should('be.visible')
|
||||||
|
.type(DELETE_TERM);
|
||||||
|
interceptURL(
|
||||||
|
'DELETE',
|
||||||
|
'/api/v1/testCase/*?hardDelete=true&recursive=false',
|
||||||
|
'deleteTest'
|
||||||
|
);
|
||||||
|
interceptURL('GET', '/api/v1/testCase?*', 'getTestCase');
|
||||||
|
cy.get('[data-testid="confirm-button"]')
|
||||||
|
.should('be.visible')
|
||||||
|
.should('not.be.disabled')
|
||||||
|
.click();
|
||||||
|
verifyResponseStatusCode('@deleteTest', 200);
|
||||||
|
verifyResponseStatusCode('@getTestCase', 200);
|
||||||
|
cy.get('.Toastify__toast-body')
|
||||||
|
.contains('Test Case deleted successfully!')
|
||||||
|
.should('be.visible')
|
||||||
|
.wait(200);
|
||||||
|
cy.get('table').contains('No Data').should('be.visible');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Delete Test suite should work properly', () => {
|
||||||
|
cy.goToHomePage();
|
||||||
|
cy.get('[data-testid="appbar-item-settings"]').should('be.visible').click();
|
||||||
|
cy.get('[data-testid="global-setting-left-panel"]')
|
||||||
|
.contains('Test Suite')
|
||||||
|
.scrollIntoView()
|
||||||
|
.should('be.visible')
|
||||||
|
.click();
|
||||||
|
cy.get(`[data-row-key="${NEW_TEST_SUITE.name}"] > :nth-child(1) > a`)
|
||||||
|
.contains(NEW_TEST_SUITE.name)
|
||||||
|
.should('be.visible')
|
||||||
|
.click();
|
||||||
|
cy.get('[data-testid="test-suite-delete"]').should('be.visible').click();
|
||||||
|
cy.get('[data-testid="hard-delete-option"]').should('be.visible').click();
|
||||||
|
cy.get('[data-testid="confirmation-text-input"]')
|
||||||
|
.should('be.visible')
|
||||||
|
.type(DELETE_TERM);
|
||||||
|
interceptURL(
|
||||||
|
'DELETE',
|
||||||
|
'/api/v1/testSuite/*?hardDelete=true&recursive=true',
|
||||||
|
'deleteTestSuite'
|
||||||
|
);
|
||||||
|
cy.get('[data-testid="confirm-button"]')
|
||||||
|
.should('be.visible')
|
||||||
|
.should('not.be.disabled')
|
||||||
|
.click();
|
||||||
|
verifyResponseStatusCode('@deleteTestSuite', 200);
|
||||||
|
cy.get('.Toastify__toast-body')
|
||||||
|
.contains('Test Suite deleted successfully!')
|
||||||
|
.should('be.visible')
|
||||||
|
.wait(200);
|
||||||
|
});
|
||||||
|
});
|
@ -73,11 +73,10 @@ Cypress.Commands.add('clickOnLogo', () => {
|
|||||||
cy.get('#openmetadata_logo > [data-testid="image"]').click();
|
cy.get('#openmetadata_logo > [data-testid="image"]').click();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const resizeObserverLoopErrRe = /^[^(ResizeObserver loop limit exceeded)]/;
|
||||||
const resizeObserverLoopErrRe = /^[^(ResizeObserver loop limit exceeded)]/
|
|
||||||
Cypress.on('uncaught:exception', (err) => {
|
Cypress.on('uncaught:exception', (err) => {
|
||||||
/* returning false here prevents Cypress from failing the test */
|
/* returning false here prevents Cypress from failing the test */
|
||||||
if (resizeObserverLoopErrRe.test(err.message)) {
|
if (resizeObserverLoopErrRe.test(err.message)) {
|
||||||
return false
|
return false;
|
||||||
}
|
}
|
||||||
})
|
});
|
||||||
|
@ -202,6 +202,7 @@ const EditTestCaseModal: React.FC<EditTestCaseModalProps> = ({
|
|||||||
form.resetFields();
|
form.resetFields();
|
||||||
onCancel();
|
onCancel();
|
||||||
}}
|
}}
|
||||||
|
okText="Submit"
|
||||||
title={`Edit ${testCase?.name}`}
|
title={`Edit ${testCase?.name}`}
|
||||||
visible={visible}
|
visible={visible}
|
||||||
onCancel={onCancel}
|
onCancel={onCancel}
|
||||||
|
@ -181,7 +181,7 @@ const TestSuiteIngestion: React.FC<TestSuiteIngestionProps> = ({
|
|||||||
<Typography.Paragraph
|
<Typography.Paragraph
|
||||||
className="tw-heading tw-text-base"
|
className="tw-heading tw-text-base"
|
||||||
data-testid="header">
|
data-testid="header">
|
||||||
Schedule Ingestion
|
Schedule for Ingestion
|
||||||
</Typography.Paragraph>
|
</Typography.Paragraph>
|
||||||
</Col>
|
</Col>
|
||||||
|
|
||||||
|
@ -118,7 +118,9 @@ const SelectTestSuite: React.FC<SelectTestSuiteProps> = ({
|
|||||||
|
|
||||||
{isNewTestSuite ? (
|
{isNewTestSuite ? (
|
||||||
<>
|
<>
|
||||||
<Typography.Paragraph className="tw-text-base tw-mt-5">
|
<Typography.Paragraph
|
||||||
|
className="tw-text-base tw-mt-5"
|
||||||
|
data-testid="new-test-title">
|
||||||
New Test Suite
|
New Test Suite
|
||||||
</Typography.Paragraph>
|
</Typography.Paragraph>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
@ -139,7 +141,10 @@ const SelectTestSuite: React.FC<SelectTestSuiteProps> = ({
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
]}>
|
]}>
|
||||||
<Input placeholder="Enter test suite name" />
|
<Input
|
||||||
|
data-testid="test-suite-name"
|
||||||
|
placeholder="Enter test suite name"
|
||||||
|
/>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label="Description:"
|
label="Description:"
|
||||||
@ -168,6 +173,7 @@ const SelectTestSuite: React.FC<SelectTestSuiteProps> = ({
|
|||||||
) : (
|
) : (
|
||||||
<Row className="tw-mb-10" justify="center">
|
<Row className="tw-mb-10" justify="center">
|
||||||
<Button
|
<Button
|
||||||
|
data-testid="create-new-test-suite"
|
||||||
icon={
|
icon={
|
||||||
<SVGIcons
|
<SVGIcons
|
||||||
alt="plus"
|
alt="plus"
|
||||||
@ -184,7 +190,7 @@ const SelectTestSuite: React.FC<SelectTestSuiteProps> = ({
|
|||||||
<Form.Item noStyle>
|
<Form.Item noStyle>
|
||||||
<Space className="tw-w-full tw-justify-end" size={16}>
|
<Space className="tw-w-full tw-justify-end" size={16}>
|
||||||
<Button onClick={handleCancelClick}>Cancel</Button>
|
<Button onClick={handleCancelClick}>Cancel</Button>
|
||||||
<Button htmlType="submit" type="primary">
|
<Button data-testid="next-button" htmlType="submit" type="primary">
|
||||||
Next
|
Next
|
||||||
</Button>
|
</Button>
|
||||||
</Space>
|
</Space>
|
||||||
|
@ -275,7 +275,7 @@ const TestCaseForm: React.FC<TestCaseFormProps> = ({
|
|||||||
<Form.Item noStyle>
|
<Form.Item noStyle>
|
||||||
<Space className="tw-w-full tw-justify-end" size={16}>
|
<Space className="tw-w-full tw-justify-end" size={16}>
|
||||||
<Button onClick={onBack}>Back</Button>
|
<Button onClick={onBack}>Back</Button>
|
||||||
<Button htmlType="submit" type="primary">
|
<Button data-testid="submit-test" htmlType="submit" type="primary">
|
||||||
Submit
|
Submit
|
||||||
</Button>
|
</Button>
|
||||||
</Space>
|
</Space>
|
||||||
|
@ -43,6 +43,7 @@ const TestSuiteScheduler: React.FC<TestSuiteSchedulerProps> = ({
|
|||||||
<Space className="tw-w-full tw-justify-end" size={16}>
|
<Space className="tw-w-full tw-justify-end" size={16}>
|
||||||
<Button onClick={onCancel}>Back</Button>
|
<Button onClick={onCancel}>Back</Button>
|
||||||
<Button
|
<Button
|
||||||
|
data-testid="deploy-button"
|
||||||
type="primary"
|
type="primary"
|
||||||
onClick={() => onSubmit(repeatFrequency || '')}>
|
onClick={() => onSubmit(repeatFrequency || '')}>
|
||||||
Submit
|
Submit
|
||||||
|
@ -70,6 +70,7 @@ const GlobalSettingLeftPanel = () => {
|
|||||||
<LeftPanelCard id="settings">
|
<LeftPanelCard id="settings">
|
||||||
<Menu
|
<Menu
|
||||||
className="global-setting-left-panel"
|
className="global-setting-left-panel"
|
||||||
|
data-testid="global-setting-left-panel"
|
||||||
items={menuItems}
|
items={menuItems}
|
||||||
mode="inline"
|
mode="inline"
|
||||||
selectedKeys={[`${settingCategory}.${tab}`]}
|
selectedKeys={[`${settingCategory}.${tab}`]}
|
||||||
|
@ -440,6 +440,7 @@ const ProfilerDashboard: React.FC<ProfilerDashboardProps> = ({
|
|||||||
<Radio.Group
|
<Radio.Group
|
||||||
buttonStyle="solid"
|
buttonStyle="solid"
|
||||||
className="profiler-switch"
|
className="profiler-switch"
|
||||||
|
data-testid="profiler-switch"
|
||||||
optionType="button"
|
optionType="button"
|
||||||
options={tabOptions}
|
options={tabOptions}
|
||||||
value={activeTab}
|
value={activeTab}
|
||||||
|
@ -74,6 +74,7 @@ const DataQualityTab: React.FC<DataQualityTabProps> = ({
|
|||||||
title: 'Name',
|
title: 'Name',
|
||||||
dataIndex: 'name',
|
dataIndex: 'name',
|
||||||
key: 'name',
|
key: 'name',
|
||||||
|
render: (name: string) => <span data-testid={name}>{name}</span>,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'Description',
|
title: 'Description',
|
||||||
@ -144,6 +145,7 @@ const DataQualityTab: React.FC<DataQualityTabProps> = ({
|
|||||||
title={hasAccess ? 'Delete' : NO_PERMISSION_FOR_ACTION}>
|
title={hasAccess ? 'Delete' : NO_PERMISSION_FOR_ACTION}>
|
||||||
<Button
|
<Button
|
||||||
className="flex-center"
|
className="flex-center"
|
||||||
|
data-testid={`delete-${record.name}`}
|
||||||
disabled={!hasAccess}
|
disabled={!hasAccess}
|
||||||
icon={
|
icon={
|
||||||
<SVGIcons
|
<SVGIcons
|
||||||
@ -165,6 +167,7 @@ const DataQualityTab: React.FC<DataQualityTabProps> = ({
|
|||||||
title={hasAccess ? 'Edit' : NO_PERMISSION_FOR_ACTION}>
|
title={hasAccess ? 'Edit' : NO_PERMISSION_FOR_ACTION}>
|
||||||
<Button
|
<Button
|
||||||
className="flex-center"
|
className="flex-center"
|
||||||
|
data-testid={`edit-${record.name}`}
|
||||||
disabled={!hasAccess}
|
disabled={!hasAccess}
|
||||||
icon={
|
icon={
|
||||||
<SVGIcons
|
<SVGIcons
|
||||||
|
@ -134,6 +134,7 @@ const ColumnProfileTable: FC<ColumnProfileTableProps> = ({
|
|||||||
key: 'Tests',
|
key: 'Tests',
|
||||||
render: (_, record) => (
|
render: (_, record) => (
|
||||||
<Link
|
<Link
|
||||||
|
data-testid={`${record.name}-test-count`}
|
||||||
to={getProfilerDashboardWithFqnPath(
|
to={getProfilerDashboardWithFqnPath(
|
||||||
ProfilerDashboardType.COLUMN,
|
ProfilerDashboardType.COLUMN,
|
||||||
record.fullyQualifiedName || '',
|
record.fullyQualifiedName || '',
|
||||||
@ -181,6 +182,7 @@ const ColumnProfileTable: FC<ColumnProfileTableProps> = ({
|
|||||||
)}>
|
)}>
|
||||||
<Button
|
<Button
|
||||||
className="flex-center"
|
className="flex-center"
|
||||||
|
data-testid={`add-test-${record.name}`}
|
||||||
disabled={!hasEditAccess}
|
disabled={!hasEditAccess}
|
||||||
icon={
|
icon={
|
||||||
<SVGIcons
|
<SVGIcons
|
||||||
|
@ -237,6 +237,7 @@ const TableProfilerV1: FC<TableProfilerProps> = ({ table, permissions }) => {
|
|||||||
<Radio.Group
|
<Radio.Group
|
||||||
buttonStyle="solid"
|
buttonStyle="solid"
|
||||||
className="profiler-switch"
|
className="profiler-switch"
|
||||||
|
data-testid="profiler-switch"
|
||||||
optionType="button"
|
optionType="button"
|
||||||
options={tabOptions}
|
options={tabOptions}
|
||||||
value={activeTab}
|
value={activeTab}
|
||||||
@ -307,7 +308,9 @@ const TableProfilerV1: FC<TableProfilerProps> = ({ table, permissions }) => {
|
|||||||
</Row>
|
</Row>
|
||||||
|
|
||||||
{isUndefined(profile) && (
|
{isUndefined(profile) && (
|
||||||
<div className="tw-border tw-flex tw-items-center tw-border-warning tw-rounded tw-p-2 tw-mb-4">
|
<div
|
||||||
|
className="tw-border tw-flex tw-items-center tw-border-warning tw-rounded tw-p-2 tw-mb-4"
|
||||||
|
data-testid="no-profiler-placeholder">
|
||||||
<NoDataIcon />
|
<NoDataIcon />
|
||||||
<p className="tw-mb-0 tw-ml-2">
|
<p className="tw-mb-0 tw-ml-2">
|
||||||
Data Profiler is an optional configuration in Ingestion. Please
|
Data Profiler is an optional configuration in Ingestion. Please
|
||||||
|
Loading…
x
Reference in New Issue
Block a user