Fix #15438: Update filters and destination for 'Conversation' source in notification alert (#15443)

* Add 'Mentions' enum for subscriptionCategory

* fix the user list selection field not showing for 'Mentioned Users' filter

* update the cypress for new changes

* fix teams not showing in the mention suggestions
This commit is contained in:
Aniket Katkar 2024-03-04 21:40:31 +05:30 committed by GitHub
parent 7b5f36b374
commit 110e7a4f4b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 943 additions and 790 deletions

View File

@ -86,6 +86,7 @@
"Admins", "Admins",
"Assignees", "Assignees",
"Owners", "Owners",
"Mentions",
"Followers", "Followers",
"External" "External"
] ]

View File

@ -127,7 +127,8 @@ export const addEventTypeFilter = (
} }
}; };
export const addUpdaterNameFilter = ( export const addFilterWithUsersListInput = (
filterTestId,
filterNumber, filterNumber,
updaterName, updaterName,
exclude = false exclude = false
@ -136,9 +137,7 @@ export const addUpdaterNameFilter = (
cy.get(`[data-testid="filter-select-${filterNumber}"]`).click({ cy.get(`[data-testid="filter-select-${filterNumber}"]`).click({
waitForAnimations: true, waitForAnimations: true,
}); });
cy.get('[data-testid="Updater Name-filter-option"]') cy.get(`[data-testid="${filterTestId}"]`).filter(':visible').click();
.filter(':visible')
.click();
// Search and select user // Search and select user
interceptURL('GET', `/api/v1/search/query?q=*`, 'getSearchResult'); interceptURL('GET', `/api/v1/search/query?q=*`, 'getSearchResult');

View File

@ -19,10 +19,10 @@ import {
addEntityFQNFilter, addEntityFQNFilter,
addEventTypeFilter, addEventTypeFilter,
addExternalDestination, addExternalDestination,
addFilterWithUsersListInput,
addGMEFilter, addGMEFilter,
addInternalDestination, addInternalDestination,
addOwnerFilter, addOwnerFilter,
addUpdaterNameFilter,
deleteAlertSteps, deleteAlertSteps,
verifyAlertDetails, verifyAlertDetails,
} from '../../common/AlertUtils'; } from '../../common/AlertUtils';
@ -54,380 +54,495 @@ const SOURCE_NAME_2 = 'dashboard';
const SOURCE_DISPLAY_NAME_2 = 'Dashboard'; const SOURCE_DISPLAY_NAME_2 = 'Dashboard';
const SOURCE_NAME_3 = 'task'; const SOURCE_NAME_3 = 'task';
const SOURCE_DISPLAY_NAME_3 = 'Task'; const SOURCE_DISPLAY_NAME_3 = 'Task';
const SOURCE_NAME_4 = 'conversation';
const SOURCE_DISPLAY_NAME_4 = 'Conversation';
describe('Notification Alert Flow', { tags: 'Settings' }, () => { describe(
const data = { 'Notification Alert Flow',
user: { { tags: ['Settings', 'Observability'] },
displayName: '', () => {
}, const data = {
domain: { user: {
name: '', displayName: '',
}, },
alertDetails: { domain: {
id: '', name: '',
}, },
}; alertDetails: {
id: '',
},
};
before(() => { before(() => {
cy.login(); cy.login();
cy.getAllLocalStorage().then((storageData) => { cy.getAllLocalStorage().then((storageData) => {
const token = Object.values(storageData)[0].oidcIdToken; const token = Object.values(storageData)[0].oidcIdToken;
// Create a dashboard // Create a dashboard
createSingleLevelEntity({ createSingleLevelEntity({
token, token,
...DASHBOARD_SERVICE, ...DASHBOARD_SERVICE,
}); });
// Create a new user // Create a new user
cy.request({ cy.request({
method: 'POST', method: 'POST',
url: `/api/v1/users/signup`, url: `/api/v1/users/signup`,
headers: { Authorization: `Bearer ${token}` }, headers: { Authorization: `Bearer ${token}` },
body: USER_DETAILS, body: USER_DETAILS,
}).then((response) => { }).then((response) => {
data.user = response.body; data.user = response.body;
}); });
// Create a domain // Create a domain
cy.request({ cy.request({
method: 'PUT', method: 'PUT',
url: `/api/v1/domains`, url: `/api/v1/domains`,
headers: { Authorization: `Bearer ${token}` }, headers: { Authorization: `Bearer ${token}` },
body: DOMAIN_CREATION_DETAILS, body: DOMAIN_CREATION_DETAILS,
}).then((response) => { }).then((response) => {
data.domain = response.body; data.domain = response.body;
});
}); });
}); });
});
after(() => { after(() => {
cy.login(); cy.login();
cy.getAllLocalStorage().then((storageData) => { cy.getAllLocalStorage().then((storageData) => {
const token = Object.values(storageData)[0].oidcIdToken; const token = Object.values(storageData)[0].oidcIdToken;
hardDeleteService({ hardDeleteService({
token, token,
serviceFqn: DASHBOARD_SERVICE.service.name, serviceFqn: DASHBOARD_SERVICE.service.name,
serviceType: DASHBOARD_SERVICE.serviceType, serviceType: DASHBOARD_SERVICE.serviceType,
}); });
// Delete created domain // Delete created domain
cy.request({ cy.request({
method: 'DELETE', method: 'DELETE',
url: `/api/v1/domains/name/${DOMAIN_CREATION_DETAILS.name}`, url: `/api/v1/domains/name/${DOMAIN_CREATION_DETAILS.name}`,
headers: { Authorization: `Bearer ${token}` }, headers: { Authorization: `Bearer ${token}` },
}); });
// Delete created user // Delete created user
cy.request({ cy.request({
method: 'DELETE', method: 'DELETE',
url: `/api/v1/users/${data.user.id}?hardDelete=true&recursive=false`, url: `/api/v1/users/${data.user.id}?hardDelete=true&recursive=false`,
headers: { Authorization: `Bearer ${token}` }, headers: { Authorization: `Bearer ${token}` },
});
}); });
}); });
});
beforeEach(() => { beforeEach(() => {
interceptURL('POST', '/api/v1/events/subscriptions', 'createAlert'); interceptURL('POST', '/api/v1/events/subscriptions', 'createAlert');
interceptURL('PUT', '/api/v1/events/subscriptions', 'updateAlert'); interceptURL('PUT', '/api/v1/events/subscriptions', 'updateAlert');
interceptURL('GET', '/api/v1/events/subscriptions/name/*', 'alertDetails'); interceptURL(
cy.login(); 'GET',
cy.sidebarClick(SidebarItem.SETTINGS); '/api/v1/events/subscriptions/name/*',
interceptURL('GET', '/api/v1/events/subscriptions?*', 'alertsPage'); 'alertDetails'
cy.get('[data-testid="notifications"]') );
.contains('Notifications') cy.login();
.scrollIntoView() cy.sidebarClick(SidebarItem.SETTINGS);
.click(); interceptURL('GET', '/api/v1/events/subscriptions?*', 'alertsPage');
}); cy.get('[data-testid="notifications"]')
.contains('Notifications')
it('Create new alert with single filter and destination', () => { .scrollIntoView()
verifyResponseStatusCode('@alertsPage', 200); .click();
cy.get('[data-testid="create-notification"]').click();
// Enter alert name
cy.get('#name').type(ALERT_NAME);
// Enter description
cy.get(descriptionBox).clear().type(ALERT_DESCRIPTION);
// Select all source
cy.get('[data-testid="add-source-button"]').scrollIntoView().click();
cy.get(
`[data-testid="drop-down-menu"] [data-testid="${SOURCE_NAME_1}-option"]`
)
.contains(SOURCE_DISPLAY_NAME_1)
.click();
cy.get('[data-testid="source-select"]').should(
'contain',
SOURCE_DISPLAY_NAME_1
);
// Select filters
cy.get('[data-testid="add-filters"]').click();
addOwnerFilter(0, data.user.displayName);
// Select Destination
cy.get('[data-testid="add-destination-button"]').scrollIntoView().click();
addInternalDestination(0, 'Admins', 'Email');
// Click save
cy.get('[data-testid="save-button"]').scrollIntoView().click();
cy.wait('@createAlert').then((interception) => {
data.alertDetails = interception?.response?.body;
expect(interception?.response?.statusCode).equal(201);
});
toastNotification('Alerts created successfully.');
// Check if the alert details page is visible
verifyResponseStatusCode('@alertDetails', 200);
cy.get('[data-testid="alert-details-container"]').should('exist');
});
it('Check created alert details', () => {
const { id: alertId } = data.alertDetails;
verifyResponseStatusCode('@alertsPage', 200);
cy.get(`[data-row-key="${alertId}"] [data-testid="alert-name"]`)
.should('contain', ALERT_NAME)
.click();
verifyResponseStatusCode('@alertDetails', 200);
// Verify alert details
verifyAlertDetails(data.alertDetails);
});
it('Edit and check alert by adding multiple filters and internal destinations', () => {
const { id: alertId } = data.alertDetails;
// Go to edit alert page
cy.get('table').should('contain', ALERT_NAME).click();
cy.get(
`[data-row-key="${alertId}"] [data-testid="alert-edit-${ALERT_NAME}"]`
).click();
// Update description
cy.get(descriptionBox).click().clear().type(ALERT_UPDATED_DESCRIPTION);
// Update source
cy.get('[data-testid="source-select"]').scrollIntoView().click();
cy.get(`[data-testid="${SOURCE_NAME_2}-option"]`)
.contains(SOURCE_DISPLAY_NAME_2)
.click();
// Filters should reset after source change
cy.get('[data-testid="filter-select-0"]').should('not.exist');
// Add multiple filters
[...Array(6).keys()].forEach(() => {
cy.get('[data-testid="add-filters"]').scrollIntoView().click();
}); });
addOwnerFilter(0, data.user.displayName); it('Create new alert with single filter and destination', () => {
addEntityFQNFilter( verifyResponseStatusCode('@alertsPage', 200);
1,
`${DASHBOARD_SERVICE.service.name}.${DASHBOARD_SERVICE.entity.name}`,
true
);
addEventTypeFilter(2, 'entityCreated');
addUpdaterNameFilter(3, data.user.displayName, true);
addDomainFilter(4, data.domain.name);
addGMEFilter(5);
// Add multiple destinations cy.get('[data-testid="create-notification"]').click();
[...Array(3).keys()].forEach(() => {
// Enter alert name
cy.get('#name').type(ALERT_NAME);
// Enter description
cy.get(descriptionBox).clear().type(ALERT_DESCRIPTION);
// Select all source
cy.get('[data-testid="add-source-button"]').scrollIntoView().click();
cy.get(
`[data-testid="drop-down-menu"] [data-testid="${SOURCE_NAME_1}-option"]`
)
.contains(SOURCE_DISPLAY_NAME_1)
.click();
cy.get('[data-testid="source-select"]').should(
'contain',
SOURCE_DISPLAY_NAME_1
);
// Select filters
cy.get('[data-testid="add-filters"]').click();
addOwnerFilter(0, data.user.displayName);
// Select Destination
cy.get('[data-testid="add-destination-button"]').scrollIntoView().click(); cy.get('[data-testid="add-destination-button"]').scrollIntoView().click();
addInternalDestination(0, 'Admins', 'Email');
// Click save
cy.get('[data-testid="save-button"]').scrollIntoView().click();
cy.wait('@createAlert').then((interception) => {
data.alertDetails = interception?.response?.body;
expect(interception?.response?.statusCode).equal(201);
});
toastNotification('Alerts created successfully.');
// Check if the alert details page is visible
verifyResponseStatusCode('@alertDetails', 200);
cy.get('[data-testid="alert-details-container"]').should('exist');
}); });
addInternalDestination(1, 'Owners', 'G Chat'); it('Check created alert details', () => {
addInternalDestination(2, 'Teams', 'Slack', 'Team-select', 'Organization'); const { id: alertId } = data.alertDetails;
addInternalDestination( verifyResponseStatusCode('@alertsPage', 200);
3,
'Users',
'Email',
'User-select',
data.user.displayName
);
// Click save cy.get(`[data-row-key="${alertId}"] [data-testid="alert-name"]`)
cy.get('[data-testid="save-button"]').scrollIntoView().click(); .should('contain', ALERT_NAME)
cy.wait('@updateAlert').then((interception) => { .click();
data.alertDetails = interception?.response?.body;
expect(interception?.response?.statusCode).equal(200); verifyResponseStatusCode('@alertDetails', 200);
// Verify the edited alert changes // Verify alert details
verifyAlertDetails(interception?.response?.body); verifyAlertDetails(data.alertDetails);
});
});
it('Delete alert with single filter', () => {
deleteAlertSteps(ALERT_NAME);
});
it('Create new alert with multiple filters and destinations', () => {
verifyResponseStatusCode('@alertsPage', 200);
cy.get('[data-testid="create-notification"]').click();
// Enter alert name
cy.get('#name').type(ALERT_NAME);
// Enter description
cy.get(descriptionBox).clear().type(ALERT_DESCRIPTION);
// Select all source
cy.get('[data-testid="add-source-button"]').scrollIntoView().click();
cy.get(
`[data-testid="drop-down-menu"] [data-testid="${SOURCE_NAME_1}-option"]`
)
.contains(SOURCE_DISPLAY_NAME_1)
.click();
cy.get('[data-testid="source-select"]').should(
'contain',
SOURCE_DISPLAY_NAME_1
);
// Add multiple filters
[...Array(6).keys()].forEach(() => {
cy.get('[data-testid="add-filters"]').scrollIntoView().click();
}); });
addOwnerFilter(0, data.user.displayName); it('Edit and check alert by adding multiple filters and internal destinations', () => {
addEntityFQNFilter( const { id: alertId } = data.alertDetails;
1,
`${DASHBOARD_SERVICE.service.name}.${DASHBOARD_SERVICE.entity.name}`,
true
);
addEventTypeFilter(2, 'entityCreated');
addUpdaterNameFilter(3, data.user.displayName, true);
addDomainFilter(4, data.domain.name);
addGMEFilter(5);
// Add multiple destinations // Go to edit alert page
[...Array(6).keys()].forEach(() => { cy.get('table').should('contain', ALERT_NAME).click();
cy.get(
`[data-row-key="${alertId}"] [data-testid="alert-edit-${ALERT_NAME}"]`
).click();
// Update description
cy.get(descriptionBox).click().clear().type(ALERT_UPDATED_DESCRIPTION);
// Update source
cy.get('[data-testid="source-select"]').scrollIntoView().click();
cy.get(`[data-testid="${SOURCE_NAME_2}-option"]`)
.contains(SOURCE_DISPLAY_NAME_2)
.click();
// Filters should reset after source change
cy.get('[data-testid="filter-select-0"]').should('not.exist');
// Add multiple filters
[...Array(6).keys()].forEach(() => {
cy.get('[data-testid="add-filters"]').scrollIntoView().click();
});
addOwnerFilter(0, data.user.displayName);
addEntityFQNFilter(
1,
`${DASHBOARD_SERVICE.service.name}.${DASHBOARD_SERVICE.entity.name}`,
true
);
addEventTypeFilter(2, 'entityCreated');
addFilterWithUsersListInput(
'Updater Name-filter-option',
3,
data.user.displayName,
true
);
addDomainFilter(4, data.domain.name);
addGMEFilter(5);
// Add multiple destinations
[...Array(3).keys()].forEach(() => {
cy.get('[data-testid="add-destination-button"]')
.scrollIntoView()
.click();
});
addInternalDestination(1, 'Owners', 'G Chat');
addInternalDestination(
2,
'Teams',
'Slack',
'Team-select',
'Organization'
);
addInternalDestination(
3,
'Users',
'Email',
'User-select',
data.user.displayName
);
// Click save
cy.get('[data-testid="save-button"]').scrollIntoView().click();
cy.wait('@updateAlert').then((interception) => {
data.alertDetails = interception?.response?.body;
expect(interception?.response?.statusCode).equal(200);
// Verify the edited alert changes
verifyAlertDetails(interception?.response?.body);
});
});
it('Delete alert with single filter', () => {
deleteAlertSteps(ALERT_NAME);
});
it('Create new alert with multiple filters and destinations', () => {
verifyResponseStatusCode('@alertsPage', 200);
cy.get('[data-testid="create-notification"]').click();
// Enter alert name
cy.get('#name').type(ALERT_NAME);
// Enter description
cy.get(descriptionBox).clear().type(ALERT_DESCRIPTION);
// Select all source
cy.get('[data-testid="add-source-button"]').scrollIntoView().click();
cy.get(
`[data-testid="drop-down-menu"] [data-testid="${SOURCE_NAME_1}-option"]`
)
.contains(SOURCE_DISPLAY_NAME_1)
.click();
cy.get('[data-testid="source-select"]').should(
'contain',
SOURCE_DISPLAY_NAME_1
);
// Add multiple filters
[...Array(6).keys()].forEach(() => {
cy.get('[data-testid="add-filters"]').scrollIntoView().click();
});
addOwnerFilter(0, data.user.displayName);
addEntityFQNFilter(
1,
`${DASHBOARD_SERVICE.service.name}.${DASHBOARD_SERVICE.entity.name}`,
true
);
addEventTypeFilter(2, 'entityCreated');
addFilterWithUsersListInput(
'Updater Name-filter-option',
3,
data.user.displayName,
true
);
addDomainFilter(4, data.domain.name);
addGMEFilter(5);
// Add multiple destinations
[...Array(6).keys()].forEach(() => {
cy.get('[data-testid="add-destination-button"]')
.scrollIntoView()
.click();
});
addInternalDestination(0, 'Followers', 'Email');
addExternalDestination(1, 'Email', 'test@example.com');
addExternalDestination(2, 'G Chat', 'https://gchat.com');
addExternalDestination(3, 'Generic', 'https://generic.com');
addExternalDestination(4, 'Ms Teams', 'https://msteams.com');
addExternalDestination(5, 'Slack', 'https://slack.com');
// Click save
cy.get('[data-testid="save-button"]').scrollIntoView().click();
cy.wait('@createAlert').then((interception) => {
data.alertDetails = interception?.response?.body;
expect(interception?.response?.statusCode).equal(201);
});
toastNotification('Alerts created successfully.');
// Check if the alert details page is visible
verifyResponseStatusCode('@alertDetails', 200);
cy.get('[data-testid="alert-details-container"]').should('exist');
});
it('Edit and check alert by removing added filters and internal destinations', () => {
const { id: alertId } = data.alertDetails;
// Go to edit alert page
cy.get('table').should('contain', ALERT_NAME).click();
cy.get(
`[data-row-key="${alertId}"] [data-testid="alert-edit-${ALERT_NAME}"]`
).click();
// Remove description
cy.get(descriptionBox).click().clear();
// Remove all filters
[...Array(6).keys()].forEach(() => {
cy.get('[data-testid="remove-filter-0"]').scrollIntoView().click();
});
// Remove all destinations except one
[...Array(5).keys()].forEach(() => {
cy.get('[data-testid="remove-destination-0"]').scrollIntoView().click();
});
// Click save
cy.get('[data-testid="save-button"]').scrollIntoView().click();
cy.wait('@updateAlert').then((interception) => {
data.alertDetails = interception?.response?.body;
expect(interception?.response?.statusCode).equal(200);
// Verify the edited alert changes
verifyAlertDetails(interception?.response?.body);
});
});
it('Delete alert with multiple filters', () => {
deleteAlertSteps(ALERT_NAME);
});
it('Create alert for task source', () => {
verifyResponseStatusCode('@alertsPage', 200);
cy.get('[data-testid="create-notification"]').click();
// Enter alert name
cy.get('#name').type(ALERT_NAME);
// Enter description
cy.get(descriptionBox).clear().type(ALERT_DESCRIPTION);
// Select all source
cy.get('[data-testid="add-source-button"]').scrollIntoView().click();
cy.get(
`[data-testid="drop-down-menu"] [data-testid="${SOURCE_NAME_3}-option"]`
)
.contains(SOURCE_DISPLAY_NAME_3)
.click();
cy.get('[data-testid="source-select"]').should(
'contain',
SOURCE_DISPLAY_NAME_3
);
// Select Destination
cy.get('[data-testid="add-destination-button"]').scrollIntoView().click(); cy.get('[data-testid="add-destination-button"]').scrollIntoView().click();
addInternalDestination(0, 'Owners', 'Email');
cy.get('[data-testid="add-destination-button"]').scrollIntoView().click();
addInternalDestination(1, 'Assignees', 'Email');
// Click save
cy.get('[data-testid="save-button"]').scrollIntoView().click();
cy.wait('@createAlert').then((interception) => {
data.alertDetails = interception?.response?.body;
expect(interception?.response?.statusCode).equal(201);
});
toastNotification('Alerts created successfully.');
// Check if the alert details page is visible
verifyResponseStatusCode('@alertDetails', 200);
cy.get('[data-testid="alert-details-container"]').should('exist');
}); });
addInternalDestination(0, 'Followers', 'Email'); it('Delete alert for task source', () => {
addExternalDestination(1, 'Email', 'test@example.com'); deleteAlertSteps(ALERT_NAME);
addExternalDestination(2, 'G Chat', 'https://gchat.com');
addExternalDestination(3, 'Generic', 'https://generic.com');
addExternalDestination(4, 'Ms Teams', 'https://msteams.com');
addExternalDestination(5, 'Slack', 'https://slack.com');
// Click save
cy.get('[data-testid="save-button"]').scrollIntoView().click();
cy.wait('@createAlert').then((interception) => {
data.alertDetails = interception?.response?.body;
expect(interception?.response?.statusCode).equal(201);
});
toastNotification('Alerts created successfully.');
// Check if the alert details page is visible
verifyResponseStatusCode('@alertDetails', 200);
cy.get('[data-testid="alert-details-container"]').should('exist');
});
it('Edit and check alert by removing added filters and internal destinations', () => {
const { id: alertId } = data.alertDetails;
// Go to edit alert page
cy.get('table').should('contain', ALERT_NAME).click();
cy.get(
`[data-row-key="${alertId}"] [data-testid="alert-edit-${ALERT_NAME}"]`
).click();
// Remove description
cy.get(descriptionBox).click().clear();
// Remove all filters
[...Array(6).keys()].forEach(() => {
cy.get('[data-testid="remove-filter-0"]').scrollIntoView().click();
}); });
// Remove all destinations except one it('Create alert for conversation source', () => {
[...Array(5).keys()].forEach(() => { verifyResponseStatusCode('@alertsPage', 200);
cy.get('[data-testid="remove-destination-0"]').scrollIntoView().click();
cy.get('[data-testid="create-notification"]').click();
// Enter alert name
cy.get('#name').type(ALERT_NAME);
// Enter description
cy.get(descriptionBox).clear().type(ALERT_DESCRIPTION);
// Select all source
cy.get('[data-testid="add-source-button"]').scrollIntoView().click();
cy.get(
`[data-testid="drop-down-menu"] [data-testid="${SOURCE_NAME_4}-option"]`
)
.contains(SOURCE_DISPLAY_NAME_4)
.click();
cy.get('[data-testid="source-select"]').should(
'contain',
SOURCE_DISPLAY_NAME_4
);
// Select Destination
cy.get('[data-testid="add-destination-button"]').scrollIntoView().click();
addInternalDestination(0, 'Owners', 'Email');
// Click save
cy.get('[data-testid="save-button"]').scrollIntoView().click();
cy.wait('@createAlert').then((interception) => {
data.alertDetails = interception?.response?.body;
expect(interception?.response?.statusCode).equal(201);
});
toastNotification('Alerts created successfully.');
// Check if the alert details page is visible
verifyResponseStatusCode('@alertDetails', 200);
cy.get('[data-testid="alert-details-container"]').should('exist');
}); });
// Click save it('Edit and check alert by adding mentions filter', () => {
cy.get('[data-testid="save-button"]').scrollIntoView().click(); const { id: alertId } = data.alertDetails;
cy.wait('@updateAlert').then((interception) => {
data.alertDetails = interception?.response?.body;
expect(interception?.response?.statusCode).equal(200); // Go to edit alert page
cy.get('table').should('contain', ALERT_NAME).click();
// Verify the edited alert changes cy.get(
verifyAlertDetails(interception?.response?.body); `[data-row-key="${alertId}"] [data-testid="alert-edit-${ALERT_NAME}"]`
).click();
// Add filter
cy.get('[data-testid="add-filters"]').scrollIntoView().click();
addFilterWithUsersListInput(
'Mentioned Users-filter-option',
0,
data.user.displayName,
true
);
// Add mentions destination
cy.get('[data-testid="add-destination-button"]').scrollIntoView().click();
addInternalDestination(1, 'Mentions', 'Slack');
// Click save
cy.get('[data-testid="save-button"]').scrollIntoView().click();
cy.wait('@updateAlert').then((interception) => {
data.alertDetails = interception?.response?.body;
expect(interception?.response?.statusCode).equal(200);
// Verify the edited alert changes
verifyAlertDetails(interception?.response?.body);
});
}); });
});
it('Delete alert with multiple filters', () => { it('Delete alert for conversation source', () => {
deleteAlertSteps(ALERT_NAME); deleteAlertSteps(ALERT_NAME);
});
it('Create alert for task source', () => {
verifyResponseStatusCode('@alertsPage', 200);
cy.get('[data-testid="create-notification"]').click();
// Enter alert name
cy.get('#name').type(ALERT_NAME);
// Enter description
cy.get(descriptionBox).clear().type(ALERT_DESCRIPTION);
// Select all source
cy.get('[data-testid="add-source-button"]').scrollIntoView().click();
cy.get(
`[data-testid="drop-down-menu"] [data-testid="${SOURCE_NAME_3}-option"]`
)
.contains(SOURCE_DISPLAY_NAME_3)
.click();
cy.get('[data-testid="source-select"]').should(
'contain',
SOURCE_DISPLAY_NAME_3
);
// Select Destination
cy.get('[data-testid="add-destination-button"]').scrollIntoView().click();
addInternalDestination(0, 'Owners', 'Email');
cy.get('[data-testid="add-destination-button"]').scrollIntoView().click();
addInternalDestination(1, 'Assignees', 'Email');
// Click save
cy.get('[data-testid="save-button"]').scrollIntoView().click();
cy.wait('@createAlert').then((interception) => {
data.alertDetails = interception?.response?.body;
expect(interception?.response?.statusCode).equal(201);
}); });
toastNotification('Alerts created successfully.'); }
);
// Check if the alert details page is visible
verifyResponseStatusCode('@alertDetails', 200);
cy.get('[data-testid="alert-details-container"]').should('exist');
});
it('Delete alert for task source', () => {
deleteAlertSteps(ALERT_NAME);
});
});

