mirror of
https://github.com/open-metadata/OpenMetadata.git
synced 2025-11-24 06:32:21 +00:00
supported cypress for team and glossary drag and drop functionality (#15213)
* supported cypress for team drag and drop functionality * added glossary drag and drop cypress and fix searchindex cypress failure * changes as per comments * fix the regression of import
This commit is contained in:
parent
3748c792d0
commit
1c1dba7a63
@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright 2024 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.
|
||||
*/
|
||||
|
||||
const dataTransfer = new DataTransfer();
|
||||
|
||||
export const dragAndDropElement = (
|
||||
dragElement: string,
|
||||
dropTarget: string,
|
||||
isHeader?: boolean
|
||||
) => {
|
||||
cy.get(`[data-row-key="${Cypress.$.escapeSelector(dragElement)}"]`)
|
||||
.invoke('attr', 'draggable')
|
||||
.should('contain', 'true');
|
||||
|
||||
cy.get(`[data-row-key="${Cypress.$.escapeSelector(dragElement)}"]`).trigger(
|
||||
'dragstart',
|
||||
{
|
||||
dataTransfer,
|
||||
}
|
||||
);
|
||||
|
||||
cy.get(
|
||||
isHeader
|
||||
? dropTarget
|
||||
: `[data-row-key="${Cypress.$.escapeSelector(dropTarget)}"]`
|
||||
)
|
||||
.trigger('drop', { dataTransfer })
|
||||
.trigger('dragend', { force: true });
|
||||
};
|
||||
|
||||
export const openDragDropDropdown = (name: string) => {
|
||||
cy.get(
|
||||
`[data-row-key=${name}] > .whitespace-nowrap > [data-testid="expand-icon"] > svg`
|
||||
).click();
|
||||
};
|
||||
@ -96,3 +96,25 @@ export const removeGlossaryTerm = (
|
||||
'[data-testid="entity-right-panel"] [data-testid="glossary-container"] [data-testid="add-tag"]'
|
||||
).should('be.visible');
|
||||
};
|
||||
|
||||
export const confirmationDragAndDropGlossary = (
|
||||
dragElement: string,
|
||||
dropElement: string,
|
||||
isHeader?: boolean
|
||||
) => {
|
||||
interceptURL('PATCH', `/api/v1/glossaryTerms/*`, 'patchGlossaryTerm');
|
||||
|
||||
// confirmation message before the transfer
|
||||
cy.get('[data-testid="confirmation-modal"] .ant-modal-body').contains(
|
||||
`Click on Confirm if you’d like to move ${
|
||||
isHeader
|
||||
? `${dragElement} under ${dropElement} .`
|
||||
: `${dragElement} term under ${dropElement} term.`
|
||||
}`
|
||||
);
|
||||
|
||||
// click on submit modal button to confirm the transfer
|
||||
cy.get('.ant-modal-footer > .ant-btn-primary').click();
|
||||
|
||||
verifyResponseStatusCode('@patchGlossaryTerm', 200);
|
||||
};
|
||||
|
||||
@ -0,0 +1,87 @@
|
||||
/*
|
||||
* Copyright 2024 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,
|
||||
toastNotification,
|
||||
verifyResponseStatusCode,
|
||||
} from '../common';
|
||||
|
||||
export const commonTeamDetails = {
|
||||
username: 'Aaron Johnson',
|
||||
userId: 'aaron_johnson0',
|
||||
assetname: 'dim_address',
|
||||
email: 'team1@gmail.com',
|
||||
updatedEmail: 'updatedemail@gmail.com',
|
||||
};
|
||||
export const confirmationDragAndDropTeam = (
|
||||
dragTeam: string,
|
||||
dropTeam: string
|
||||
) => {
|
||||
interceptURL('PUT', `/api/v1/teams`, 'putTeam');
|
||||
|
||||
// confirmation message before the transfer
|
||||
cy.get('[data-testid="confirmation-modal"] .ant-modal-body')
|
||||
.contains(
|
||||
`Click on Confirm if you’d like to move ${dragTeam} team under ${dropTeam} team.`
|
||||
)
|
||||
.should('be.visible');
|
||||
|
||||
// click on submit modal button to confirm the transfer
|
||||
cy.get('.ant-modal-footer > .ant-btn-primary').click();
|
||||
|
||||
verifyResponseStatusCode('@putTeam', 200);
|
||||
|
||||
toastNotification('Team moved successfully!');
|
||||
};
|
||||
|
||||
export const deleteTeamPermanently = (teamName: string) => {
|
||||
interceptURL('GET', `/api/v1/teams/name/${teamName}*`, 'getSelectedTeam');
|
||||
// Click on created team
|
||||
cy.get(`[data-row-key="${teamName}"]`).contains(teamName).click();
|
||||
|
||||
verifyResponseStatusCode('@getSelectedTeam', 200);
|
||||
cy.get(
|
||||
'[data-testid="team-detail-header"] [data-testid="manage-button"]'
|
||||
).click();
|
||||
|
||||
cy.get('[data-menu-id*="delete-button"]').should('be.visible');
|
||||
|
||||
cy.get('[data-testid="delete-button-title"]').click();
|
||||
|
||||
cy.get('[data-testid="confirm-button"]')
|
||||
.should('exist')
|
||||
.should('be.disabled');
|
||||
|
||||
// Check if soft delete option is present
|
||||
cy.get('[data-testid="soft-delete-option"]').should('contain', teamName);
|
||||
|
||||
// Click on permanent delete option
|
||||
cy.get('[data-testid="hard-delete-option"]')
|
||||
.should('contain', teamName)
|
||||
.click();
|
||||
|
||||
cy.get('[data-testid="confirmation-text-input"]').type('DELETE');
|
||||
|
||||
interceptURL('DELETE', '/api/v1/teams/*', 'deleteTeam');
|
||||
cy.get('[data-testid="confirm-button"]').click();
|
||||
|
||||
verifyResponseStatusCode('@deleteTeam', 200);
|
||||
|
||||
// Verify the toast message
|
||||
toastNotification(`"${teamName}" deleted successfully!`);
|
||||
|
||||
// Validating the deleted team
|
||||
|
||||
cy.get('table').should('not.contain', teamName);
|
||||
};
|
||||
@ -0,0 +1,168 @@
|
||||
/*
|
||||
* Copyright 2024 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 { addTeam, interceptURL, toastNotification } from '../../common/common';
|
||||
import {
|
||||
dragAndDropElement,
|
||||
openDragDropDropdown,
|
||||
} from '../../common/Utils/DragAndDrop';
|
||||
import {
|
||||
commonTeamDetails,
|
||||
confirmationDragAndDropTeam,
|
||||
deleteTeamPermanently,
|
||||
} from '../../common/Utils/Teams';
|
||||
import { uuid } from '../../constants/constants';
|
||||
import { SidebarItem } from '../../constants/Entity.interface';
|
||||
import { GlobalSettingOptions } from '../../constants/settings.constant';
|
||||
|
||||
const teamNameGroup = `team-ct-test-${uuid()}`;
|
||||
const teamNameBusiness = `team-ct-test-${uuid()}`;
|
||||
const teamNameDivision = `team-ct-test-${uuid()}`;
|
||||
const teamNameDepartment = `team-ct-test-${uuid()}`;
|
||||
|
||||
const TEAM_TYPE_BY_NAME = {
|
||||
[teamNameBusiness]: 'BusinessUnit',
|
||||
[teamNameDivision]: 'Division',
|
||||
[teamNameDepartment]: 'Department',
|
||||
[teamNameGroup]: 'Group',
|
||||
};
|
||||
|
||||
const DRAG_AND_DROP_TEAM_DETAILS = [
|
||||
{
|
||||
name: teamNameBusiness,
|
||||
updatedName: `${teamNameBusiness}-updated`,
|
||||
teamType: 'BusinessUnit',
|
||||
description: `This is ${teamNameBusiness} description`,
|
||||
...commonTeamDetails,
|
||||
},
|
||||
{
|
||||
name: teamNameDivision,
|
||||
updatedName: `${teamNameDivision}-updated`,
|
||||
teamType: 'Division',
|
||||
description: `This is ${teamNameDivision} description`,
|
||||
...commonTeamDetails,
|
||||
},
|
||||
{
|
||||
name: teamNameDepartment,
|
||||
updatedName: `${teamNameDepartment}-updated`,
|
||||
teamType: 'Department',
|
||||
description: `This is ${teamNameDepartment} description`,
|
||||
...commonTeamDetails,
|
||||
},
|
||||
{
|
||||
name: teamNameGroup,
|
||||
updatedName: `${teamNameGroup}-updated`,
|
||||
teamType: 'Group',
|
||||
description: `This is ${teamNameGroup} description`,
|
||||
...commonTeamDetails,
|
||||
},
|
||||
];
|
||||
|
||||
describe('Teams drag and drop should work properly', () => {
|
||||
beforeEach(() => {
|
||||
interceptURL('GET', `/api/v1/users?fields=*`, 'getUserDetails');
|
||||
interceptURL('GET', `/api/v1/permissions/team/name/*`, 'permissions');
|
||||
cy.login();
|
||||
|
||||
cy.sidebarClick(SidebarItem.SETTINGS);
|
||||
|
||||
// Clicking on teams
|
||||
cy.settingClick(GlobalSettingOptions.TEAMS);
|
||||
});
|
||||
|
||||
it('Add new team for drag and drop', () => {
|
||||
DRAG_AND_DROP_TEAM_DETAILS.map((team) => {
|
||||
addTeam(team);
|
||||
cy.reload();
|
||||
// asserting the added values
|
||||
cy.get(`[data-row-key="${team.name}"]`)
|
||||
.scrollIntoView()
|
||||
.should('be.visible');
|
||||
cy.get(`[data-row-key="${team.name}"]`).should(
|
||||
'contain',
|
||||
team.description
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
it('Should fail when drop team type is Group', () => {
|
||||
[teamNameBusiness, teamNameDepartment, teamNameDivision].map((team) => {
|
||||
dragAndDropElement(team, teamNameGroup);
|
||||
toastNotification(
|
||||
`You cannot move to this team as Team Type ${TEAM_TYPE_BY_NAME[team]} can't be Group children`
|
||||
);
|
||||
|
||||
cy.get('.Toastify__toast-body', { timeout: 10000 }).should('not.exist');
|
||||
});
|
||||
});
|
||||
|
||||
it('Should fail when droppable team type is Department', () => {
|
||||
[teamNameBusiness, teamNameDivision].map((team) => {
|
||||
dragAndDropElement(team, teamNameDepartment);
|
||||
toastNotification(
|
||||
`You cannot move to this team as Team Type ${TEAM_TYPE_BY_NAME[team]} can't be Department children`
|
||||
);
|
||||
cy.get('.Toastify__toast-body', { timeout: 10000 }).should('not.exist');
|
||||
});
|
||||
});
|
||||
|
||||
it('Should fail when draggable team type is BusinessUnit and droppable team type is Division', () => {
|
||||
dragAndDropElement(teamNameBusiness, teamNameDivision);
|
||||
toastNotification(
|
||||
`You cannot move to this team as Team Type BusinessUnit can't be Division children`
|
||||
);
|
||||
});
|
||||
|
||||
[teamNameBusiness, teamNameDivision, teamNameDepartment].map(
|
||||
(droppableTeamName, index) => {
|
||||
it(`Should drag and drop on ${TEAM_TYPE_BY_NAME[droppableTeamName]} team type`, () => {
|
||||
// nested team will be shown once anything is moved under it
|
||||
if (index !== 0) {
|
||||
openDragDropDropdown(
|
||||
[teamNameBusiness, teamNameDivision, teamNameDepartment][index - 1]
|
||||
);
|
||||
}
|
||||
|
||||
dragAndDropElement(teamNameGroup, droppableTeamName);
|
||||
|
||||
confirmationDragAndDropTeam(teamNameGroup, droppableTeamName);
|
||||
|
||||
// verify the team is moved under the business team
|
||||
openDragDropDropdown(droppableTeamName);
|
||||
cy.get(
|
||||
`.ant-table-row-level-1[data-row-key="${teamNameGroup}"]`
|
||||
).should('be.visible');
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
it(`Should drag and drop team on table level`, () => {
|
||||
// open department team dropdown as it is moved under it from last test
|
||||
openDragDropDropdown(teamNameDepartment);
|
||||
|
||||
dragAndDropElement(teamNameGroup, '.ant-table-thead > tr', true);
|
||||
confirmationDragAndDropTeam(teamNameGroup, 'Organization');
|
||||
|
||||
// verify the team is moved under the table level
|
||||
cy.get(`.ant-table-row-level-0[data-row-key="${teamNameGroup}"]`).should(
|
||||
'be.visible'
|
||||
);
|
||||
});
|
||||
|
||||
it('Permanently deleting a team for drag and drop', () => {
|
||||
[teamNameBusiness, teamNameDivision, teamNameDepartment, teamNameGroup].map(
|
||||
(teamName) => {
|
||||
deleteTeamPermanently(teamName);
|
||||
}
|
||||
);
|
||||
});
|
||||
});
|
||||
@ -28,26 +28,26 @@ describe(
|
||||
verifyResponseStatusCode('@getApplications', 200);
|
||||
});
|
||||
|
||||
it('Edit data insight application', () => {
|
||||
interceptURL(
|
||||
'GET',
|
||||
'/api/v1/apps/name/DataInsightsApplication?fields=*',
|
||||
'getDataInsightDetails'
|
||||
);
|
||||
interceptURL('PATCH', '/api/v1/apps/*', 'updateApplication');
|
||||
cy.get(
|
||||
'[data-testid="data-insights-application-card"] [data-testid="config-btn"]'
|
||||
).click();
|
||||
verifyResponseStatusCode('@getDataInsightDetails', 200);
|
||||
cy.get('[data-testid="edit-button"]').click();
|
||||
cy.get('[data-testid="cron-type"]').click();
|
||||
cy.get('.rc-virtual-list [title="Day"]').click();
|
||||
cy.get('[data-testid="hour-options"]').click();
|
||||
cy.get('[title="01"]').click();
|
||||
cy.get('.ant-modal-body [data-testid="deploy-button"]').click();
|
||||
verifyResponseStatusCode('@updateApplication', 200);
|
||||
cy.get('[data-testid="cron-string"]').should('contain', 'At 01:00 AM');
|
||||
});
|
||||
it('Edit data insight application', () => {
|
||||
interceptURL(
|
||||
'GET',
|
||||
'/api/v1/apps/name/DataInsightsApplication?fields=*',
|
||||
'getDataInsightDetails'
|
||||
);
|
||||
interceptURL('PATCH', '/api/v1/apps/*', 'updateApplication');
|
||||
cy.get(
|
||||
'[data-testid="data-insights-application-card"] [data-testid="config-btn"]'
|
||||
).click();
|
||||
verifyResponseStatusCode('@getDataInsightDetails', 200);
|
||||
cy.get('[data-testid="edit-button"]').click();
|
||||
cy.get('[data-testid="cron-type"]').click();
|
||||
cy.get('.rc-virtual-list [title="Day"]').click();
|
||||
cy.get('[data-testid="hour-options"]').click();
|
||||
cy.get('[title="01"]').click();
|
||||
cy.get('.ant-modal-body [data-testid="deploy-button"]').click();
|
||||
verifyResponseStatusCode('@updateApplication', 200);
|
||||
cy.get('[data-testid="cron-string"]').should('contain', 'At 01:00 AM');
|
||||
});
|
||||
|
||||
it('Uninstall application', () => {
|
||||
interceptURL(
|
||||
@ -75,27 +75,26 @@ describe(
|
||||
);
|
||||
});
|
||||
|
||||
it('Install application', () => {
|
||||
interceptURL('GET', '/api/v1/apps/marketplace?limit=*', 'getMarketPlace');
|
||||
interceptURL('POST', '/api/v1/apps', 'installApplication');
|
||||
cy.get('[data-testid="add-application"]').click();
|
||||
verifyResponseStatusCode('@getMarketPlace', 200);
|
||||
cy.get(
|
||||
'[data-testid="data-insights-application-card"] [data-testid="config-btn"]'
|
||||
).click();
|
||||
cy.get('[data-testid="install-application"]').click();
|
||||
cy.get('[data-testid="save-button"]').click();
|
||||
cy.get('[data-testid="cron-type"]').click();
|
||||
cy.get('.rc-virtual-list [title="Day"]').click();
|
||||
cy.get('[data-testid="cron-type"]').should('contain', 'Day');
|
||||
cy.get('[data-testid="deploy-button"]').click();
|
||||
verifyResponseStatusCode('@installApplication', 201);
|
||||
verifyResponseStatusCode('@getApplications', 200);
|
||||
cy.get('[data-testid="data-insights-application-card"]').should(
|
||||
'be.visible'
|
||||
);
|
||||
});
|
||||
|
||||
it('Install application', () => {
|
||||
interceptURL('GET', '/api/v1/apps/marketplace?limit=*', 'getMarketPlace');
|
||||
interceptURL('POST', '/api/v1/apps', 'installApplication');
|
||||
cy.get('[data-testid="add-application"]').click();
|
||||
verifyResponseStatusCode('@getMarketPlace', 200);
|
||||
cy.get(
|
||||
'[data-testid="data-insights-application-card"] [data-testid="config-btn"]'
|
||||
).click();
|
||||
cy.get('[data-testid="install-application"]').click();
|
||||
cy.get('[data-testid="save-button"]').click();
|
||||
cy.get('[data-testid="cron-type"]').click();
|
||||
cy.get('.rc-virtual-list [title="Day"]').click();
|
||||
cy.get('[data-testid="cron-type"]').should('contain', 'Day');
|
||||
cy.get('[data-testid="deploy-button"]').click();
|
||||
verifyResponseStatusCode('@installApplication', 201);
|
||||
verifyResponseStatusCode('@getApplications', 200);
|
||||
cy.get('[data-testid="data-insights-application-card"]').should(
|
||||
'be.visible'
|
||||
);
|
||||
});
|
||||
|
||||
it('Deploy & run application', () => {
|
||||
interceptURL(
|
||||
|
||||
@ -25,7 +25,9 @@ import {
|
||||
verifyResponseStatusCode,
|
||||
} from '../../common/common';
|
||||
import { deleteGlossary } from '../../common/GlossaryUtils';
|
||||
import { dragAndDropElement } from '../../common/Utils/DragAndDrop';
|
||||
import { visitEntityDetailsPage } from '../../common/Utils/Entity';
|
||||
import { confirmationDragAndDropGlossary } from '../../common/Utils/Glossary';
|
||||
import { addOwner, removeOwner } from '../../common/Utils/Owner';
|
||||
import {
|
||||
COLUMN_NAME_FOR_APPLY_GLOSSARY_TERM,
|
||||
@ -1223,6 +1225,50 @@ describe('Glossary page should work properly', { tags: 'Glossary' }, () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('Drag and Drop should work properly for glossary term', () => {
|
||||
selectActiveGlossary(NEW_GLOSSARY.name);
|
||||
|
||||
dragAndDropElement(
|
||||
NEW_GLOSSARY_TERMS.term_2.fullyQualifiedName,
|
||||
NEW_GLOSSARY_TERMS.term_1.fullyQualifiedName
|
||||
);
|
||||
|
||||
confirmationDragAndDropGlossary(
|
||||
NEW_GLOSSARY_TERMS.term_2.name,
|
||||
NEW_GLOSSARY_TERMS.term_1.name
|
||||
);
|
||||
|
||||
// verify the term is moved under the parent term
|
||||
cy.get(
|
||||
`.ant-table-row-level-1[data-row-key="${Cypress.$.escapeSelector(
|
||||
NEW_GLOSSARY_TERMS.term_1.fullyQualifiedName
|
||||
)}.${NEW_GLOSSARY_TERMS.term_2.name}"]`
|
||||
).should('be.visible');
|
||||
});
|
||||
|
||||
it('Drag and Drop should work properly for glossary term at table level', () => {
|
||||
selectActiveGlossary(NEW_GLOSSARY.name);
|
||||
|
||||
dragAndDropElement(
|
||||
`${NEW_GLOSSARY_TERMS.term_1.fullyQualifiedName}.${NEW_GLOSSARY_TERMS.term_2.name}`,
|
||||
'.ant-table-thead > tr',
|
||||
true
|
||||
);
|
||||
|
||||
confirmationDragAndDropGlossary(
|
||||
NEW_GLOSSARY_TERMS.term_2.name,
|
||||
NEW_GLOSSARY.name,
|
||||
true
|
||||
);
|
||||
|
||||
// verify the term is moved under the parent term
|
||||
cy.get(
|
||||
`.ant-table-row-level-0[data-row-key="${Cypress.$.escapeSelector(
|
||||
NEW_GLOSSARY_TERMS.term_2.fullyQualifiedName
|
||||
)}"]`
|
||||
).should('be.visible');
|
||||
});
|
||||
|
||||
it('Delete glossary term should work properly', () => {
|
||||
const terms = Object.values(NEW_GLOSSARY_TERMS);
|
||||
selectActiveGlossary(NEW_GLOSSARY.name);
|
||||
|
||||
@ -23,6 +23,7 @@ import {
|
||||
uuid,
|
||||
verifyResponseStatusCode,
|
||||
} from '../../common/common';
|
||||
import { deleteTeamPermanently } from '../../common/Utils/Teams';
|
||||
import { SidebarItem } from '../../constants/Entity.interface';
|
||||
import { GlobalSettingOptions } from '../../constants/settings.constant';
|
||||
|
||||
@ -394,55 +395,6 @@ describe('Teams flow should work properly', () => {
|
||||
it('Permanently deleting a team without soft deleting should work properly', () => {
|
||||
// Add a new team
|
||||
addTeam(HARD_DELETE_TEAM_DETAILS);
|
||||
|
||||
interceptURL(
|
||||
'GET',
|
||||
`/api/v1/teams/name/${HARD_DELETE_TEAM_DETAILS.name}*`,
|
||||
'getSelectedTeam'
|
||||
);
|
||||
// Click on created team
|
||||
cy.get(`[data-row-key="${HARD_DELETE_TEAM_DETAILS.name}"]`)
|
||||
.contains(HARD_DELETE_TEAM_DETAILS.name)
|
||||
.click();
|
||||
|
||||
verifyResponseStatusCode('@getSelectedTeam', 200);
|
||||
cy.get(
|
||||
'[data-testid="team-detail-header"] [data-testid="manage-button"]'
|
||||
).click();
|
||||
|
||||
cy.get('[data-menu-id*="delete-button"]').should('be.visible');
|
||||
|
||||
cy.get('[data-testid="delete-button-title"]').click();
|
||||
|
||||
cy.get('[data-testid="confirm-button"]')
|
||||
.should('exist')
|
||||
.should('be.disabled');
|
||||
|
||||
// Check if soft delete option is present
|
||||
cy.get('[data-testid="soft-delete-option"]').should(
|
||||
'contain',
|
||||
HARD_DELETE_TEAM_DETAILS.name
|
||||
);
|
||||
|
||||
// Click on permanent delete option
|
||||
cy.get('[data-testid="hard-delete-option"]')
|
||||
.should('contain', HARD_DELETE_TEAM_DETAILS.name)
|
||||
.click();
|
||||
|
||||
cy.get('[data-testid="confirmation-text-input"]').type('DELETE');
|
||||
|
||||
interceptURL('DELETE', '/api/v1/teams/*', 'deleteTeam');
|
||||
cy.get('[data-testid="confirm-button"]').click();
|
||||
|
||||
verifyResponseStatusCode('@deleteTeam', 200);
|
||||
|
||||
// Verify the toast message
|
||||
toastNotification(
|
||||
`"${HARD_DELETE_TEAM_DETAILS.name}" deleted successfully!`
|
||||
);
|
||||
|
||||
// Validating the deleted team
|
||||
|
||||
cy.get('table').should('not.contain', HARD_DELETE_TEAM_DETAILS.name);
|
||||
deleteTeamPermanently(HARD_DELETE_TEAM_DETAILS.name);
|
||||
});
|
||||
});
|
||||
|
||||
@ -21,6 +21,7 @@ import RedshiftWithDBTIngestionClass from '../../common/Services/RedshiftWithDBT
|
||||
import S3IngestionClass from '../../common/Services/S3IngestionClass';
|
||||
import SnowflakeIngestionClass from '../../common/Services/SnowflakeIngestionClass';
|
||||
import SupersetIngestionClass from '../../common/Services/SupersetIngestionClass';
|
||||
import { goToServiceListingPage } from '../../common/Utils/Services';
|
||||
|
||||
const services = [
|
||||
new S3IngestionClass(),
|
||||
|
||||
@ -39,6 +39,7 @@ jest.mock('react-router-dom', () => ({
|
||||
|
||||
jest.mock('../../../../utils/TeamUtils', () => ({
|
||||
getMovedTeamData: jest.fn().mockReturnValue([]),
|
||||
isDropRestricted: jest.fn().mockReturnValue(false),
|
||||
}));
|
||||
|
||||
jest.mock('../../../../rest/teamsAPI', () => ({
|
||||
|
||||
@ -12,10 +12,11 @@
|
||||
*/
|
||||
|
||||
import { Modal, Skeleton, Typography } from 'antd';
|
||||
import { ColumnsType } from 'antd/lib/table';
|
||||
import { ColumnsType, TableProps } from 'antd/lib/table';
|
||||
import { ExpandableConfig } from 'antd/lib/table/interface';
|
||||
import { AxiosError } from 'axios';
|
||||
import { isEmpty } from 'lodash';
|
||||
import classNames from 'classnames';
|
||||
import { isEmpty, isUndefined } from 'lodash';
|
||||
import React, { FC, useCallback, useMemo, useState } from 'react';
|
||||
import { DndProvider } from 'react-dnd';
|
||||
import { HTML5Backend } from 'react-dnd-html5-backend';
|
||||
@ -26,7 +27,6 @@ import {
|
||||
NO_DATA_PLACEHOLDER,
|
||||
} from '../../../../constants/constants';
|
||||
import { TABLE_CONSTANTS } from '../../../../constants/Teams.constants';
|
||||
import { TeamType } from '../../../../generated/api/teams/createTeam';
|
||||
import { Team } from '../../../../generated/entity/teams/team';
|
||||
import { Include } from '../../../../generated/type/include';
|
||||
import { getTeamByName, updateTeam } from '../../../../rest/teamsAPI';
|
||||
@ -34,7 +34,10 @@ import { Transi18next } from '../../../../utils/CommonUtils';
|
||||
import { getEntityName } from '../../../../utils/EntityUtils';
|
||||
import { getTeamsWithFqnPath } from '../../../../utils/RouterUtils';
|
||||
import { getTableExpandableConfig } from '../../../../utils/TableUtils';
|
||||
import { getMovedTeamData } from '../../../../utils/TeamUtils';
|
||||
import {
|
||||
getMovedTeamData,
|
||||
isDropRestricted,
|
||||
} from '../../../../utils/TeamUtils';
|
||||
import { showErrorToast, showSuccessToast } from '../../../../utils/ToastUtils';
|
||||
import { DraggableBodyRowProps } from '../../../common/Draggable/DraggableBodyRowProps.interface';
|
||||
import FilterTablePlaceHolder from '../../../common/ErrorWithPlaceholder/FilterTablePlaceHolder';
|
||||
@ -53,6 +56,7 @@ const TeamHierarchy: FC<TeamHierarchyProps> = ({
|
||||
const [isModalOpen, setIsModalOpen] = useState<boolean>(false);
|
||||
const [isTableLoading, setIsTableLoading] = useState<boolean>(false);
|
||||
const [movedTeam, setMovedTeam] = useState<MovedTeamProps>();
|
||||
const [isTableHovered, setIsTableHovered] = useState(false);
|
||||
|
||||
const columns: ColumnsType<Team> = useMemo(() => {
|
||||
return [
|
||||
@ -143,14 +147,27 @@ const TeamHierarchy: FC<TeamHierarchyProps> = ({
|
||||
];
|
||||
}, [data, isFetchingAllTeamAdvancedDetails, onTeamExpand]);
|
||||
|
||||
const handleTableHover = useCallback(
|
||||
(value: boolean) => setIsTableHovered(value),
|
||||
[]
|
||||
);
|
||||
|
||||
const handleMoveRow = useCallback(
|
||||
async (dragRecord: Team, dropRecord: Team) => {
|
||||
if (dragRecord.id === dropRecord.id) {
|
||||
async (dragRecord: Team, dropRecord?: Team) => {
|
||||
if (dragRecord.id === dropRecord?.id) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (dropRecord.teamType === TeamType.Group) {
|
||||
showErrorToast(t('message.error-team-transfer-message'));
|
||||
if (
|
||||
!isUndefined(dropRecord) &&
|
||||
isDropRestricted(dragRecord.teamType, dropRecord?.teamType)
|
||||
) {
|
||||
showErrorToast(
|
||||
t('message.error-team-transfer-message', {
|
||||
dragTeam: dragRecord.teamType,
|
||||
dropTeam: dropRecord.teamType,
|
||||
})
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
@ -167,11 +184,14 @@ const TeamHierarchy: FC<TeamHierarchyProps> = ({
|
||||
if (movedTeam) {
|
||||
setIsTableLoading(true);
|
||||
try {
|
||||
const dropTeam = movedTeam.to?.id;
|
||||
const data = await getTeamByName(movedTeam.from.name, {
|
||||
fields: 'users, defaultRoles, policies, owner, parents, children',
|
||||
include: Include.All,
|
||||
});
|
||||
await updateTeam(getMovedTeamData(data, [movedTeam.to.id]));
|
||||
await updateTeam(
|
||||
getMovedTeamData(data, dropTeam ? [dropTeam] : undefined)
|
||||
);
|
||||
onTeamExpand(true, currentTeam?.name);
|
||||
showSuccessToast(t('message.team-moved-success'));
|
||||
} catch (error) {
|
||||
@ -179,12 +199,29 @@ const TeamHierarchy: FC<TeamHierarchyProps> = ({
|
||||
} finally {
|
||||
setIsTableLoading(false);
|
||||
setIsModalOpen(false);
|
||||
setIsTableHovered(false);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const onTableRow = (record: Team, index?: number) =>
|
||||
({ index, handleMoveRow, record } as DraggableBodyRowProps<Team>);
|
||||
({
|
||||
index,
|
||||
handleMoveRow,
|
||||
handleTableHover,
|
||||
record,
|
||||
} as DraggableBodyRowProps<Team>);
|
||||
|
||||
const onTableHeader: TableProps<Team>['onHeaderRow'] = () =>
|
||||
({
|
||||
handleMoveRow,
|
||||
handleTableHover,
|
||||
} as DraggableBodyRowProps<Team>);
|
||||
|
||||
const onDragConfirmationModalClose = useCallback(() => {
|
||||
setIsModalOpen(false);
|
||||
setIsTableHovered(false);
|
||||
}, []);
|
||||
|
||||
const expandableConfig: ExpandableConfig<Team> = useMemo(
|
||||
() => ({
|
||||
@ -203,7 +240,9 @@ const TeamHierarchy: FC<TeamHierarchyProps> = ({
|
||||
<DndProvider backend={HTML5Backend}>
|
||||
<Table
|
||||
bordered
|
||||
className="teams-list-table"
|
||||
className={classNames('teams-list-table drop-over-background', {
|
||||
'drop-over-table': isTableHovered,
|
||||
})}
|
||||
columns={columns}
|
||||
components={TABLE_CONSTANTS}
|
||||
data-testid="team-hierarchy-table"
|
||||
@ -216,6 +255,7 @@ const TeamHierarchy: FC<TeamHierarchyProps> = ({
|
||||
pagination={false}
|
||||
rowKey="name"
|
||||
size="small"
|
||||
onHeaderRow={onTableHeader}
|
||||
onRow={onTableRow}
|
||||
/>
|
||||
</DndProvider>
|
||||
@ -230,14 +270,14 @@ const TeamHierarchy: FC<TeamHierarchyProps> = ({
|
||||
okText={t('label.confirm')}
|
||||
open={isModalOpen}
|
||||
title={t('label.move-the-entity', { entity: t('label.team') })}
|
||||
onCancel={() => setIsModalOpen(false)}
|
||||
onCancel={onDragConfirmationModalClose}
|
||||
onOk={handleChangeTeam}>
|
||||
<Transi18next
|
||||
i18nKey="message.entity-transfer-message"
|
||||
renderElement={<strong />}
|
||||
values={{
|
||||
from: movedTeam?.from?.name,
|
||||
to: movedTeam?.to?.name,
|
||||
from: movedTeam?.from.name,
|
||||
to: movedTeam?.to?.name ?? getEntityName(currentTeam),
|
||||
entity: t('label.team-lowercase'),
|
||||
}}
|
||||
/>
|
||||
|
||||
@ -30,7 +30,7 @@ export interface TeamHierarchyProps {
|
||||
|
||||
export interface MovedTeamProps {
|
||||
from: Team;
|
||||
to: Team;
|
||||
to?: Team;
|
||||
}
|
||||
|
||||
export interface TableExpandableDataProps {
|
||||
|
||||
@ -20,7 +20,7 @@ export interface DraggableBodyRowProps<T>
|
||||
extends React.HTMLAttributes<HTMLTableRowElement> {
|
||||
index?: number;
|
||||
record?: T;
|
||||
handleMoveRow: (dragRecord: T, dropRecord?: T) => void;
|
||||
handleMoveRow: (dragRecord: T, dropRecord?: T) => Promise<void>;
|
||||
handleTableHover?: (value: boolean) => void;
|
||||
}
|
||||
|
||||
|
||||
@ -1403,7 +1403,7 @@
|
||||
"entity-size-in-between": "{{entity}} Größe muss zwischen {{min}} und {{max}} liegen.",
|
||||
"entity-size-must-be-between-2-and-64": "{{entity}} Größe muss zwischen 2 und 64 liegen.",
|
||||
"entity-transfer-message": "Klicken Sie auf Bestätigen, wenn Sie {{entity}} von <0>{{from}}</0> unter <0>{{to}}</0> {{entity}} verschieben möchten.",
|
||||
"error-team-transfer-message": "Sie können nicht zu diesem Team wechseln, da Teamtyp 'Gruppe' keine untergeordneten Teams haben kann.",
|
||||
"error-team-transfer-message": "You cannot move to this team as Team Type {{dragTeam}} can't be {{dropTeam}} children",
|
||||
"error-while-fetching-access-token": "Fehler beim Abrufen des Zugriffstokens.",
|
||||
"explore-our-guide-here": "explore our guide here.",
|
||||
"export-entity-help": "Laden Sie alle Ihre {{entity}} als CSV-Datei herunter und teilen Sie sie mit Ihrem Team.",
|
||||
|
||||
@ -1403,7 +1403,7 @@
|
||||
"entity-size-in-between": "{{entity}} size must be between {{min}} and {{max}}",
|
||||
"entity-size-must-be-between-2-and-64": "{{entity}} size must be between 2 and 64",
|
||||
"entity-transfer-message": "Click on Confirm if you’d like to move <0>{{from}}</0> {{entity}} under <0>{{to}}</0> {{entity}}.",
|
||||
"error-team-transfer-message": "You cannot move to this team as Team Type Group cannot have children",
|
||||
"error-team-transfer-message": "You cannot move to this team as Team Type {{dragTeam}} can't be {{dropTeam}} children",
|
||||
"error-while-fetching-access-token": "Error while fetching access token.",
|
||||
"explore-our-guide-here": "explore our guide here.",
|
||||
"export-entity-help": "Download all your {{entity}} as a CSV file, and share with your team.",
|
||||
|
||||
@ -1403,7 +1403,7 @@
|
||||
"entity-size-in-between": "El tamaño de {{entity}} debe estar entre {{min}} y {{max}}",
|
||||
"entity-size-must-be-between-2-and-64": "El tamaño de {{entity}} debe estar entre 2 y 64",
|
||||
"entity-transfer-message": "Haga clic en Confirmar si desea mover <0>{{from}}</0> {{entity}} debajo de <0>{{to}}</0> {{entity}}.",
|
||||
"error-team-transfer-message": "No puede mover a este equipo ya que el tipo de equipo \"Grupo\" no puede tener hijos",
|
||||
"error-team-transfer-message": "You cannot move to this team as Team Type {{dragTeam}} can't be {{dropTeam}} children",
|
||||
"error-while-fetching-access-token": "Error al obtener el token de acceso.",
|
||||
"explore-our-guide-here": "explore our guide here.",
|
||||
"export-entity-help": "Download all your {{entity}} as a CSV file, and share with your team.",
|
||||
|
||||
@ -1403,7 +1403,7 @@
|
||||
"entity-size-in-between": "{{entity}} taille doit être de {{min}} et {{max}}",
|
||||
"entity-size-must-be-between-2-and-64": "{{entity}} taille doit être comprise entre 2 et 64",
|
||||
"entity-transfer-message": "Cliquer sur Confirmer si vous souhaitez déplacer <0>{{from}}</0> {{entity}} sous <0>{{to}}</0> {{entity}}.",
|
||||
"error-team-transfer-message": "Vous ne pouvez pas déplacer cette équipe car le type d'équipe Groupe ne peut pas eêtre changé. Merci de créer une nouvelle équipe avec le type préférentiel.",
|
||||
"error-team-transfer-message": "You cannot move to this team as Team Type {{dragTeam}} can't be {{dropTeam}} children",
|
||||
"error-while-fetching-access-token": "Erreur pendant la récupération du jeton d'accès.",
|
||||
"explore-our-guide-here": "explore our guide here.",
|
||||
"export-entity-help": "Download all your {{entity}} as a CSV file, and share with your team.",
|
||||
|
||||
@ -1403,7 +1403,7 @@
|
||||
"entity-size-in-between": "{{entity}} יכול להיות בגודל בין {{min}} ל-{{max}}",
|
||||
"entity-size-must-be-between-2-and-64": "{{entity}} יכול להיות בגודל בין 2 ל-64",
|
||||
"entity-transfer-message": "לחץ על אישור אם ברצונך להעביר <0>{{from}}</0> {{entity}} מתחת ל-<0>{{to}}</0> {{entity}}.",
|
||||
"error-team-transfer-message": "אין אפשרות להעביר לצוות זה כיוון שצוות מסוג קבוצה לא יכולים לכלול ילדים",
|
||||
"error-team-transfer-message": "You cannot move to this team as Team Type {{dragTeam}} can't be {{dropTeam}} children",
|
||||
"error-while-fetching-access-token": "שגיאה בעת קבלת טוקן גישה.",
|
||||
"explore-our-guide-here": "explore our guide here.",
|
||||
"export-entity-help": "הורד את כל הישויות שלך בפורמט קובץ CSV ושתף עם הצוות שלך.",
|
||||
|
||||
@ -1403,7 +1403,7 @@
|
||||
"entity-size-in-between": "{{entity}}のサイズは{{min}}以上{{max}}以下にしてください",
|
||||
"entity-size-must-be-between-2-and-64": "{{entity}}のサイズは2以上64以下",
|
||||
"entity-transfer-message": "Click on Confirm if you’d like to move <0>{{from}}</0> {{entity}} under <0>{{to}}</0> {{entity}}.",
|
||||
"error-team-transfer-message": "You cannot move to this team as Team Type Group cannot have children",
|
||||
"error-team-transfer-message": "You cannot move to this team as Team Type {{dragTeam}} can't be {{dropTeam}} children",
|
||||
"error-while-fetching-access-token": "アクセストークンの取得中にエラーが発生しました。",
|
||||
"explore-our-guide-here": "explore our guide here.",
|
||||
"export-entity-help": "Download all your {{entity}} as a CSV file, and share with your team.",
|
||||
|
||||
@ -1403,7 +1403,7 @@
|
||||
"entity-size-in-between": "{{entity}} grootte moet tussen {{min}} en {{max}} liggen",
|
||||
"entity-size-must-be-between-2-and-64": "{{entity}} grootte moet tussen 2 en 64 liggen",
|
||||
"entity-transfer-message": "Klik op Bevestigen als je <0>{{from}}</0> {{entity}} wilt verplaatsen naar <0>{{to}}</0> {{entity}}.",
|
||||
"error-team-transfer-message": "Je kunt niet naar dit team verplaatsen, omdat een groep van het teamtype geen kinderen kan hebben",
|
||||
"error-team-transfer-message": "You cannot move to this team as Team Type {{dragTeam}} can't be {{dropTeam}} children",
|
||||
"error-while-fetching-access-token": "Fout bij het ophalen van toegangstoken.",
|
||||
"explore-our-guide-here": "bekijk onze handleiding hier.",
|
||||
"export-entity-help": "Download al je {{entity}} als een CSV-bestand en deel het met je team.",
|
||||
|
||||
@ -1403,7 +1403,7 @@
|
||||
"entity-size-in-between": "O tamanho de {{entity}} deve ser entre {{min}} e {{max}}",
|
||||
"entity-size-must-be-between-2-and-64": "O tamanho de {{entity}} deve ser entre 2 e 64",
|
||||
"entity-transfer-message": "Clique em Confirmar se deseja mover <0>{{from}}</0> {{entity}} para <0>{{to}}</0> {{entity}}.",
|
||||
"error-team-transfer-message": "Você não pode mover para esta equipe, pois o Tipo de Equipe Grupo não pode ter filhos",
|
||||
"error-team-transfer-message": "You cannot move to this team as Team Type {{dragTeam}} can't be {{dropTeam}} children",
|
||||
"error-while-fetching-access-token": "Erro ao buscar token de acesso.",
|
||||
"explore-our-guide-here": "explore our guide here.",
|
||||
"export-entity-help": "Baixe todos os seus {{entity}} como um arquivo CSV e compartilhe com sua equipe.",
|
||||
|
||||
@ -1403,7 +1403,7 @@
|
||||
"entity-size-in-between": "Размер {{entity}} должен быть между {{min}} и {{max}}",
|
||||
"entity-size-must-be-between-2-and-64": "Размер {{entity}} должен быть от 2 до 64",
|
||||
"entity-transfer-message": "Нажмите «Подтвердить», если вы хотите переместить <0>{{from}}</0> {{entity}} в <0>{{to}}</0> {{entity}}.",
|
||||
"error-team-transfer-message": "Вы не можете перейти в эту команду, так как в группе данного типа не может быть дочерних элементов",
|
||||
"error-team-transfer-message": "You cannot move to this team as Team Type {{dragTeam}} can't be {{dropTeam}} children",
|
||||
"error-while-fetching-access-token": "Ошибка при получении токена доступа.",
|
||||
"explore-our-guide-here": "explore our guide here.",
|
||||
"export-entity-help": "Загрузите все свои {{entity}} в виде CSV-файла и поделитесь ими со своей командой.",
|
||||
|
||||
@ -1403,7 +1403,7 @@
|
||||
"entity-size-in-between": "{{entity}}大小须介于{{min}}和{{max}}之间",
|
||||
"entity-size-must-be-between-2-and-64": "{{entity}}大小必须介于2和64之间",
|
||||
"entity-transfer-message": "如果您想将<0>{{from}}</0> {{entity}} 移动到<0>{{to}}</0> {{entity}}中,请单击确认",
|
||||
"error-team-transfer-message": "由于团队类型的组不能有子级,因此您无法移动到此团队",
|
||||
"error-team-transfer-message": "You cannot move to this team as Team Type {{dragTeam}} can't be {{dropTeam}} children",
|
||||
"error-while-fetching-access-token": "获取访问令牌时出现错误",
|
||||
"explore-our-guide-here": "explore our guide here.",
|
||||
"export-entity-help": "以 CSV 文件格式导出下载所有{{entity}},并可与团队共享。",
|
||||
|
||||
@ -91,7 +91,7 @@
|
||||
.drop-over-background {
|
||||
.drop-over-child {
|
||||
td {
|
||||
background: @active-color;
|
||||
background: @active-color !important;
|
||||
border: 2px dashed @primary-color;
|
||||
border-left: transparent;
|
||||
|
||||
@ -113,7 +113,7 @@
|
||||
border: 2px dashed @primary-color;
|
||||
|
||||
td {
|
||||
background: @active-color;
|
||||
background: @active-color !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,112 @@
|
||||
/*
|
||||
* Copyright 2024 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 { TeamType } from '../generated/entity/teams/team';
|
||||
import { isDropRestricted } from './TeamUtils';
|
||||
|
||||
describe('isDropRestricted', () => {
|
||||
it('should be droppable if on drop team is BusinessUnit', () => {
|
||||
const groupDragResult = isDropRestricted(
|
||||
TeamType.Group,
|
||||
TeamType.BusinessUnit
|
||||
);
|
||||
|
||||
expect(groupDragResult).toBe(false);
|
||||
|
||||
const departmentDragResult = isDropRestricted(
|
||||
TeamType.Department,
|
||||
TeamType.BusinessUnit
|
||||
);
|
||||
|
||||
expect(departmentDragResult).toBe(false);
|
||||
|
||||
const divisionDragResult = isDropRestricted(
|
||||
TeamType.Division,
|
||||
TeamType.BusinessUnit
|
||||
);
|
||||
|
||||
expect(divisionDragResult).toBe(false);
|
||||
});
|
||||
|
||||
it('should not be droppable if on drop team team is Group', () => {
|
||||
const businessUnitDragResult = isDropRestricted(
|
||||
TeamType.BusinessUnit,
|
||||
TeamType.Group
|
||||
);
|
||||
|
||||
expect(businessUnitDragResult).toBe(true);
|
||||
|
||||
const departmentDragResult = isDropRestricted(
|
||||
TeamType.Department,
|
||||
TeamType.Group
|
||||
);
|
||||
|
||||
expect(departmentDragResult).toBe(true);
|
||||
|
||||
const divisionDragResult = isDropRestricted(
|
||||
TeamType.Division,
|
||||
TeamType.Group
|
||||
);
|
||||
|
||||
expect(divisionDragResult).toBe(true);
|
||||
});
|
||||
|
||||
// For Division TeamType
|
||||
it('should not be droppable if on drop team is Division', () => {
|
||||
const businessUnitDragResult = isDropRestricted(
|
||||
TeamType.BusinessUnit,
|
||||
TeamType.Division
|
||||
);
|
||||
|
||||
expect(businessUnitDragResult).toBe(true);
|
||||
});
|
||||
|
||||
it('should be droppable if on drop team is Division', () => {
|
||||
const departmentDragResult = isDropRestricted(
|
||||
TeamType.Department,
|
||||
TeamType.Division
|
||||
);
|
||||
|
||||
expect(departmentDragResult).toBe(false);
|
||||
|
||||
const groupDragResult = isDropRestricted(TeamType.Group, TeamType.Division);
|
||||
|
||||
expect(groupDragResult).toBe(false);
|
||||
});
|
||||
|
||||
// For Department TeamType
|
||||
it('should not be droppable if on drop team is Department', () => {
|
||||
const businessUnitDragResult = isDropRestricted(
|
||||
TeamType.BusinessUnit,
|
||||
TeamType.Department
|
||||
);
|
||||
|
||||
expect(businessUnitDragResult).toBe(true);
|
||||
|
||||
const divisionDragResult = isDropRestricted(
|
||||
TeamType.Division,
|
||||
TeamType.Department
|
||||
);
|
||||
|
||||
expect(divisionDragResult).toBe(true);
|
||||
});
|
||||
|
||||
it('should be droppable if on drop team is Department', () => {
|
||||
const groupDragResult = isDropRestricted(
|
||||
TeamType.Group,
|
||||
TeamType.Department
|
||||
);
|
||||
|
||||
expect(groupDragResult).toBe(false);
|
||||
});
|
||||
});
|
||||
@ -57,7 +57,10 @@ const getEntityValue = (value: EntityReference[] | undefined) => {
|
||||
return undefined;
|
||||
};
|
||||
|
||||
export const getMovedTeamData = (team: Team, parents: string[]): CreateTeam => {
|
||||
export const getMovedTeamData = (
|
||||
team: Team,
|
||||
parents?: string[]
|
||||
): CreateTeam => {
|
||||
const userDetails = omit(cloneDeep(team), [
|
||||
'id',
|
||||
'fullyQualifiedName',
|
||||
@ -84,7 +87,7 @@ export const getMovedTeamData = (team: Team, parents: string[]): CreateTeam => {
|
||||
userDetails.teamType === TeamType.Group
|
||||
? undefined
|
||||
: getEntityValue(children),
|
||||
parents: parents,
|
||||
parents,
|
||||
policies: getEntityValue(policies),
|
||||
users: getEntityValue(users),
|
||||
} as CreateTeam;
|
||||
@ -126,3 +129,21 @@ export const getTeamOptionsFromType = (parentType: TeamType) => {
|
||||
return [TeamType.Group];
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Restricting the drop of team based on the team type
|
||||
* Group: Can't have any child team
|
||||
* Division: Can have only Department and Group
|
||||
* Department: Can have only Group
|
||||
*/
|
||||
|
||||
export const isDropRestricted = (
|
||||
dragTeamType?: TeamType,
|
||||
dropTeamType?: TeamType
|
||||
) =>
|
||||
dropTeamType === TeamType.Group ||
|
||||
(dropTeamType === TeamType.Division &&
|
||||
dragTeamType === TeamType.BusinessUnit) ||
|
||||
(dropTeamType === TeamType.Department &&
|
||||
dragTeamType === TeamType.BusinessUnit) ||
|
||||
(dropTeamType === TeamType.Department && dragTeamType === TeamType.Division);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user