diff --git a/openmetadata-ui/src/main/resources/ui/cypress/common/common.js b/openmetadata-ui/src/main/resources/ui/cypress/common/common.js index 8eb0e9ccb76..07a187699f7 100644 --- a/openmetadata-ui/src/main/resources/ui/cypress/common/common.js +++ b/openmetadata-ui/src/main/resources/ui/cypress/common/common.js @@ -13,9 +13,12 @@ /// +import { SEARCH_INDEX } from '../constants/constants'; + export const descriptionBox = '.toastui-editor-md-container > .toastui-editor > .ProseMirror'; export const uuid = () => Cypress._.random(0, 1e6); +const RETRY_TIMES = 30; const ADMIN = 'admin'; @@ -49,7 +52,7 @@ export const handleIngestionRetry = ( ) => { const rowIndex = ingestionType === 'metadata' ? 1 : 2; // ingestions page - const retryTimes = 30; + let retryCount = count; const testIngestionsTab = () => { cy.get('[data-testid="Ingestions"]').should('be.visible'); @@ -74,7 +77,7 @@ export const handleIngestionRetry = ( if ( ($ingestionStatus.text() === 'Running' || $ingestionStatus.text() === 'Queued') && - retryCount <= retryTimes + retryCount <= RETRY_TIMES ) { // retry after waiting for 20 seconds cy.wait(20000); @@ -403,12 +406,23 @@ export const searchEntity = (term, suggestionOverly = true) => { export const visitEntityDetailsPage = (term, serviceName, entity) => { interceptURL('GET', '/api/v1/*/name/*', 'getEntityDetails'); - interceptURL('GET', '/api/v1/search/*', 'explorePageSearch'); + interceptURL( + 'GET', + `/api/v1/search/query?q=*&from=*&size=*&index=${SEARCH_INDEX[entity]}`, + 'explorePageTabSearch' + ); + interceptURL( + 'GET', + `/api/v1/search/suggest?q=*&index=dashboard_search_index,table_search_index,topic_search_index,pipeline_search_index,mlmodel_search_index`, + 'searchQuery' + ); + interceptURL('GET', `/api/v1/search/*`, 'explorePageSearch'); // searching term in search box cy.get('[data-testid="searchBox"]').scrollIntoView().should('be.visible'); cy.get('[data-testid="searchBox"]').type(term); cy.get('[data-testid="suggestion-overlay"]').should('exist'); + verifyResponseStatusCode('@searchQuery', 200); cy.get('body').then(($body) => { // checking if requested term is available in search suggestion if ( @@ -425,12 +439,13 @@ export const visitEntityDetailsPage = (term, serviceName, entity) => { // if term is not available in search suggestion, hitting enter to search box so it will redirect to explore page cy.get('body').click(1, 1); cy.get('[data-testid="searchBox"]').type('{enter}'); + verifyResponseStatusCode('@explorePageSearch', 200); cy.get(`[data-testid="${entity}-tab"]`).should('be.visible').click(); cy.get(`[data-testid="${entity}-tab"]`) .should('be.visible') .should('have.class', 'active'); - verifyResponseStatusCode('@explorePageSearch', 200); + verifyResponseStatusCode('@explorePageTabSearch', 200); cy.get(`[data-testid="${serviceName}-${term}"]`) .scrollIntoView() @@ -811,7 +826,9 @@ export const deleteCreatedProperty = (propertyName) => { cy.get('[data-testid="save-button"]').should('be.visible').click(); //Checking if property got deleted successfully - cy.get('[data-testid="add-field-button"]').scrollIntoView().should('be.visible'); + cy.get('[data-testid="add-field-button"]') + .scrollIntoView() + .should('be.visible'); }; export const updateOwner = () => { @@ -911,7 +928,6 @@ export const addTeam = (TEAM_DETAILS) => { }; export const retryIngestionRun = () => { - const retryTimes = 10; let retryCount = 0; const testIngestionsTab = () => { @@ -935,7 +951,7 @@ export const retryIngestionRun = () => { if ( ($ingestionStatus.text() === 'Running' || $ingestionStatus.text() === 'Queued') && - retryCount <= retryTimes + retryCount <= RETRY_TIMES ) { // retry after waiting for 20 seconds cy.wait(20000); diff --git a/openmetadata-ui/src/main/resources/ui/cypress/constants/constants.js b/openmetadata-ui/src/main/resources/ui/cypress/constants/constants.js index cbdee534c3b..4ae208f1cf9 100644 --- a/openmetadata-ui/src/main/resources/ui/cypress/constants/constants.js +++ b/openmetadata-ui/src/main/resources/ui/cypress/constants/constants.js @@ -11,8 +11,7 @@ * limitations under the License. */ -import { uuid } from '../common/common'; - +export const uuid = () => Cypress._.random(0, 1e6); const id = uuid(); export const MYDATA_SUMMARY_OPTIONS = { @@ -23,7 +22,15 @@ export const MYDATA_SUMMARY_OPTIONS = { service: 'service', user: 'user', terms: 'terms', - mlmodels:'mlmodels' + mlmodels: 'mlmodels', +}; + +export const SEARCH_INDEX = { + tables: 'table_search_index', + topics: 'topic_search_index', + dashboards: 'dashboard_search_index', + pipelines: 'pipeline_search_index', + mlmodels: 'mlmodel_search_index', }; export const SEARCH_ENTITY_TABLE = { diff --git a/openmetadata-ui/src/main/resources/ui/cypress/e2e/Pages/DataQualityAndProfiler.js b/openmetadata-ui/src/main/resources/ui/cypress/e2e/Pages/DataQualityAndProfiler.js index e97e91d1184..15b972608e7 100644 --- a/openmetadata-ui/src/main/resources/ui/cypress/e2e/Pages/DataQualityAndProfiler.js +++ b/openmetadata-ui/src/main/resources/ui/cypress/e2e/Pages/DataQualityAndProfiler.js @@ -83,6 +83,7 @@ describe('Data Quality and Profiler should work properly', () => { .scrollIntoView() .contains('Profiler Ingestion') .click(); + cy.get('[data-testid="profileSample"]').should('be.visible').type(0.01); cy.get('[data-testid="next-button"]') .scrollIntoView() .should('be.visible') @@ -107,7 +108,7 @@ describe('Data Quality and Profiler should work properly', () => { cy.goToHomePage(); goToProfilerTab(); cy.get('[data-testid="no-profiler-placeholder"]').should('not.exist'); - }) + }); it('Add table test case with new test suite', () => { login(LOGIN.username, LOGIN.password); diff --git a/openmetadata-ui/src/main/resources/ui/cypress/e2e/Pages/Glossary.spec.js b/openmetadata-ui/src/main/resources/ui/cypress/e2e/Pages/Glossary.spec.js index 7adfa0b6ff1..3fb34d30d31 100644 --- a/openmetadata-ui/src/main/resources/ui/cypress/e2e/Pages/Glossary.spec.js +++ b/openmetadata-ui/src/main/resources/ui/cypress/e2e/Pages/Glossary.spec.js @@ -325,7 +325,7 @@ describe('Glossary page should work properly', () => { cy.get('[data-testid="section-related-terms"] [data-testid="edit-button"]') .scrollIntoView() .should('be.visible') - .click(); + .click({ force: true }); interceptURL( 'GET', '/api/v1/search/query?q=*&from=0&size=10&index=glossary_search_index', diff --git a/openmetadata-ui/src/main/resources/ui/cypress/e2e/Pages/Login.spec.js b/openmetadata-ui/src/main/resources/ui/cypress/e2e/Pages/Login.spec.js index 036d919e73f..4b2a8333e20 100644 --- a/openmetadata-ui/src/main/resources/ui/cypress/e2e/Pages/Login.spec.js +++ b/openmetadata-ui/src/main/resources/ui/cypress/e2e/Pages/Login.spec.js @@ -24,7 +24,7 @@ const invalidPassword = 'testUsers@123'; const baseURL = location.origin; -const ERROR_MESSAGE = 'You have entered an invalid username or password.' +const ERROR_MESSAGE = 'You have entered an invalid username or password.'; describe('Login flow should work properly', () => { it('Signup and Login with signed up credentials', () => { @@ -57,9 +57,7 @@ describe('Login flow should work properly', () => { .type(CREDENTIALS.password); //Click on create account button cy.get('.ant-btn').contains('Create Account').should('be.visible').click(); - cy.url() - .should('eq', `${baseURL}/signin`) - .and('contain', 'signin'); + cy.url().should('eq', `${baseURL}/signin`).and('contain', 'signin'); //Login with the created user @@ -75,7 +73,9 @@ describe('Login flow should work properly', () => { .invoke('text') .should('contain', `${CREDENTIALS.firstName}${CREDENTIALS.lastName}`); interceptURL('GET', 'api/v1/users/name/*', 'getUserPage'); - cy.get('[data-testid="user-name"]').should('be.visible').click({force: true}); + cy.get('[data-testid="user-name"]') + .should('be.visible') + .click({ force: true }); verifyResponseStatusCode('@getUserPage', 200); cy.get('[data-testid="left-panel"]').should( 'contain', @@ -104,7 +104,11 @@ describe('Login flow should work properly', () => { cy.visit('/'); verifyResponseStatusCode('@getLoginPage', 200); //Click on Forgot button - cy.get('[data-testid="forgot-password"]').should('be.visible').click(); + cy.get('[data-testid="forgot-password"]') + .should('be.visible') + .trigger('mouseover') + .click(); + cy.url() .should('eq', `${baseURL}/forgot-password`) .and('contain', 'forgot-password'); diff --git a/openmetadata-ui/src/main/resources/ui/cypress/e2e/Pages/Teams.spec.js b/openmetadata-ui/src/main/resources/ui/cypress/e2e/Pages/Teams.spec.js index 42b5c59a4d1..167dfeb394e 100644 --- a/openmetadata-ui/src/main/resources/ui/cypress/e2e/Pages/Teams.spec.js +++ b/openmetadata-ui/src/main/resources/ui/cypress/e2e/Pages/Teams.spec.js @@ -26,6 +26,13 @@ const TEAM_DETAILS = { ownername: 'Aaron Johnson', assetname: 'dim_address', }; +const hardDeleteTeamName = `team-ct-test-${uuid()}`; +const HARD_DELETE_TEAM_DETAILS = { + name: hardDeleteTeamName, + displayName: hardDeleteTeamName, + teamType: 'Department', + description: `This is ${hardDeleteTeamName} description`, +}; describe('Teams flow should work properly', () => { before(() => { @@ -35,6 +42,7 @@ describe('Teams flow should work properly', () => { cy.saveLocalStorage('localstorage'); }); beforeEach(() => { + interceptURL('GET', `/api/v1/users?fields=*`, 'getUserDetails'); cy.log('Restoring local storage snapshot'); cy.restoreLocalStorage('localstorage'); cy.clickOnLogo(); @@ -73,6 +81,9 @@ describe('Teams flow should work properly', () => { cy.get('table').find('.ant-table-row').contains(TEAM_DETAILS.name).click(); verifyResponseStatusCode('@getUsers', 200); + cy.get('[data-testid="team-heading"]') + .should('be.visible') + .contains(TEAM_DETAILS.name); //Clicking on users tab cy.get('[data-testid="Users"]') .should('exist') @@ -158,16 +169,18 @@ describe('Teams flow should work properly', () => { cy.get('body').find('[data-testid="leave-team-button"]').should('exist'); }); - it('Update description and display name for created team', () => { + it('Update display name for created team', () => { interceptURL( 'GET', `/api/v1/teams/name/${TEAM_DETAILS.name}*`, 'getSelectedTeam' ); + interceptURL('PATCH', `/api/v1/teams/*`, 'patchTeam'); //Click on created team name cy.get('table').find('.ant-table-row').contains(TEAM_DETAILS.name).click(); verifyResponseStatusCode('@getSelectedTeam', 200); + verifyResponseStatusCode('@getUserDetails', 200); //Click on edit display name cy.get('[data-testid="edit-synonyms"]').should('be.visible').click(); @@ -178,18 +191,37 @@ describe('Teams flow should work properly', () => { .clear() .type(TEAM_DETAILS.updatedname); - interceptURL( - 'GET', - `api/v1/users?fields=teams,roles&team=${TEAM_DETAILS.name}&limit=15`, - 'getTeamDetails' - ); //Save the updated display name cy.get('[data-testid="saveAssociatedTag"]') .should('exist') .should('be.visible') .click(); - verifyResponseStatusCode('@getTeamDetails', 200); + verifyResponseStatusCode('@patchTeam', 200); + verifyResponseStatusCode('@getSelectedTeam', 200); + verifyResponseStatusCode('@getUserDetails', 200); + //Validate the updated display name + cy.get('[data-testid="team-heading"]').then(($el) => { + cy.wrap($el).should('have.text', TEAM_DETAILS.updatedname); + }); + + cy.get('[data-testid="inactive-link"]') + .should('be.visible') + .should('contain', TEAM_DETAILS.updatedname); + }); + + it('Update description for created team', () => { + interceptURL('GET', `/api/v1/teams/name/*`, 'getSelectedTeam'); + interceptURL('PATCH', `/api/v1/teams/*`, 'patchTeam'); + //Click on created team name + cy.get('table') + .find('.ant-table-row') + .contains(TEAM_DETAILS.updatedname) + .click(); + + verifyResponseStatusCode('@getSelectedTeam', 200); + verifyResponseStatusCode('@getUserDetails', 200); + //Validate the updated display name cy.get('[data-testid="team-heading"]').then(($el) => { cy.wrap($el).should('have.text', TEAM_DETAILS.updatedname); @@ -201,10 +233,8 @@ describe('Teams flow should work properly', () => { //Click on edit description button cy.get('[data-testid="edit-description"]') - .should('exist') - .then(($editDescription) => { - cy.wrap($editDescription).should('be.visible').click(); - }); + .should('be.visible') + .click({ force: true }); //Entering updated description cy.get(descriptionBox).clear().type(updateddescription); @@ -286,6 +316,10 @@ describe('Teams flow should work properly', () => { cy.get('table').find('.ant-table-row').contains(TEAM_DETAILS.name).click(); verifyResponseStatusCode('@getSelectedTeam', 200); + cy.get('[data-testid="team-heading"]') + .should('be.visible') + .contains(TEAM_DETAILS.name); + verifyResponseStatusCode('@getUserDetails', 200); // //Click on Leave team cy.get('[data-testid="leave-team-button"]').should('be.visible').click(); @@ -308,7 +342,10 @@ describe('Teams flow should work properly', () => { cy.get('table').find('.ant-table-row').contains(TEAM_DETAILS.name).click(); verifyResponseStatusCode('@getSelectedTeam', 200); - + cy.get('[data-testid="team-heading"]') + .should('be.visible') + .contains(TEAM_DETAILS.updatedname); + verifyResponseStatusCode('@getUserDetails', 200); cy.get('[data-testid="manage-button"]') .should('exist') .should('be.visible') @@ -325,23 +362,6 @@ describe('Teams flow should work properly', () => { .should('exist') .should('be.disabled'); - cy.get('[data-testid="discard-button"]') - .should('exist') - .should('be.visible') - .click(); - - cy.get('[data-testid="manage-button"]') - .should('exist') - .should('be.visible') - .click(); - - cy.get('[data-menu-id*="delete-button"]').should('be.visible'); - - cy.get('[data-testid="delete-button-title"]') - .should('exist') - .should('be.visible') - .click(); - //Click on soft delete option cy.get('[data-testid="soft-delete-option"]') .should('contain', TEAM_DETAILS.name) @@ -378,6 +398,10 @@ describe('Teams flow should work properly', () => { cy.get('table').find('.ant-table-row').contains(TEAM_DETAILS.name).click(); verifyResponseStatusCode('@getSelectedTeam', 200); + cy.get('[data-testid="team-heading"]') + .should('be.visible') + .contains(TEAM_DETAILS.updatedname); + verifyResponseStatusCode('@getUserDetails', 200); cy.get('[data-testid="manage-button"]') .should('exist') @@ -420,18 +444,21 @@ describe('Teams flow should work properly', () => { it('Permanently deleting a team without soft deleting should work properly', () => { //Add a new team - addTeam(TEAM_DETAILS); + addTeam(HARD_DELETE_TEAM_DETAILS); interceptURL( 'GET', - `/api/v1/teams/name/${TEAM_DETAILS.name}*`, + `/api/v1/teams/name/${HARD_DELETE_TEAM_DETAILS.name}*`, 'getSelectedTeam' ); //Click on created team - cy.get('table').find('.ant-table-row').contains(TEAM_DETAILS.name).click(); + cy.get('table') + .find('.ant-table-row') + .contains(HARD_DELETE_TEAM_DETAILS.name) + .click(); verifyResponseStatusCode('@getSelectedTeam', 200); - + verifyResponseStatusCode('@getUserDetails', 200); cy.get('[data-testid="manage-button"]') .should('exist') .should('be.visible') @@ -450,12 +477,12 @@ describe('Teams flow should work properly', () => { //Check if soft delete option is present cy.get('[data-testid="soft-delete-option"]') - .should('contain', TEAM_DETAILS.name) + .should('contain', HARD_DELETE_TEAM_DETAILS.name) .should('be.visible'); //Click on permanent delete option cy.get('[data-testid="hard-delete-option"]') - .should('contain', TEAM_DETAILS.name) + .should('contain', HARD_DELETE_TEAM_DETAILS.name) .should('be.visible') .click(); @@ -474,6 +501,6 @@ describe('Teams flow should work properly', () => { //Validating the deleted team - cy.get('table').should('not.contain', TEAM_DETAILS.name); + cy.get('table').should('not.contain', HARD_DELETE_TEAM_DETAILS.name); }); }); diff --git a/openmetadata-ui/src/main/resources/ui/src/components/common/table-data-card/TableDataCard.tsx b/openmetadata-ui/src/main/resources/ui/src/components/common/table-data-card/TableDataCard.tsx index 9b0ebe64676..15c41f82188 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/common/table-data-card/TableDataCard.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/components/common/table-data-card/TableDataCard.tsx @@ -38,6 +38,7 @@ import { getEntityId, getEntityName, getEntityPlaceHolder, + getNameFromFQN, getOwnerValue, getPartialNameFromTableFQN, } from '../../../utils/CommonUtils'; @@ -161,7 +162,7 @@ const TableDataCard: FunctionComponent = ({ className="tw-text-grey-body tw-font-semibold" data-testid={`${getPartialNameFromTableFQN(fullyQualifiedName, [ FqnPart.Service, - ])}-${getPartialNameFromTableFQN(fullyQualifiedName, [FqnPart.Table])}`} + ])}-${getNameFromFQN(fullyQualifiedName)}`} id={`${id}Title`} onClick={handleLinkClick}> {stringToHTML(name)} diff --git a/openmetadata-ui/src/main/resources/ui/src/pages/teams/TeamsPage.tsx b/openmetadata-ui/src/main/resources/ui/src/pages/teams/TeamsPage.tsx index 9bdd62130e8..988c29739c9 100644 --- a/openmetadata-ui/src/main/resources/ui/src/pages/teams/TeamsPage.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/pages/teams/TeamsPage.tsx @@ -64,6 +64,7 @@ const TeamsPage = () => { const { isAdminUser } = useAuth(); const { isAuthDisabled } = useAuthContext(); const { fqn } = useParams<{ [key: string]: string }>(); + const [currentFqn, setCurrentFqn] = useState(''); const [allTeam, setAllTeam] = useState([]); const [selectedTeam, setSelectedTeam] = useState({} as Team); const [users, setUsers] = useState([]); @@ -470,11 +471,15 @@ const TeamsPage = () => { }; useEffect(() => { - if (entityPermissions.ViewAll || entityPermissions.ViewBasic) { + if ( + (entityPermissions.ViewAll || entityPermissions.ViewBasic) && + currentFqn !== fqn + ) { if (fqn) { fetchTeamByFqn(fqn); } fetchAllTeams(false, fqn); + setCurrentFqn(fqn); } }, [entityPermissions, fqn]);