View File

@ -55,473 +55,495 @@ import { SERVICE_CATEGORIES } from '../../constants/service.constants';
const SOURCE_NAME_1 = 'Container'; const SOURCE_NAME_1 = 'Container';
const SOURCE_NAME_2 = 'Pipeline'; const SOURCE_NAME_2 = 'Pipeline';
describe('Observability Alert Flow', { tags: 'Settings' }, () => { describe(
const data = { 'Observability Alert Flow',
testCase: {}, { tags: ['Settings', 'Observability'] },
testSuite: {}, () => {
pipelineService: {}, const data = {
ingestionPipeline: {}, testCase: {},
user: { testSuite: {},
displayName: '', pipelineService: {},
}, ingestionPipeline: {},
domain: { user: {
name: '', displayName: '',
}, },
alertDetails: { domain: {
id: '', name: '',
}, },
}; alertDetails: {
id: '',
},
};
before(() => { before(() => {
cy.login(); cy.login();
cy.getAllLocalStorage().then((storageData) => { cy.getAllLocalStorage().then((storageData) => {
const token = Object.values(storageData)[0].oidcIdToken; const token = Object.values(storageData)[0].oidcIdToken;
// Create a table // Create a table
createEntityTable({ createEntityTable({
token, token,
...DATABASE_SERVICE, ...DATABASE_SERVICE,
tables: [DATABASE_SERVICE.entity], tables: [DATABASE_SERVICE.entity],
}); });
// Create a test suite and test case for table
cy.request({
method: 'POST',
url: `/api/v1/dataQuality/testSuites/executable`,
headers: { Authorization: `Bearer ${token}` },
body: {
name: TEST_SUITE_FQN,
executableEntityReference: TABLE_FQN,
},
}).then((response) => {
data.testSuite = response.body;
// Create a test suite and test case for table
cy.request({ cy.request({
method: 'POST', method: 'POST',
url: `/api/v1/dataQuality/testCases`, url: `/api/v1/dataQuality/testSuites/executable`,
headers: { Authorization: `Bearer ${token}` }, headers: { Authorization: `Bearer ${token}` },
body: { body: {
name: TEST_CASE_NAME, name: TEST_SUITE_FQN,
displayName: TEST_CASE_NAME, executableEntityReference: TABLE_FQN,
entityLink: `<#E::table::${TABLE_FQN}>`,
parameterValues: [
{
name: 'columnCount',
value: 7,
},
],
testDefinition: 'tableColumnCountToEqual',
testSuite: TEST_SUITE_FQN,
}, },
}).then((testCaseResponse) => { }).then((response) => {
data.testCase = testCaseResponse.body; data.testSuite = response.body;
});
});
// Create a pipeline cy.request({
cy.request({ method: 'POST',
method: 'POST', url: `/api/v1/dataQuality/testCases`,
url: `/api/v1/services/${PIPELINE_SERVICE.serviceType}`, headers: { Authorization: `Bearer ${token}` },
headers: { Authorization: `Bearer ${token}` }, body: {
body: PIPELINE_SERVICE.service, name: TEST_CASE_NAME,
}).then((pipelineServiceResponse) => { displayName: TEST_CASE_NAME,
data.pipelineService = pipelineServiceResponse.body; entityLink: `<#E::table::${TABLE_FQN}>`,
parameterValues: [
cy.request({ {
method: 'POST', name: 'columnCount',
url: `/api/v1/${PIPELINE_SERVICE.entityType}`, value: 7,
headers: { Authorization: `Bearer ${token}` }, },
body: PIPELINE_SERVICE.entity, ],
}); testDefinition: 'tableColumnCountToEqual',
testSuite: TEST_SUITE_FQN,
// Create a ingestion pipeline
cy.request({
method: 'POST',
url: `/api/v1/services/ingestionPipelines`,
headers: { Authorization: `Bearer ${token}` },
body: {
airflowConfig: {},
loggerLevel: 'INFO',
name: INGESTION_PIPELINE_NAME,
pipelineType: 'metadata',
service: {
id: data.pipelineService.id,
type: 'pipelineService',
}, },
sourceConfig: { }).then((testCaseResponse) => {
config: {}, data.testCase = testCaseResponse.body;
},
},
}).then((ingestionPipelineResponse) => {
data.ingestionPipeline = ingestionPipelineResponse.body;
});
});
// Create a new user
cy.request({
method: 'POST',
url: `/api/v1/users/signup`,
headers: { Authorization: `Bearer ${token}` },
body: USER_DETAILS,
}).then((response) => {
data.user = response.body;
});
// Create a domain
cy.request({
method: 'PUT',
url: `/api/v1/domains`,
headers: { Authorization: `Bearer ${token}` },
body: DOMAIN_CREATION_DETAILS,
}).then((response) => {
data.domain = response.body;
});
});
});
after(() => {
cy.login();
cy.getAllLocalStorage().then((storageData) => {
const token = Object.values(storageData)[0].oidcIdToken;
// Delete created services
hardDeleteService({
token,
serviceFqn: DATABASE_SERVICE.service.name,
serviceType: SERVICE_CATEGORIES.DATABASE_SERVICES,
});
hardDeleteService({
token,
serviceFqn: PIPELINE_SERVICE.service.name,
serviceType: PIPELINE_SERVICE.serviceType,
});
// Delete created domain
cy.request({
method: 'DELETE',
url: `/api/v1/domains/name/${DOMAIN_CREATION_DETAILS.name}`,
headers: { Authorization: `Bearer ${token}` },
});
// Delete created user
cy.request({
method: 'DELETE',
url: `/api/v1/users/${data.user.id}?hardDelete=true&recursive=false`,
headers: { Authorization: `Bearer ${token}` },
});
});
});
beforeEach(() => {
interceptURL('POST', '/api/v1/events/subscriptions', 'createAlert');
interceptURL('PUT', '/api/v1/events/subscriptions', 'updateAlert');
interceptURL('GET', '/api/v1/events/subscriptions/name/*', 'alertDetails');
interceptURL('GET', '/api/v1/events/subscriptions?*', 'alertsPage');
cy.login();
cy.sidebarClick(SidebarItem.OBSERVABILITY_ALERT);
});
it('Create new alert Pipeline', () => {
verifyResponseStatusCode('@alertsPage', 200);
cy.get('[data-testid="create-observability"]').click();
// Enter alert name
cy.get('#name').type(ALERT_NAME);
// Enter description
cy.get(descriptionBox).clear().type(ALERT_DESCRIPTION);
// Select all source
cy.get('[data-testid="add-source-button"]').scrollIntoView().click();
cy.get('[data-testid="drop-down-menu"] [data-testid="container-option"]')
.contains(SOURCE_NAME_1)
.click();
cy.get('[data-testid="source-select"]').should('contain', SOURCE_NAME_1);
// Select filters
cy.get('[data-testid="add-filters"]').click();
addOwnerFilter(0, data.user.displayName, false, 'Owner Name');
// Select actions
cy.get('[data-testid="add-trigger"]').click();
addGetSchemaChangesAction(0);
// Select Destination
cy.get('[data-testid="add-destination-button"]').scrollIntoView().click();
addInternalDestination(0, 'Admins', 'Email');
// Click save
cy.get('[data-testid="save-button"]').scrollIntoView().click();
cy.wait('@createAlert').then((interception) => {
data.alertDetails = interception?.response?.body;
expect(interception?.response?.statusCode).equal(201);
});
toastNotification('Alerts created successfully.');
// Check if the alert details page is visible
verifyResponseStatusCode('@alertDetails', 200);
cy.get('[data-testid="alert-details-container"]').should('exist');
});
it('Check created pipeline alert details', () => {
const { id: alertId } = data.alertDetails;
verifyResponseStatusCode('@alertsPage', 200);
cy.get(`[data-row-key="${alertId}"] [data-testid="alert-name"]`)
.should('contain', ALERT_NAME)
.click();
verifyResponseStatusCode('@alertDetails', 200);
// Verify alert details
verifyAlertDetails(data.alertDetails);
});
it('Edit created alert', () => {
const { id: alertId } = data.alertDetails;
// Go to edit alert page
cy.get('table').should('contain', ALERT_NAME).click();
cy.get(
`[data-row-key="${alertId}"] [data-testid="alert-edit-${ALERT_NAME}"]`
).click();
// Update description
cy.get(descriptionBox).click().clear().type(ALERT_UPDATED_DESCRIPTION);
// Update source
cy.get('[data-testid="source-select"]').scrollIntoView().click();
cy.get('[data-testid="pipeline-option"]').contains(SOURCE_NAME_2).click();
// Filters should reset after source change
cy.get('[data-testid="filter-select-0"]').should('not.exist');
// Add multiple filters
[...Array(3).keys()].forEach(() => {
cy.get('[data-testid="add-filters"]').scrollIntoView().click();
});
addOwnerFilter(0, data.user.displayName, false, 'Owner Name');
addEntityFQNFilter(
1,
`${PIPELINE_SERVICE.service.name}.${PIPELINE_SERVICE.entity.name}`,
true,
'Pipeline Name'
);
addDomainFilter(2, data.domain.name);
// Add actions
cy.get('[data-testid="add-trigger"]').click();
addPipelineStatusUpdatesAction(0, 'Successful', true);
// Add multiple destinations
[...Array(2).keys()].forEach(() => {
cy.get('[data-testid="add-destination-button"]').scrollIntoView().click();
});
addInternalDestination(1, 'Owners', 'G Chat');
addInternalDestination(2, 'Teams', 'Slack', 'Team-select', 'Organization');
// Click save
cy.get('[data-testid="save-button"]').scrollIntoView().click();
cy.wait('@updateAlert').then((interception) => {
data.alertDetails = interception?.response?.body;
expect(interception?.response?.statusCode).equal(200);
// Verify the edited alert changes
verifyAlertDetails(interception?.response?.body);
});
});
it('Delete created alert', () => {
deleteAlertSteps(ALERT_NAME);
});
Object.entries(OBSERVABILITY_CREATION_DETAILS).forEach(
([source, alertDetails]) => {
it(`Alert creation for ${source}`, () => {
verifyResponseStatusCode('@alertsPage', 200);
cy.get('[data-testid="create-observability"]').click();
// Enter alert name
cy.get('#name').type(ALERT_NAME);
// Enter description
cy.get(descriptionBox).clear().type(ALERT_DESCRIPTION);
// Select source
cy.get('[data-testid="add-source-button"]').scrollIntoView().click();
cy.get(
`[data-testid="drop-down-menu"] [data-testid="${source}-option"]`
)
.contains(alertDetails.sourceDisplayName)
.click();
cy.get('[data-testid="source-select"]').should(
'contain',
alertDetails.sourceDisplayName
);
// Add filters
alertDetails.filters.forEach((filter, filterNumber) => {
cy.get('[data-testid="add-filters"]').click();
// Select filter
cy.get(`[data-testid="filter-select-${filterNumber}"]`).click({
waitForAnimations: true,
}); });
cy.get(`[data-testid="${filter.name}-filter-option"]`) });
.filter(':visible')
.click();
// Search and select filter input value // Create a pipeline
interceptURL('GET', `/api/v1/search/query?q=*`, 'getSearchResult'); cy.request({
cy.get(`[data-testid="${filter.inputSelector}"]`) method: 'POST',
.click() url: `/api/v1/services/${PIPELINE_SERVICE.serviceType}`,
.type(filter.inputValue); headers: { Authorization: `Bearer ${token}` },
body: PIPELINE_SERVICE.service,
}).then((pipelineServiceResponse) => {
data.pipelineService = pipelineServiceResponse.body;
// Adding manual wait here as as safe since debounced API is not being detected in the cypress cy.request({
cy.wait(500); method: 'POST',
verifyResponseStatusCode('@getSearchResult', 200); url: `/api/v1/${PIPELINE_SERVICE.entityType}`,
cy.get(`[title="${filter.inputValue}"]`) headers: { Authorization: `Bearer ${token}` },
.filter(':visible') body: PIPELINE_SERVICE.entity,
.scrollIntoView() });
.click();
// Create a ingestion pipeline
cy.request({
method: 'POST',
url: `/api/v1/services/ingestionPipelines`,
headers: { Authorization: `Bearer ${token}` },
body: {
airflowConfig: {},
loggerLevel: 'INFO',
name: INGESTION_PIPELINE_NAME,
pipelineType: 'metadata',
service: {
id: data.pipelineService.id,
type: 'pipelineService',
},
sourceConfig: {
config: {},
},
},
}).then((ingestionPipelineResponse) => {
data.ingestionPipeline = ingestionPipelineResponse.body;
});
});
// Create a new user
cy.request({
method: 'POST',
url: `/api/v1/users/signup`,
headers: { Authorization: `Bearer ${token}` },
body: USER_DETAILS,
}).then((response) => {
data.user = response.body;
});
// Create a domain
cy.request({
method: 'PUT',
url: `/api/v1/domains`,
headers: { Authorization: `Bearer ${token}` },
body: DOMAIN_CREATION_DETAILS,
}).then((response) => {
data.domain = response.body;
});
});
});
after(() => {
cy.login();
cy.getAllLocalStorage().then((storageData) => {
const token = Object.values(storageData)[0].oidcIdToken;
// Delete created services
hardDeleteService({
token,
serviceFqn: DATABASE_SERVICE.service.name,
serviceType: SERVICE_CATEGORIES.DATABASE_SERVICES,
});
hardDeleteService({
token,
serviceFqn: PIPELINE_SERVICE.service.name,
serviceType: PIPELINE_SERVICE.serviceType,
});
// Delete created domain
cy.request({
method: 'DELETE',
url: `/api/v1/domains/name/${DOMAIN_CREATION_DETAILS.name}`,
headers: { Authorization: `Bearer ${token}` },
});
// Delete created user
cy.request({
method: 'DELETE',
url: `/api/v1/users/${data.user.id}?hardDelete=true&recursive=false`,
headers: { Authorization: `Bearer ${token}` },
});
});
});
beforeEach(() => {
interceptURL('POST', '/api/v1/events/subscriptions', 'createAlert');
interceptURL('PUT', '/api/v1/events/subscriptions', 'updateAlert');
interceptURL(
'GET',
'/api/v1/events/subscriptions/name/*',
'alertDetails'
);
interceptURL('GET', '/api/v1/events/subscriptions?*', 'alertsPage');
cy.login();
cy.sidebarClick(SidebarItem.OBSERVABILITY_ALERT);
});
it('Create new alert Pipeline', () => {
verifyResponseStatusCode('@alertsPage', 200);
cy.get('[data-testid="create-observability"]').click();
// Enter alert name
cy.get('#name').type(ALERT_NAME);
// Enter description
cy.get(descriptionBox).clear().type(ALERT_DESCRIPTION);
// Select all source
cy.get('[data-testid="add-source-button"]').scrollIntoView().click();
cy.get('[data-testid="drop-down-menu"] [data-testid="container-option"]')
.contains(SOURCE_NAME_1)
.click();
cy.get('[data-testid="source-select"]').should('contain', SOURCE_NAME_1);
// Select filters
cy.get('[data-testid="add-filters"]').click();
addOwnerFilter(0, data.user.displayName, false, 'Owner Name');
// Select actions
cy.get('[data-testid="add-trigger"]').click();
addGetSchemaChangesAction(0);
// Select Destination
cy.get('[data-testid="add-destination-button"]').scrollIntoView().click();
addInternalDestination(0, 'Admins', 'Email');
// Click save
cy.get('[data-testid="save-button"]').scrollIntoView().click();
cy.wait('@createAlert').then((interception) => {
data.alertDetails = interception?.response?.body;
expect(interception?.response?.statusCode).equal(201);
});
toastNotification('Alerts created successfully.');
// Check if the alert details page is visible
verifyResponseStatusCode('@alertDetails', 200);
cy.get('[data-testid="alert-details-container"]').should('exist');
});
it('Check created pipeline alert details', () => {
const { id: alertId } = data.alertDetails;
verifyResponseStatusCode('@alertsPage', 200);
cy.get(`[data-row-key="${alertId}"] [data-testid="alert-name"]`)
.should('contain', ALERT_NAME)
.click();
verifyResponseStatusCode('@alertDetails', 200);
// Verify alert details
verifyAlertDetails(data.alertDetails);
});
it('Edit created alert', () => {
const { id: alertId } = data.alertDetails;
// Go to edit alert page
cy.get('table').should('contain', ALERT_NAME).click();
cy.get(
`[data-row-key="${alertId}"] [data-testid="alert-edit-${ALERT_NAME}"]`
).click();
// Update description
cy.get(descriptionBox).click().clear().type(ALERT_UPDATED_DESCRIPTION);
// Update source
cy.get('[data-testid="source-select"]').scrollIntoView().click();
cy.get('[data-testid="pipeline-option"]').contains(SOURCE_NAME_2).click();
// Filters should reset after source change
cy.get('[data-testid="filter-select-0"]').should('not.exist');
// Add multiple filters
[...Array(3).keys()].forEach(() => {
cy.get('[data-testid="add-filters"]').scrollIntoView().click();
});
addOwnerFilter(0, data.user.displayName, false, 'Owner Name');
addEntityFQNFilter(
1,
`${PIPELINE_SERVICE.service.name}.${PIPELINE_SERVICE.entity.name}`,
true,
'Pipeline Name'
);
addDomainFilter(2, data.domain.name);
// Add actions
cy.get('[data-testid="add-trigger"]').click();
addPipelineStatusUpdatesAction(0, 'Successful', true);
// Add multiple destinations
[...Array(2).keys()].forEach(() => {
cy.get('[data-testid="add-destination-button"]')
.scrollIntoView()
.click();
});
addInternalDestination(1, 'Owners', 'G Chat');
addInternalDestination(
2,
'Teams',
'Slack',
'Team-select',
'Organization'
);
// Click save
cy.get('[data-testid="save-button"]').scrollIntoView().click();
cy.wait('@updateAlert').then((interception) => {
data.alertDetails = interception?.response?.body;
expect(interception?.response?.statusCode).equal(200);
// Verify the edited alert changes
verifyAlertDetails(interception?.response?.body);
});
});
it('Delete created alert', () => {
deleteAlertSteps(ALERT_NAME);
});
Object.entries(OBSERVABILITY_CREATION_DETAILS).forEach(
([source, alertDetails]) => {
it(`Alert creation for ${source}`, () => {
verifyResponseStatusCode('@alertsPage', 200);
cy.get('[data-testid="create-observability"]').click();
// Enter alert name
cy.get('#name').type(ALERT_NAME);
// Enter description
cy.get(descriptionBox).clear().type(ALERT_DESCRIPTION);
// Select source
cy.get('[data-testid="add-source-button"]').scrollIntoView().click();
// Check if option is selected
cy.get( cy.get(
`[title="${filter.inputValue}"] .ant-select-item-option-state` `[data-testid="drop-down-menu"] [data-testid="${source}-option"]`
).should('exist'); )
.contains(alertDetails.sourceDisplayName)
.click();
if (filter.exclude) { cy.get('[data-testid="source-select"]').should(
// Change filter effect 'contain',
cy.get(`[data-testid="filter-switch-${filterNumber}"]`) alertDetails.sourceDisplayName
);
// Add filters
alertDetails.filters.forEach((filter, filterNumber) => {
cy.get('[data-testid="add-filters"]').click();
// Select filter
cy.get(`[data-testid="filter-select-${filterNumber}"]`).click({
waitForAnimations: true,
});
cy.get(`[data-testid="${filter.name}-filter-option"]`)
.filter(':visible')
.click();
// Search and select filter input value
interceptURL('GET', `/api/v1/search/query?q=*`, 'getSearchResult');
cy.get(`[data-testid="${filter.inputSelector}"]`)
.click()
.type(filter.inputValue);
// Adding manual wait here as as safe since debounced API is not being detected in the cypress
cy.wait(500);
verifyResponseStatusCode('@getSearchResult', 200);
cy.get(`[title="${filter.inputValue}"]`)
.filter(':visible')
.scrollIntoView() .scrollIntoView()
.click(); .click();
}
});
// Add actions // Check if option is selected
alertDetails.actions.forEach((action, actionNumber) => { cy.get(
cy.get('[data-testid="add-trigger"]').click(); `[title="${filter.inputValue}"] .ant-select-item-option-state`
).should('exist');
// Select action if (filter.exclude) {
cy.get(`[data-testid="trigger-select-${actionNumber}"]`).click({ // Change filter effect
waitForAnimations: true, cy.get(`[data-testid="filter-switch-${filterNumber}"]`)
});
cy.get(`[data-testid="${action.name}-filter-option"]`)
.filter(':visible')
.click();
if (action.inputs && action.inputs.length > 0) {
action.inputs.forEach((input) => {
// Search and select domain
interceptURL(
'GET',
`/api/v1/search/query?q=*`,
'getSearchResult'
);
cy.get(`[data-testid="${input.inputSelector}"]`)
.click()
.type(input.inputValue);
if (input.waitForAPI) {
verifyResponseStatusCode('@getSearchResult', 200);
}
cy.get(`[title="${input.inputValue}"]`)
.filter(':visible')
.scrollIntoView() .scrollIntoView()
.click(); .click();
cy.get(`[data-testid="${input.inputSelector}"]`).should( }
'contain', });
input.inputValue
);
cy.clickOutside();
});
}
if (action.exclude) { // Add actions
// Change filter effect alertDetails.actions.forEach((action, actionNumber) => {
cy.get(`[data-testid="trigger-switch-${actionNumber}"]`) cy.get('[data-testid="add-trigger"]').click();
.scrollIntoView()
// Select action
cy.get(`[data-testid="trigger-select-${actionNumber}"]`).click({
waitForAnimations: true,
});
cy.get(`[data-testid="${action.name}-filter-option"]`)
.filter(':visible')
.click(); .click();
}
if (action.inputs && action.inputs.length > 0) {
action.inputs.forEach((input) => {
// Search and select domain
interceptURL(
'GET',
`/api/v1/search/query?q=*`,
'getSearchResult'
);
cy.get(`[data-testid="${input.inputSelector}"]`)
.click()
.type(input.inputValue);
if (input.waitForAPI) {
verifyResponseStatusCode('@getSearchResult', 200);
}
cy.get(`[title="${input.inputValue}"]`)
.filter(':visible')
.scrollIntoView()
.click();
cy.get(`[data-testid="${input.inputSelector}"]`).should(
'contain',
input.inputValue
);
cy.clickOutside();
});
}
if (action.exclude) {
// Change filter effect
cy.get(`[data-testid="trigger-switch-${actionNumber}"]`)
.scrollIntoView()
.click();
}
});
// Add Destinations
alertDetails.destinations.forEach(
(destination, destinationNumber) => {
cy.get('[data-testid="add-destination-button"]')
.scrollIntoView()
.click();
if (destination.mode === 'internal') {
addInternalDestination(
destinationNumber,
destination.category,
destination.type,
destination.inputSelector,
destination.inputValue
);
} else {
addExternalDestination(
destinationNumber,
destination.category,
destination.inputValue
);
}
}
);
// Click save
cy.get('[data-testid="save-button"]').scrollIntoView().click();
cy.wait('@createAlert').then((interception) => {
data.alertDetails = interception?.response?.body;
expect(interception?.response?.statusCode).equal(201);
});
toastNotification('Alerts created successfully.');
// Check if the alert details page is visible
verifyResponseStatusCode('@alertDetails', 200);
cy.get('[data-testid="alert-details-container"]').should('exist');
}); });
// Add Destinations it(`Verify created ${source} alert details and delete alert`, () => {
alertDetails.destinations.forEach((destination, destinationNumber) => { const { id: alertId } = data.alertDetails;
cy.get('[data-testid="add-destination-button"]') verifyResponseStatusCode('@alertsPage', 200);
.scrollIntoView()
cy.get(`[data-row-key="${alertId}"] [data-testid="alert-name"]`)
.should('contain', ALERT_NAME)
.click(); .click();
if (destination.mode === 'internal') { verifyResponseStatusCode('@alertDetails', 200);
addInternalDestination(
destinationNumber, // Verify alert details
destination.category, verifyAlertDetails(data.alertDetails);
destination.type,
destination.inputSelector, // Delete alert
destination.inputValue cy.get('[data-testid="delete-button"]').scrollIntoView().click();
); cy.get('.ant-modal-header').should(
} else { 'contain',
addExternalDestination( `Delete subscription "${ALERT_NAME}"`
destinationNumber, );
destination.category, cy.get('[data-testid="confirmation-text-input"]').type(DELETE_TERM);
destination.inputValue interceptURL(
); 'DELETE',
} '/api/v1/events/subscriptions/*',
'deleteAlert'
);
cy.get('[data-testid="confirm-button"]').click();
verifyResponseStatusCode('@deleteAlert', 200);
toastNotification(`"${ALERT_NAME}" deleted successfully!`);
}); });
}
// Click save );
cy.get('[data-testid="save-button"]').scrollIntoView().click(); }
cy.wait('@createAlert').then((interception) => { );
data.alertDetails = interception?.response?.body;
expect(interception?.response?.statusCode).equal(201);
});
toastNotification('Alerts created successfully.');
// Check if the alert details page is visible
verifyResponseStatusCode('@alertDetails', 200);
cy.get('[data-testid="alert-details-container"]').should('exist');
});
it(`Verify created ${source} alert details and delete alert`, () => {
const { id: alertId } = data.alertDetails;
verifyResponseStatusCode('@alertsPage', 200);
cy.get(`[data-row-key="${alertId}"] [data-testid="alert-name"]`)
.should('contain', ALERT_NAME)
.click();
verifyResponseStatusCode('@alertDetails', 200);
// Verify alert details
verifyAlertDetails(data.alertDetails);
// Delete alert
cy.get('[data-testid="delete-button"]').scrollIntoView().click();
cy.get('.ant-modal-header').should(
'contain',
`Delete subscription "${ALERT_NAME}"`
);
cy.get('[data-testid="confirmation-text-input"]').type(DELETE_TERM);
interceptURL('DELETE', '/api/v1/events/subscriptions/*', 'deleteAlert');
cy.get('[data-testid="confirm-button"]').click();
verifyResponseStatusCode('@deleteAlert', 200);
toastNotification(`"${ALERT_NAME}" deleted successfully!`);
});
}
);
});

