From 9b4f5f63f08b4a4b12fe9529f8cc43495efce321 Mon Sep 17 00:00:00 2001 From: Miguel Serrano Date: Thu, 13 Jun 2024 10:36:32 +0200 Subject: [PATCH] [CE/SP] Add e2e tests for admin panel (#18476) * [CE/SP] Add e2e tests for admin panel GitOrigin-RevId: 1f98fa18cc03e9265d7e2ee6b0e9060a77dab35a --- server-ce/test/admin.spec.ts | 218 +++++++++++++++++++++++++++++++++++ 1 file changed, 218 insertions(+) create mode 100644 server-ce/test/admin.spec.ts diff --git a/server-ce/test/admin.spec.ts b/server-ce/test/admin.spec.ts new file mode 100644 index 0000000000..944c5d8a8a --- /dev/null +++ b/server-ce/test/admin.spec.ts @@ -0,0 +1,218 @@ +import { startWith } from './helpers/config' +import { activateUser, ensureUserExists, login } from './helpers/login' +import { v4 as uuid } from 'uuid' +import { createProject } from './helpers/project' + +describe('admin panel', function () { + describe('in server pro', () => { + const admin = 'admin@example.com' + const user1 = 'user@example.com' + const user2 = 'user2@example.com' + + const testProjectName = `project-${uuid()}` + let testProjectId = '' + const deletedProjectName = `deleted-project-${uuid()}` + let projectToDeleteId = '' + + const findProjectRow = (projectName: string) => + cy.findByText(projectName).parent().parent() + + startWith({ + pro: true, + }) + ensureUserExists({ email: admin, isAdmin: true }) + ensureUserExists({ email: user1 }) + ensureUserExists({ email: user2 }) + + before(() => { + login(user1) + cy.visit('/project') + createProject(testProjectName).then(id => (testProjectId = id)) + cy.visit('/project') + createProject(deletedProjectName).then(id => (projectToDeleteId = id)) + }) + + describe('manage site', () => { + let resumeAdminSession: () => void + beforeEach(() => { + resumeAdminSession = login(admin) + cy.visit('/project') + cy.get('nav').findByText('Admin').click() + cy.get('nav').findByText('Manage Site').click() + }) + + it.skip('publish and clear admin messages', () => { + const message = 'Admin Message ' + uuid() + + cy.log('create system message') + cy.get('[role="tab"]').contains('System Messages').click() + cy.get('input[name="content"]').type(message) + cy.get('button').contains('Post Message').click() + cy.findByText(message) + + cy.log('wait for system message propagation') + cy.wait(13000) + const resumeUser1Session = login(user1) + cy.visit('/project') + cy.findByText(message) + + cy.log('clear system messages') + resumeAdminSession() + cy.visit('/project') + cy.get('nav').findByText('Admin').click() + cy.get('nav').findByText('Manage Site').click() + cy.get('[role="tab"]').contains('System Messages').click() + cy.get('button').contains('Clear all messages').click() + + cy.log('verify system messages are no longer displayed') + resumeUser1Session() + cy.visit('/project') + cy.findByText(message).should('not.exist') + }) + }) + + describe('manage users', () => { + beforeEach(() => { + login(admin) + cy.visit('/project') + cy.get('nav').findByText('Admin').click() + cy.get('nav').findByText('Manage Users').click() + }) + + it('create and login user', () => { + const user = `${uuid()}@example.com` + + cy.get('a').contains('New User').click() + cy.get('input[name="email"]').type(user + '{enter}') + + cy.get('td') + .contains(/\/user\/activate/) + .then($td => { + const url = $td.text().trim() + activateUser(url) + }) + }) + + it('user list RegExp search', () => { + cy.get('input[name="isRegExpSearch"]').click() + cy.get('input[name="email"]').type('user[0-9]{enter}') + cy.findByText(user2) + cy.findByText(user1).should('not.exist') + }) + }) + + describe('user page', () => { + beforeEach(() => { + login(admin) + cy.visit('/project') + cy.get('nav').findByText('Admin').click() + cy.get('nav').findByText('Manage Users').click() + cy.get('input[name="email"]').type(user1 + '{enter}') + cy.findByText(user1).click() + cy.url().should('match', /\/admin\/user\/[a-fA-F0-9]{24}/) + }) + + it('displays expected tabs', () => { + const tabs = [ + 'User Info', + 'Projects', + 'Deleted Projects', + 'Audit Log', + 'Sessions', + ] + cy.get('[role="tab"]').each((el, index) => { + cy.wrap(el).findByText(tabs[index]).click() + }) + }) + + describe('user info tab', () => { + beforeEach(() => { + cy.get('[role="tab"]').contains('User Info').click() + }) + + it('displays required sections', () => { + // not exhaustive list, checks the tab content is rendered + cy.findByText('Profile') + cy.findByText('Editor Settings') + }) + + it('should not display SaaS-only sections', () => { + cy.findByText('Referred User Count').should('not.exist') + cy.findByText('Split Test Assignments').should('not.exist') + cy.findByText('Experimental Features').should('not.exist') + cy.findByText('Service Integration').should('not.exist') + cy.findByText('SSO Integrations').should('not.exist') + cy.findByText('Security').should('not.exist') + }) + }) + + it('transfer project ownership', () => { + cy.log("access project admin through owners' project list") + cy.get('[role="tab"]').contains('Projects').click() + cy.get(`a[href="/admin/project/${testProjectId}"]`).click() + + cy.findByText('Transfer Ownership').click() + cy.get('button[type="submit"]').should('be.disabled') + cy.get('input[name="user_id"]').type(user2) + cy.get('button[type="submit"]').should('not.be.disabled') + cy.get('button[type="submit"]').click() + cy.findByText('Transfer project to this user?') + cy.get('button').contains('Confirm').click() + + cy.log('check the project is displayed in the new owner projects tab') + cy.get('input[name="email"]').type(user2 + '{enter}') + cy.findByText(user2).click() + cy.get('[role="tab"]').contains('Projects').click() + cy.get(`a[href="/admin/project/${testProjectId}"]`) + }) + }) + + it('restore deleted projects', () => { + const resumeUserSession = login(user1) + cy.visit('/project') + + cy.log('select project to delete') + findProjectRow(deletedProjectName).within(() => + cy.get('input[type="checkbox"]').first().check() + ) + + cy.log('delete project') + findProjectRow(deletedProjectName).within(() => + cy.get('button[aria-label="Trash"]').click() + ) + cy.get('button').contains('Confirm').click() + cy.findByText(deletedProjectName).should('not.exist') + + cy.log('navigate to thrashed projects and delete the project') + cy.get('.project-list-sidebar-react').within(() => { + cy.findByText('Trashed Projects').click() + }) + findProjectRow(deletedProjectName).within(() => + cy.get('button[aria-label="Delete"]').click() + ) + cy.get('button').contains('Confirm').click() + cy.findByText(deletedProjectName).should('not.exist') + + cy.log('login as an admin and navigate to the deleted project') + login(admin) + cy.visit('/admin/user') + cy.get('input[name="email"]').type(user1 + '{enter}') + cy.get('a').contains(user1).click() + cy.findByText('Deleted Projects').click() + cy.get('a').contains(deletedProjectName).click() + + cy.log('undelete the project') + cy.findByText('undelete').click() + cy.findByText('undelete').should('not.exist') + cy.url().should('contain', `/admin/project/${projectToDeleteId}`) + + cy.log('login as the user and verify the project is restored') + resumeUserSession() + cy.visit('/project') + cy.get('.project-list-sidebar-react').within(() => { + cy.findByText('Trashed Projects').click() + }) + cy.findByText(`${deletedProjectName} (Restored)`) + }) + }) +})