Update selectors to improve CE test stability (#28096)

* Update selectors to improve test stability

* Update selectors to improve test stability

* Use plain string matchers

* Fix test

* [monorepo] use plain string matchers everywhere

* [web] remove Kb/ prefix from title of learn wiki links

---------

Co-authored-by: Jakob Ackermann <jakob.ackermann@overleaf.com>
GitOrigin-RevId: 12e13c39822795338a3bee20236454f9948e6221
This commit is contained in:
Rebeka Dekany
2025-09-02 08:04:56 +00:00
committed by Copybot
co-authored by Jakob Ackermann
parent bd4130c147
commit 97d8f73749
24 changed files with 736 additions and 476 deletions
+109 -69
View File
@@ -14,7 +14,7 @@ describe('admin panel', function () {
function registrationTests() {
it('via GUI and opening URL manually', () => {
const user = `${uuid()}@example.com`
cy.get('input[name="email"]').type(user + '{enter}')
cy.findByLabelText('Emails to register new users').type(user + '{enter}')
cy.get('td')
.contains(/\/user\/activate/)
@@ -26,7 +26,7 @@ describe('admin panel', function () {
it('via GUI and email', () => {
const user = `${uuid()}@example.com`
cy.get('input[name="email"]').type(user + '{enter}')
cy.findByLabelText('Emails to register new users').type(user + '{enter}')
let url: string
cy.get('td')
@@ -93,8 +93,8 @@ describe('admin panel', function () {
beforeEach(() => {
login(admin)
cy.visit('/project')
cy.get('nav').findByText('Admin').click()
cy.get('nav').findByText('Manage Users').click()
cy.findByRole('menuitem', { name: 'Admin' }).click()
cy.findByRole('menuitem', { name: 'Manage Users' }).click()
})
registrationTests()
})
@@ -139,17 +139,17 @@ describe('admin panel', function () {
beforeEach(() => {
login(admin)
cy.visit('/project')
cy.get('nav').findByText('Admin').click()
cy.get('nav').findByText('Manage Site').click()
cy.findByRole('menuitem', { name: 'Admin' }).click()
cy.findByRole('menuitem', { name: 'Manage Site' }).click()
})
it('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.findByRole('tab', { name: 'System Messages' }).click()
cy.findByLabelText('Message').type(message)
cy.findByRole('button', { name: 'Post Message' }).click()
cy.findByText(message)
login(user1)
@@ -159,10 +159,10 @@ describe('admin panel', function () {
cy.log('clear system messages')
login(admin)
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.findByRole('menuitem', { name: 'Admin' }).click()
cy.findByRole('menuitem', { name: 'Manage Site' }).click()
cy.findByRole('tab', { name: 'System Messages' }).click()
cy.findByRole('button', { name: 'Clear all messages' }).click()
cy.log('verify system messages are no longer displayed')
login(user1)
@@ -175,16 +175,16 @@ describe('admin panel', function () {
beforeEach(() => {
login(admin)
cy.visit('/project')
cy.get('nav').findByText('Admin').click()
cy.get('nav').findByText('Manage Users').click()
cy.findByRole('menuitem', { name: 'Admin' }).click()
cy.findByRole('menuitem', { name: 'Manage Users' }).click()
})
it('displays expected tabs', () => {
const tabs = ['Users', 'License Usage']
cy.get('[role="tab"]').each((el, index) => {
cy.wrap(el).findByText(tabs[index]).click()
cy.findAllByRole('tab').should('have.length', tabs.length)
tabs.forEach(tabName => {
cy.findByRole('tab', { name: tabName }).click()
})
cy.get('[role="tab"]').should('have.length', tabs.length)
})
it('license usage tab', () => {
@@ -202,10 +202,12 @@ describe('admin panel', function () {
})
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')
cy.findByLabelText('RegExp').click()
cy.findByPlaceholderText('Search users by email or id…').type(
'user[0-9]{enter}'
)
cy.findByRole('link', { name: user2 })
cy.findByRole('link', { name: user1 }).should('not.exist')
})
})
@@ -213,10 +215,12 @@ describe('admin panel', function () {
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.findByRole('menuitem', { name: 'Admin' }).click()
cy.findByRole('menuitem', { name: 'Manage Users' }).click()
cy.findByPlaceholderText('Search users by email or id…').type(
user1 + '{enter}'
)
cy.findByRole('link', { name: user1 }).click()
cy.url().should('match', /\/admin\/user\/[a-fA-F0-9]{24}/)
})
@@ -228,15 +232,15 @@ describe('admin panel', function () {
'Audit Log',
'Sessions',
]
cy.get('[role="tab"]').each((el, index) => {
cy.wrap(el).findByText(tabs[index]).click()
cy.findAllByRole('tab').should('have.length', tabs.length)
tabs.forEach(tabName => {
cy.findByRole('tab', { name: tabName }).click()
})
cy.get('[role="tab"]').should('have.length', tabs.length)
})
describe('user info tab', () => {
beforeEach(() => {
cy.get('[role="tab"]').contains('User Info').click()
cy.findByRole('tab', { name: 'User Info' }).click()
})
it('displays required sections', () => {
@@ -246,33 +250,61 @@ describe('admin panel', function () {
})
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')
cy.findByLabelText('Referred User Count').should('not.exist')
cy.findByRole('heading', { name: /Split Test Assignments/ }).should(
'not.exist'
)
cy.findByRole('heading', { name: 'Experimental Features' }).should(
'not.exist'
)
cy.findByRole('heading', { name: 'Service Integration' }).should(
'not.exist'
)
cy.findByRole('heading', { name: 'SSO Integrations' }).should(
'not.exist'
)
cy.findByRole('heading', { name: '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.findByRole('tablist').within(() => {
cy.findByRole('tab', { name: 'Projects' }).click()
})
cy.get(`a[href="/admin/project/${testProjectId}"]`)
.should('contain.text', 'Project information')
.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.findByRole('button', { name: 'Transfer Ownership' }).click()
cy.findByRole('dialog').within(() => {
cy.findByRole('heading', { name: 'Transfer Ownership of Project' })
cy.findByRole('button', { name: 'Find' }).should('be.disabled')
cy.findByRole('button', { name: 'Confirm' }).should('be.disabled')
cy.findByPlaceholderText('User ID or Email').type(user2)
cy.findByRole('button', { name: 'Find' }).should('not.be.disabled')
cy.findByRole('button', { name: 'Find' }).click()
cy.findByText('Transfer project to this user?')
cy.findByRole('cell', { name: 'ID' })
cy.findByRole('cell', { name: 'Name' })
cy.findByRole('cell', { name: 'Email' })
cy.findByRole('cell', { name: user2 })
cy.findByRole('button', { name: 'Confirm' }).should('not.be.disabled')
cy.findByRole('button', { name: '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}"]`)
cy.findByPlaceholderText('Search users by email or id…').type(
user2 + '{enter}'
)
cy.findByRole('link', { name: user2 }).click()
cy.findByRole('tablist').within(() => {
cy.findByRole('tab', { name: 'Projects' }).click()
})
cy.get(`a[href="/admin/project/${testProjectId}"]`).should(
'contain.text',
'Project information'
)
})
})
@@ -284,10 +316,10 @@ describe('admin panel', function () {
it('displays expected tabs', () => {
const tabs = ['Project Info', 'Deleted Docs', 'Audit Log']
cy.get('[role="tab"]').each((el, index) => {
cy.wrap(el).findByText(tabs[index]).click()
cy.findAllByRole('tab').should('have.length', tabs.length)
tabs.forEach(tabName => {
cy.findByRole('tab', { name: tabName }).click()
})
cy.get('[role="tab"]').should('have.length', tabs.length)
})
})
@@ -297,46 +329,54 @@ describe('admin panel', function () {
cy.log('select project to delete')
findProjectRow(deletedProjectName).within(() =>
cy.get('input[type="checkbox"]').first().check()
cy
.findByRole('checkbox', { name: `Select ${deletedProjectName}` })
.first()
.check()
)
cy.log('delete project')
findProjectRow(deletedProjectName).within(() =>
cy.findByRole('button', { name: 'Trash' }).click()
)
cy.get('button').contains('Confirm').click()
cy.findByText(deletedProjectName).should('not.exist')
cy.findByRole('button', { name: 'Confirm' }).click()
cy.findByRole('link', { name: deletedProjectName }).should('not.exist')
cy.log('navigate to thrashed projects and delete the project')
cy.get('.project-list-sidebar-scroll').within(() => {
cy.findByText('Trashed projects').click()
cy.findByRole('navigation', {
name: 'Project categories and tags',
})
.findByRole('button', { name: 'Trashed projects' })
.click()
findProjectRow(deletedProjectName).within(() =>
cy.findByRole('button', { name: 'Delete' }).click()
)
cy.get('button').contains('Confirm').click()
cy.findByText(deletedProjectName).should('not.exist')
cy.findByRole('button', { name: 'Confirm' }).click()
cy.findByRole('link', { name: 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.findByPlaceholderText('Search users by email or id…').type(
user1 + '{enter}'
)
cy.findByRole('link', { name: user1 }).click()
cy.findByRole('tab', { name: 'Deleted Projects' }).click()
cy.findByRole('link', { name: deletedProjectName }).click()
cy.log('undelete the project')
cy.findByText('Undelete').click()
cy.findByText('Undelete').should('not.exist')
cy.findByRole('button', { name: 'Undelete' }).click()
cy.findByRole('button', { name: 'Undelete' }).should('not.exist')
cy.url().should('contain', `/admin/project/${projectToDeleteId}`)
cy.log('login as the user and verify the project is restored')
login(user1)
cy.visit('/project')
cy.get('.project-list-sidebar-scroll').within(() => {
cy.findByText('Trashed projects').click()
cy.findByRole('navigation', {
name: 'Project categories and tags',
})
cy.findByText(`${deletedProjectName} (Restored)`)
.findByRole('button', { name: 'Trashed projects' })
.click()
cy.findByRole('link', { name: `${deletedProjectName} (Restored)` })
})
})
})