View File

@ -268,14 +268,14 @@ const SignInPage = () => {
</div> </div>
</div> </div>
)} )}
{(!isAuthProviderLDAP) && ( {!isAuthProviderLDAP && (
<div className="mt-8" onClick={onClickForgotPassword}> <div className="mt-8" onClick={onClickForgotPassword}>
<Typography.Link underline data-testid="forgot-password"> <Typography.Link underline data-testid="forgot-password">
{t('label.forgot-password')} {t('label.forgot-password')}
</Typography.Link> </Typography.Link>
</div> </div>
)} )}
{(authConfig?.enableSelfSignup) && (!isAuthProviderLDAP) && ( {authConfig?.enableSelfSignup && !isAuthProviderLDAP && (
<> <>
<Divider className="w-min-0 mt-8 mb-12 justify-center"> <Divider className="w-min-0 mt-8 mb-12 justify-center">
<Typography.Text className="text-sm" type="secondary"> <Typography.Text className="text-sm" type="secondary">

View File

@ -528,6 +528,7 @@ export const getFieldByArgumentType = (
break; break;
case 'updateByUserList': case 'updateByUserList':
case 'userList':
field = ( field = (
<Col key="user-select" span={12}> <Col key="user-select" span={12}>
<Form.Item <Form.Item
@ -921,8 +922,10 @@ export const getFilteredDestinationOptions = (
// Logic to filter options for destination type "Internal" // Logic to filter options for destination type "Internal"
// Show all options except "Assignees" for all sources. // Show all options except "Assignees" and "Mentions" for all sources.
let shouldShowOption = option.value !== SubscriptionCategory.Assignees; let shouldShowOption =
option.value !== SubscriptionCategory.Assignees &&
option.value !== SubscriptionCategory.Mentions;
// Only show "Owners" and "Assignees" options for "Task" source. // Only show "Owners" and "Assignees" options for "Task" source.
if (selectedSource === 'task') { if (selectedSource === 'task') {
@ -932,6 +935,14 @@ export const getFilteredDestinationOptions = (
].includes(option.value as SubscriptionCategory); ].includes(option.value as SubscriptionCategory);
} }
// Only show "Owners" and "Mentions" options for "Conversation" source.
if (selectedSource === 'conversation') {
shouldShowOption = [
SubscriptionCategory.Owners,
SubscriptionCategory.Mentions,
].includes(option.value as SubscriptionCategory);
}
return shouldShowOption; return shouldShowOption;
}); });

View File

@ -164,7 +164,7 @@ export async function suggestions(
'isBot:false', 'isBot:false',
'displayName.keyword', 'displayName.keyword',
'asc', 'asc',
SearchIndex.USER [SearchIndex.USER, SearchIndex.TEAM]
); );
const hits = data.data.hits.hits; const hits = data.data.hits.hits;

View File

@ -15,6 +15,7 @@ import { includes, isNil } from 'lodash';
import React from 'react'; import React from 'react';
import { ReactComponent as AdminIcon } from '../assets/svg/admin-colored-icon.svg'; import { ReactComponent as AdminIcon } from '../assets/svg/admin-colored-icon.svg';
import { ReactComponent as GChatIcon } from '../assets/svg/gchat.svg'; import { ReactComponent as GChatIcon } from '../assets/svg/gchat.svg';
import { ReactComponent as MentionIcon } from '../assets/svg/ic-mentions.svg';
import { ReactComponent as MSTeamsIcon } from '../assets/svg/ms-teams.svg'; import { ReactComponent as MSTeamsIcon } from '../assets/svg/ms-teams.svg';
import { ReactComponent as SlackIcon } from '../assets/svg/slack.svg'; import { ReactComponent as SlackIcon } from '../assets/svg/slack.svg';
import { ReactComponent as TeamIcon } from '../assets/svg/team-colored-icon.svg'; import { ReactComponent as TeamIcon } from '../assets/svg/team-colored-icon.svg';
@ -42,6 +43,10 @@ export const getAlertDestinationCategoryIcons = (type: string) => {
case 'Assignees': case 'Assignees':
Icon = AssigneeIcon; Icon = AssigneeIcon;
break;
case 'Mentions':
Icon = MentionIcon;
break; break;
case 'GChat': case 'GChat':
Icon = GChatIcon; Icon = GChatIcon;