From 068c55a9257f5aef8f37d6d31df51a81e7d60095 Mon Sep 17 00:00:00 2001 From: andreas-unleash Date: Wed, 8 Mar 2023 12:47:42 +0200 Subject: [PATCH] Feat/notifications cypress (#3244) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## About the changes Closes # [1-743](https://linear.app/unleash/issue/1-743/add-cypress-test-for-notifications-happy-path) ### Important files ## Discussion points --------- Signed-off-by: andreas-unleash --- .../projects/notifications.spec.ts | 137 ++++++++++++++++++ frontend/cypress/support/commands.ts | 4 + frontend/cypress/support/index.ts | 1 + .../common/Notifications/Notifications.tsx | 8 +- .../Notifications/NotificationsList.tsx | 6 +- .../ProjectFeatureToggles.tsx | 1 + frontend/src/utils/testIds.ts | 4 + src/lib/routes/admin-api/user-admin.ts | 4 +- 8 files changed, 161 insertions(+), 4 deletions(-) create mode 100644 frontend/cypress/integration/projects/notifications.spec.ts 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 = () => { +