diff --git a/frontend/cypress/integration/projects/notifications.spec.ts b/frontend/cypress/integration/projects/notifications.spec.ts
new file mode 100644
index 0000000000..78158b9063
--- /dev/null
+++ b/frontend/cypress/integration/projects/notifications.spec.ts
@@ -0,0 +1,137 @@
+///
+
+type UserCredentials = { email: string; password: string };
+const ENTERPRISE = Boolean(Cypress.env('ENTERPRISE'));
+const randomId = String(Math.random()).split('.')[1];
+const featureToggleName = `notifications_test-${randomId}`;
+const baseUrl = Cypress.config().baseUrl;
+let strategyId = '';
+const userIds: number[] = [];
+const userCredentials: UserCredentials[] = [];
+const userName = `notifications_user-${randomId}`;
+const projectName = `default`;
+const password = Cypress.env(`AUTH_PASSWORD`) + '_A';
+const EDITOR = 2;
+const PROJECT_MEMBER = 5;
+
+// Disable all active splash pages by visiting them.
+const disableActiveSplashScreens = () => {
+ cy.visit(`/splash/operators`);
+};
+
+const createUser = () => {
+ const name = `${userName}`;
+ const email = `${name}@test.com`;
+ cy.request('POST', `${baseUrl}/api/admin/user-admin`, {
+ name: name,
+ email: `${name}@test.com`,
+ username: `${name}@test.com`,
+ sendEmail: false,
+ rootRole: EDITOR,
+ })
+ .as(name)
+ .then(response => {
+ const id = response.body.id;
+ updateUserPassword(id).then(() => {
+ addUserToProject(id).then(() => {
+ userIds.push(id);
+ userCredentials.push({ email, password });
+ });
+ });
+ });
+};
+
+const updateUserPassword = async (id: number) => {
+ cy.request(
+ 'POST',
+ `${baseUrl}/api/admin/user-admin/${id}/change-password`,
+ {
+ password,
+ }
+ );
+};
+
+const addUserToProject = async (id: number) => {
+ cy.request(
+ 'POST',
+ `${baseUrl}/api/admin/projects/${projectName}/role/${PROJECT_MEMBER}/access`,
+ {
+ groups: [],
+ users: [{ id }],
+ }
+ );
+};
+
+describe('notifications', () => {
+ before(() => {
+ disableActiveSplashScreens();
+ cy.login();
+ createUser();
+ });
+
+ after(() => {
+ // We need to login as admin for cleanup
+ cy.login();
+ userIds.forEach(id =>
+ cy.request('DELETE', `${baseUrl}/api/admin/user-admin/${id}`)
+ );
+
+ cy.request(
+ 'DELETE',
+ `${baseUrl}/api/admin/features/${featureToggleName}`
+ );
+ });
+
+ beforeEach(() => {
+ cy.login();
+ cy.visit(`/projects/${projectName}`);
+ if (document.querySelector("[data-testid='CLOSE_SPLASH']")) {
+ cy.get("[data-testid='CLOSE_SPLASH']").click();
+ }
+ });
+
+ afterEach(() => {
+ cy.logout();
+ });
+
+ const createFeature = () => {
+ cy.get('[data-testid=NAVIGATE_TO_CREATE_FEATURE').click();
+
+ cy.intercept('POST', `/api/admin/projects/${projectName}/features`).as(
+ 'createFeature'
+ );
+
+ cy.get("[data-testid='CF_NAME_ID'").type(featureToggleName);
+ cy.get("[data-testid='CF_DESC_ID'").type('hello-world');
+ cy.get("[data-testid='CF_CREATE_BTN_ID']").click();
+ cy.wait('@createFeature');
+ };
+
+ it('should create a notification when a feature is created in a project', () => {
+ createFeature();
+
+ //Should not show own notifications
+ cy.get("[data-testid='NOTIFICATIONS_BUTTON']").click();
+
+ //then
+ cy.get("[data-testid='NOTIFICATIONS_MODAL']").should('exist');
+ cy.get("[data-testid='UNREAD_NOTIFICATIONS']").should('not.exist');
+
+ const credentials = userCredentials[0];
+
+ //Sign in as a different user
+ cy.login(credentials.email, credentials.password);
+ cy.visit(`/projects/${projectName}`);
+ if (document.querySelector("[data-testid='CLOSE_SPLASH']")) {
+ cy.get("[data-testid='CLOSE_SPLASH']").click();
+ }
+ cy.get("[data-testid='NOTIFICATIONS_BUTTON']").click();
+
+ //then
+ cy.get("[data-testid='UNREAD_NOTIFICATIONS']").should('exist');
+ cy.get("[data-testid='NOTIFICATIONS_LIST']")
+ .should('have.length', 1)
+ .eq(0)
+ .should('contain.text', 'New feature');
+ });
+});
diff --git a/frontend/cypress/support/commands.ts b/frontend/cypress/support/commands.ts
index 528146d5bc..0d16067cc2 100644
--- a/frontend/cypress/support/commands.ts
+++ b/frontend/cypress/support/commands.ts
@@ -43,3 +43,7 @@ Cypress.Commands.add('login', (user = AUTH_USER, password = AUTH_PASSWORD) =>
cy.get("[data-testid='HEADER_USER_AVATAR']");
})
);
+
+Cypress.Commands.add('logout', () => {
+ cy.visit('/logout');
+});
diff --git a/frontend/cypress/support/index.ts b/frontend/cypress/support/index.ts
index 1f43f103c0..a8f805772b 100644
--- a/frontend/cypress/support/index.ts
+++ b/frontend/cypress/support/index.ts
@@ -23,6 +23,7 @@ declare global {
namespace Cypress {
interface Chainable {
login(user?: string, password?: string): Chainable;
+ logout(user?: string): Chainable;
}
}
}
diff --git a/frontend/src/component/common/Notifications/Notifications.tsx b/frontend/src/component/common/Notifications/Notifications.tsx
index 862d86d1f7..437a93e32d 100644
--- a/frontend/src/component/common/Notifications/Notifications.tsx
+++ b/frontend/src/component/common/Notifications/Notifications.tsx
@@ -164,6 +164,7 @@ export const Notifications = () => {
setShowNotifications(!showNotifications)}
+ data-testid="NOTIFICATIONS_BUTTON"
>
{
setShowNotifications(false)}
>
-
+
@@ -194,7 +198,7 @@ export const Notifications = () => {
+