mirror of
https://github.com/open-metadata/OpenMetadata.git
synced 2025-09-25 17:04:54 +00:00

* Fix the styling issue for the teams and user selection component in the alert form * Fix the incorrect field names in form error messages * Fix and modify cypress tests * Fix the incorrect util function import * update the field name in form validation message * Update proper assertions
454 lines
12 KiB
TypeScript
454 lines
12 KiB
TypeScript
/*
|
|
* 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 {
|
|
DELETE_TERM,
|
|
INVALID_NAMES,
|
|
NAME_MIN_MAX_LENGTH_VALIDATION_ERROR_1_128,
|
|
NAME_VALIDATION_ERROR,
|
|
} from '../constants/constants';
|
|
import { SidebarItem } from '../constants/Entity.interface';
|
|
import {
|
|
descriptionBox,
|
|
interceptURL,
|
|
toastNotification,
|
|
verifyResponseStatusCode,
|
|
} from './common';
|
|
|
|
export const validateForm = () => {
|
|
// error messages
|
|
cy.get('#name_help')
|
|
.scrollIntoView()
|
|
.should('be.visible')
|
|
.contains('Name is required');
|
|
cy.get('#description_help')
|
|
.should('be.visible')
|
|
.contains('Description is required');
|
|
|
|
// max length validation
|
|
cy.get('[data-testid="name"]')
|
|
.scrollIntoView()
|
|
.should('be.visible')
|
|
.type(INVALID_NAMES.MAX_LENGTH);
|
|
cy.get('#name_help').should(
|
|
'contain',
|
|
NAME_MIN_MAX_LENGTH_VALIDATION_ERROR_1_128
|
|
);
|
|
|
|
// with special char validation
|
|
cy.get('[data-testid="name"]')
|
|
.should('be.visible')
|
|
.clear()
|
|
.type(INVALID_NAMES.WITH_SPECIAL_CHARS);
|
|
cy.get('#name_help').should('be.visible').contains(NAME_VALIDATION_ERROR);
|
|
};
|
|
|
|
export const selectActiveGlossary = (glossaryName) => {
|
|
interceptURL('GET', '/api/v1/glossaryTerms*', 'getGlossaryTerms');
|
|
cy.get('.ant-menu-item').contains(glossaryName).click();
|
|
verifyResponseStatusCode('@getGlossaryTerms', 200);
|
|
};
|
|
|
|
export const checkDisplayName = (displayName) => {
|
|
cy.get('[data-testid="entity-header-display-name"]')
|
|
.filter(':visible')
|
|
.scrollIntoView()
|
|
.within(() => {
|
|
cy.contains(displayName);
|
|
});
|
|
};
|
|
|
|
export const visitGlossaryPage = () => {
|
|
interceptURL('GET', '/api/v1/glossaries?fields=*', 'getGlossaries');
|
|
|
|
cy.sidebarClick(SidebarItem.GLOSSARY);
|
|
|
|
verifyResponseStatusCode('@getGlossaries', 200);
|
|
};
|
|
|
|
export const removeReviewer = (entity) => {
|
|
interceptURL('PATCH', `/api/v1/${entity}/*`, 'patchOwner');
|
|
|
|
cy.get('[data-testid="edit-reviewer-button"]').click();
|
|
|
|
cy.get('[data-testid="clear-all-button"]').click();
|
|
|
|
cy.get('[data-testid="selectable-list-update-btn"]').click();
|
|
|
|
verifyResponseStatusCode('@patchOwner', 200);
|
|
|
|
cy.get('[data-testid="glossary-reviewer"] [data-testid="Add"]').should(
|
|
'be.visible'
|
|
);
|
|
};
|
|
|
|
export const deleteGlossary = (glossary) => {
|
|
cy.get('.ant-menu-item').contains(glossary).click();
|
|
|
|
cy.get('[data-testid="manage-button"]').click();
|
|
|
|
cy.get('[data-testid="delete-button"]').scrollIntoView().click();
|
|
|
|
cy.get('[data-testid="delete-confirmation-modal"]').then(() => {
|
|
cy.get('[role="dialog"]').should('be.visible');
|
|
cy.get('[data-testid="modal-header"]').should('be.visible');
|
|
});
|
|
|
|
cy.get('[data-testid="modal-header"]').should('contain', glossary);
|
|
|
|
cy.get('[data-testid="confirmation-text-input"]').type(DELETE_TERM);
|
|
|
|
interceptURL('DELETE', '/api/v1/glossaries/*', 'getGlossary');
|
|
|
|
cy.get('[data-testid="confirm-button"]').click();
|
|
|
|
verifyResponseStatusCode('@getGlossary', 200);
|
|
|
|
toastNotification('"Glossary" deleted successfully!');
|
|
};
|
|
|
|
export const addOwnerInGlossary = (
|
|
ownerNames: string | string[],
|
|
activatorBtnDataTestId: string,
|
|
resultTestId = 'owner-link',
|
|
isSelectableInsideForm = false
|
|
) => {
|
|
const isMultipleOwners = Array.isArray(ownerNames);
|
|
const owners = isMultipleOwners ? ownerNames : [ownerNames];
|
|
|
|
interceptURL('GET', '/api/v1/users?*isBot=false*', 'getUsers');
|
|
|
|
cy.get(`[data-testid="${activatorBtnDataTestId}"]`).click();
|
|
cy.get("[data-testid='select-owner-tabs']").should('be.visible');
|
|
cy.wait(500); // Due to popover positioning issue adding wait here, will handle this with playwright @karan
|
|
cy.get('.ant-tabs [id*=tab-users]').click({
|
|
waitForAnimations: true,
|
|
});
|
|
verifyResponseStatusCode('@getUsers', 200);
|
|
|
|
interceptURL(
|
|
'GET',
|
|
`api/v1/search/query?q=*&index=user_search_index*`,
|
|
'searchOwner'
|
|
);
|
|
interceptURL('PATCH', `/api/v1/**`, 'patchOwner');
|
|
|
|
if (isMultipleOwners) {
|
|
cy.get('[data-testid="clear-all-button"]').scrollIntoView().click();
|
|
}
|
|
|
|
owners.forEach((ownerName) => {
|
|
cy.get('[data-testid="owner-select-users-search-bar"]')
|
|
.clear()
|
|
.type(ownerName);
|
|
verifyResponseStatusCode('@searchOwner', 200);
|
|
cy.get(`.ant-popover [title="${ownerName}"]`).click();
|
|
});
|
|
|
|
if (isMultipleOwners) {
|
|
cy.get('[data-testid="selectable-list-update-btn"]').click();
|
|
}
|
|
|
|
if (!isSelectableInsideForm) {
|
|
verifyResponseStatusCode('@patchOwner', 200);
|
|
}
|
|
|
|
cy.get(`[data-testid=${resultTestId}]`).within(() => {
|
|
owners.forEach((name) => {
|
|
cy.contains(name);
|
|
});
|
|
});
|
|
};
|
|
|
|
export const addTeamAsReviewer = (
|
|
teamName: string,
|
|
activatorBtnDataTestId: string,
|
|
dataTestId?: string,
|
|
isSelectableInsideForm = false
|
|
) => {
|
|
interceptURL(
|
|
'GET',
|
|
'/api/v1/search/query?q=*&from=0&size=*&index=team_search_index&sort_field=displayName.keyword&sort_order=asc',
|
|
'getTeams'
|
|
);
|
|
|
|
cy.get(`[data-testid="${activatorBtnDataTestId}"]`).click();
|
|
|
|
cy.get("[data-testid='select-owner-tabs']").should('be.visible');
|
|
|
|
verifyResponseStatusCode('@getTeams', 200);
|
|
|
|
interceptURL(
|
|
'GET',
|
|
`api/v1/search/query?q=*${encodeURI(teamName)}*`,
|
|
'searchTeams'
|
|
);
|
|
|
|
cy.get('[data-testid="owner-select-teams-search-bar"]').type(teamName);
|
|
|
|
verifyResponseStatusCode('@searchTeams', 200);
|
|
|
|
interceptURL('PATCH', `/api/v1/**`, 'patchOwner');
|
|
cy.get(`.ant-popover [title="${teamName}"]`).click();
|
|
|
|
if (!isSelectableInsideForm) {
|
|
verifyResponseStatusCode('@patchOwner', 200);
|
|
}
|
|
|
|
cy.get(`[data-testid=${dataTestId ?? 'owner-link'}]`).should(
|
|
'contain',
|
|
teamName
|
|
);
|
|
};
|
|
|
|
export const createGlossary = (glossaryData, bValidateForm) => {
|
|
// Intercept API calls
|
|
interceptURL('POST', '/api/v1/glossaries', `create_${glossaryData.name}`);
|
|
interceptURL(
|
|
'GET',
|
|
'/api/v1/search/query?q=*disabled:false&index=tag_search_index&from=0&size=10&query_filter=%7B%7D',
|
|
'fetchTags'
|
|
);
|
|
|
|
// Click on the "Add Glossary" button
|
|
cy.get('[data-testid="add-glossary"]').click();
|
|
|
|
// Validate redirection to the add glossary page
|
|
cy.get('[data-testid="form-heading"]')
|
|
.contains('Add Glossary')
|
|
.should('be.visible');
|
|
|
|
// Perform glossary creation steps
|
|
cy.get('[data-testid="save-glossary"]')
|
|
.scrollIntoView()
|
|
.should('be.visible')
|
|
.click();
|
|
|
|
if (bValidateForm) {
|
|
validateForm();
|
|
}
|
|
|
|
cy.get('[data-testid="name"]')
|
|
.scrollIntoView()
|
|
.should('be.visible')
|
|
.clear()
|
|
.type(glossaryData.name);
|
|
|
|
cy.get(descriptionBox)
|
|
.scrollIntoView()
|
|
.should('be.visible')
|
|
.type(glossaryData.description);
|
|
|
|
if (glossaryData.isMutually) {
|
|
cy.get('[data-testid="mutually-exclusive-button"]')
|
|
.scrollIntoView()
|
|
.click();
|
|
}
|
|
|
|
if (glossaryData.tag) {
|
|
// Add tag
|
|
cy.get('[data-testid="tag-selector"] .ant-select-selection-overflow')
|
|
.scrollIntoView()
|
|
.type(glossaryData.tag);
|
|
|
|
verifyResponseStatusCode('@fetchTags', 200);
|
|
cy.get(`[data-testid="tag-${glossaryData.tag}"]`).click();
|
|
cy.get('[data-testid="right-panel"]').click();
|
|
}
|
|
|
|
if (glossaryData.reviewers.length > 0) {
|
|
// Add reviewer
|
|
if (glossaryData.reviewers[0].type === 'user') {
|
|
addOwnerInGlossary(
|
|
glossaryData.reviewers.map((reviewer) => reviewer.name),
|
|
'add-reviewers',
|
|
'reviewers-container',
|
|
true
|
|
);
|
|
} else {
|
|
addTeamAsReviewer(
|
|
glossaryData.reviewers[0].name,
|
|
'add-reviewers',
|
|
'reviewers-container',
|
|
true
|
|
);
|
|
}
|
|
}
|
|
|
|
cy.get('[data-testid="save-glossary"]')
|
|
.scrollIntoView()
|
|
.should('be.visible')
|
|
.click();
|
|
|
|
cy.wait(`@create_${glossaryData.name}`).then(({ request }) => {
|
|
expect(request.body.name).equals(glossaryData.name);
|
|
expect(request.body.description).equals(glossaryData.description);
|
|
});
|
|
|
|
cy.url().should('include', '/glossary/');
|
|
checkDisplayName(glossaryData.name);
|
|
};
|
|
|
|
const fillGlossaryTermDetails = (
|
|
term,
|
|
isMutually = false,
|
|
validateCreateForm = true
|
|
) => {
|
|
cy.get('[data-testid="add-new-tag-button-header"]').click();
|
|
|
|
cy.contains('Add Glossary Term').should('be.visible');
|
|
|
|
// validation should work
|
|
cy.get('[data-testid="save-glossary-term"]')
|
|
.scrollIntoView()
|
|
.should('be.visible')
|
|
.click();
|
|
|
|
if (validateCreateForm) {
|
|
validateForm();
|
|
}
|
|
|
|
cy.get('[data-testid="name"]')
|
|
.scrollIntoView()
|
|
.should('be.visible')
|
|
.clear()
|
|
.type(term.name);
|
|
cy.get(descriptionBox)
|
|
.scrollIntoView()
|
|
.should('be.visible')
|
|
.type(term.description);
|
|
|
|
const synonyms = term.synonyms.split(',');
|
|
cy.get('[data-testid="synonyms"]')
|
|
.scrollIntoView()
|
|
.should('be.visible')
|
|
.type(synonyms.join('{enter}'));
|
|
if (isMutually) {
|
|
cy.get('[data-testid="mutually-exclusive-button"]')
|
|
.scrollIntoView()
|
|
.should('exist')
|
|
.should('be.visible')
|
|
.click();
|
|
}
|
|
cy.get('[data-testid="add-reference"]')
|
|
.scrollIntoView()
|
|
.should('be.visible')
|
|
.click();
|
|
|
|
cy.get('#name-0').scrollIntoView().should('be.visible').type('test');
|
|
cy.get('#url-0')
|
|
.scrollIntoView()
|
|
.should('be.visible')
|
|
.type('https://test.com');
|
|
|
|
if (term.icon) {
|
|
cy.get('[data-testid="icon-url"]').scrollIntoView().type(term.icon);
|
|
}
|
|
if (term.color) {
|
|
cy.get('[data-testid="color-color-input"]')
|
|
.scrollIntoView()
|
|
.type(term.color);
|
|
}
|
|
|
|
if (term.owner) {
|
|
addOwnerInGlossary(term.owner, 'add-owner', 'owner-container', true);
|
|
}
|
|
};
|
|
|
|
export const createGlossaryTerm = (
|
|
term,
|
|
status,
|
|
isMutually = false,
|
|
validateCreateForm = true
|
|
) => {
|
|
fillGlossaryTermDetails(term, isMutually, validateCreateForm);
|
|
|
|
interceptURL('POST', '/api/v1/glossaryTerms', `createGlossaryTerms`);
|
|
cy.get('[data-testid="save-glossary-term"]')
|
|
.scrollIntoView()
|
|
.should('be.visible')
|
|
.click();
|
|
|
|
verifyResponseStatusCode('@createGlossaryTerms', 201);
|
|
|
|
cy.get(
|
|
`[data-row-key="${Cypress.$.escapeSelector(term.fullyQualifiedName)}"]`
|
|
)
|
|
.scrollIntoView()
|
|
.should('be.visible')
|
|
.contains(term.name);
|
|
|
|
cy.get(
|
|
`[data-testid="${Cypress.$.escapeSelector(
|
|
term.fullyQualifiedName
|
|
)}-status"]`
|
|
)
|
|
.should('be.visible')
|
|
.contains(status);
|
|
};
|
|
|
|
export const verifyGlossaryDetails = (glossaryDetails) => {
|
|
cy.get('[data-testid="glossary-left-panel"]')
|
|
.contains(glossaryDetails.name)
|
|
.click();
|
|
|
|
checkDisplayName(glossaryDetails.name);
|
|
|
|
cy.get('[data-testid="viewer-container"]')
|
|
.invoke('text')
|
|
.then((text) => {
|
|
expect(text).to.contain(glossaryDetails.description);
|
|
});
|
|
|
|
// Owner
|
|
cy.get(`[data-testid="glossary-right-panel-owner-link"]`).should(
|
|
'contain',
|
|
glossaryDetails.owner ? glossaryDetails.owner : 'No Owner'
|
|
);
|
|
|
|
// Reviewer
|
|
if (glossaryDetails.reviewers.length > 0) {
|
|
cy.get(`[data-testid="glossary-reviewer-name"]`).within(() => {
|
|
glossaryDetails.reviewers.forEach((reviewer) => {
|
|
cy.contains(reviewer.name);
|
|
});
|
|
});
|
|
}
|
|
|
|
// Tags
|
|
if (glossaryDetails.tag) {
|
|
cy.get(`[data-testid="tag-${glossaryDetails.tag}"]`).should('be.visible');
|
|
}
|
|
};
|
|
|
|
const verifyGlossaryTermDataInTable = (term, status: string) => {
|
|
const escapedName = Cypress.$.escapeSelector(term.fullyQualifiedName);
|
|
const selector = `[data-row-key=${escapedName}]`;
|
|
cy.get(selector).scrollIntoView().should('be.visible');
|
|
cy.get(`${selector} [data-testid="${escapedName}-status"]`).contains(status);
|
|
// If empty owner, the creator is the owner
|
|
cy.get(`${selector} [data-testid="owner-link"]`).contains(
|
|
term.owner ?? 'admin'
|
|
);
|
|
};
|
|
|
|
export const createGlossaryTerms = (glossaryDetails) => {
|
|
selectActiveGlossary(glossaryDetails.name);
|
|
const termStatus =
|
|
glossaryDetails.reviewers.length > 0 ? 'Draft' : 'Approved';
|
|
glossaryDetails.terms.forEach((term, index) => {
|
|
createGlossaryTerm(term, termStatus, true, index === 0);
|
|
verifyGlossaryTermDataInTable(term, termStatus);
|
|
});
|
|
};
|