diff --git a/server-ce/test/accounts.spec.ts b/server-ce/test/accounts.spec.ts
index 85d545535a..92327a24d9 100644
--- a/server-ce/test/accounts.spec.ts
+++ b/server-ce/test/accounts.spec.ts
@@ -10,7 +10,7 @@ describe('Accounts', function () {
login('user@example.com')
cy.visit('/project')
cy.findByRole('menuitem', { name: 'Account' }).click()
- cy.findByText('Log Out').click()
+ cy.findByRole('menuitem', { name: 'Log Out' }).click()
cy.url().should('include', '/login')
cy.visit('/project')
cy.url().should('include', '/login')
diff --git a/server-ce/test/admin.spec.ts b/server-ce/test/admin.spec.ts
index 538a821811..b404698b51 100644
--- a/server-ce/test/admin.spec.ts
+++ b/server-ce/test/admin.spec.ts
@@ -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)` })
})
})
})
diff --git a/server-ce/test/create-and-compile-project.spec.ts b/server-ce/test/create-and-compile-project.spec.ts
index a0e03fe8d0..ac73f8ab7a 100644
--- a/server-ce/test/create-and-compile-project.spec.ts
+++ b/server-ce/test/create-and-compile-project.spec.ts
@@ -6,46 +6,59 @@ import {
import { isExcludedBySharding, startWith } from './helpers/config'
import { throttledRecompile } from './helpers/compile'
+const USER = 'user@example.com'
+const COLLABORATOR = 'collaborator@example.com'
+
describe('Project creation and compilation', function () {
if (isExcludedBySharding('CE_DEFAULT')) return
startWith({})
- ensureUserExists({ email: 'user@example.com' })
- ensureUserExists({ email: 'collaborator@example.com' })
+ ensureUserExists({ email: USER })
+ ensureUserExists({ email: COLLABORATOR })
it('users can create project and compile it', function () {
- login('user@example.com')
+ login(USER)
createProject('test-project')
const recompile = throttledRecompile()
- cy.findByText('\\maketitle').parent().click()
- cy.findByText('\\maketitle').parent().type('\n\\section{{}Test Section}')
+ cy.findByRole('textbox', { name: 'Source Editor editing' }).within(() => {
+ cy.findByText('\\maketitle').parent().click()
+ cy.findByText('\\maketitle').parent().type('\n\\section{{}Test Section}')
+ })
recompile()
- cy.get('.pdf-viewer').should('contain.text', 'Test Section')
+ cy.findByRole('region', { name: 'PDF preview and logs' }).within(() => {
+ cy.findByLabelText(/Page.*1/i).should('be.visible')
+ cy.findByText('Test Section').should('be.visible')
+ })
})
it('create and edit markdown file', function () {
const fileName = `test-${Date.now()}.md`
const markdownContent = '# Markdown title'
- login('user@example.com')
+ login(USER)
createProject('test-project')
- // FIXME: Add aria-label maybe? or at least data-test-id
- cy.findByText('New file').click({ force: true })
+ cy.findByRole('navigation', { name: 'Project files and outline' })
+ .findByRole('button', { name: 'New file' })
+ .click()
cy.findByRole('dialog').within(() => {
- cy.get('input').clear()
- cy.get('input').type(fileName)
- cy.findByText('Create').click()
+ cy.findByLabelText('File Name').clear().type(fileName)
+ cy.findByRole('button', { name: 'Create' }).click()
})
- cy.findByText(fileName).click()
+ cy.findByRole('button', { name: fileName }).click()
// wait until we've switched to the newly created empty file
- cy.get('.cm-line').should('have.length', 1)
- cy.get('.cm-line').type(markdownContent)
- cy.findByText('main.tex').click()
- cy.findByRole('textbox', { name: /Source Editor editing/i }).should(
+ cy.findByRole('textbox', { name: 'Source Editor editing' }).should(
+ 'have.length',
+ 1
+ )
+ cy.findByRole('textbox', { name: 'Source Editor editing' }).type(
+ markdownContent
+ )
+ cy.findByRole('button', { name: 'main.tex' }).click()
+ cy.findByRole('textbox', { name: 'Source Editor editing' }).should(
'contain.text',
'\\maketitle'
)
- cy.findByText(fileName).click()
- cy.findByRole('textbox', { name: /Source Editor editing/i }).should(
+ cy.findByRole('button', { name: fileName }).click()
+ cy.findByRole('textbox', { name: 'Source Editor editing' }).should(
'contain.text',
markdownContent
)
@@ -54,7 +67,7 @@ describe('Project creation and compilation', function () {
it('can link and display linked image from other project', function () {
const sourceProjectName = `test-project-${Date.now()}`
const targetProjectName = `${sourceProjectName}-target`
- login('user@example.com')
+ login(USER)
createProject(sourceProjectName, {
type: 'Example project',
@@ -63,15 +76,17 @@ describe('Project creation and compilation', function () {
createProject(targetProjectName)
// link the image from `projectName` into this project
- cy.findByText('New file').click({ force: true })
+ cy.findByRole('button', { name: 'New file' }).click()
cy.findByRole('dialog').within(() => {
- cy.findByText('From another project').click()
+ cy.findByRole('button', { name: 'From another project' }).click()
cy.findByLabelText('Select a Project').select(sourceProjectName)
cy.findByLabelText('Select a File').select('frog.jpg')
- cy.findByText('Create').click()
+ cy.findByRole('button', { name: 'Create' }).click()
})
- cy.findByTestId('file-tree').findByText('frog.jpg').click()
- cy.findByText('Another project')
+ cy.findByRole('navigation', { name: 'Project files and outline' })
+ .findByRole('treeitem', { name: 'frog.jpg' })
+ .click()
+ cy.findByRole('link', { name: 'Another project' })
.should('have.attr', 'href')
.then(href => {
cy.get('@sourceProjectId').then(sourceProjectId => {
@@ -83,7 +98,7 @@ describe('Project creation and compilation', function () {
it('can refresh linked files as collaborator', function () {
const sourceProjectName = `test-project-${Date.now()}`
const targetProjectName = `${sourceProjectName}-target`
- login('user@example.com')
+ login(USER)
createProject(sourceProjectName, {
type: 'Example project',
open: false,
@@ -91,31 +106,36 @@ describe('Project creation and compilation', function () {
createProject(targetProjectName).as('targetProjectId')
// link the image from `projectName` into this project
- cy.findByText('New file').click({ force: true })
+ cy.findByRole('navigation', { name: 'Project files and outline' })
+ .findByRole('button', { name: 'New file' })
+ .click()
+
cy.findByRole('dialog').within(() => {
- cy.findByText('From another project').click()
+ cy.findByRole('button', { name: 'From another project' }).click()
cy.findByLabelText('Select a Project').select(sourceProjectName)
cy.findByLabelText('Select a File').select('frog.jpg')
- cy.findByText('Create').click()
+ cy.findByRole('button', { name: 'Create' }).click()
})
- cy.findByText('Share').click()
+ cy.findByRole('navigation', { name: 'Project actions' }).within(() => {
+ cy.findByRole('button', { name: 'Share' }).click()
+ })
cy.findByRole('dialog').within(() => {
- cy.findByTestId('collaborator-email-input').type(
- 'collaborator@example.com,'
- )
- cy.findByText('Invite').click({ force: true })
+ cy.findByTestId('collaborator-email-input').type(COLLABORATOR + ',')
+ cy.findByRole('button', { name: 'Invite' }).click()
cy.findByText('Invite not yet accepted.')
})
- login('collaborator@example.com')
+ login(COLLABORATOR)
openProjectViaInviteNotification(targetProjectName)
cy.get('@targetProjectId').then(targetProjectId => {
cy.url().should('include', targetProjectId)
})
- cy.findByTestId('file-tree').findByText('frog.jpg').click()
- cy.findByText('Another project')
+ cy.findByRole('navigation', { name: 'Project files and outline' })
+ .findByRole('treeitem', { name: 'frog.jpg' })
+ .click()
+ cy.findByRole('link', { name: 'Another project' })
.should('have.attr', 'href')
.then(href => {
cy.get('@sourceProjectId').then(sourceProjectId => {
diff --git a/server-ce/test/editor.spec.ts b/server-ce/test/editor.spec.ts
index db1b9301dc..8e3fe4827e 100644
--- a/server-ce/test/editor.spec.ts
+++ b/server-ce/test/editor.spec.ts
@@ -10,11 +10,14 @@ import { v4 as uuid } from 'uuid'
import { beforeWithReRunOnTestRetry } from './helpers/beforeWithReRunOnTestRetry'
import { prepareWaitForNextCompileSlot } from './helpers/compile'
+const USER = 'user@example.com'
+const COLLABORATOR = 'collaborator@example.com'
+
describe('editor', () => {
if (isExcludedBySharding('PRO_DEFAULT_1')) return
startWith({ pro: true })
- ensureUserExists({ email: 'user@example.com' })
- ensureUserExists({ email: 'collaborator@example.com' })
+ ensureUserExists({ email: USER })
+ ensureUserExists({ email: COLLABORATOR })
let projectName: string
let projectId: string
@@ -22,7 +25,7 @@ describe('editor', () => {
let waitForCompileRateLimitCoolOff: (fn: () => void) => void
beforeWithReRunOnTestRetry(function () {
projectName = `project-${uuid()}`
- login('user@example.com')
+ login(USER)
createProject(projectName, { type: 'Example project', open: false }).then(
id => (projectId = id)
)
@@ -31,7 +34,7 @@ describe('editor', () => {
})
beforeEach(() => {
- login('user@example.com')
+ login(USER)
waitForCompileRateLimitCoolOff(() => {
openProjectById(projectId)
})
@@ -40,9 +43,16 @@ describe('editor', () => {
describe('spelling', function () {
function changeSpellCheckLanguageTo(lng: string) {
cy.log(`change project language to '${lng}'`)
- cy.get('button').contains('Menu').click()
- cy.get('select[id=settings-menu-spellCheckLanguage]').select(lng)
- cy.get('[id="left-menu"]').type('{esc}') // close left menu
+ cy.findByRole('navigation', {
+ name: 'Project actions',
+ })
+ .findByRole('button', { name: 'Menu' })
+ .click()
+
+ cy.findByRole('dialog').within(() => {
+ cy.findByLabelText('Spell check').select(lng)
+ })
+ cy.get('body').type('{esc}')
}
afterEach(function () {
@@ -70,20 +80,28 @@ describe('editor', () => {
cy.findByText(word).should('not.have.class', 'ol-cm-spelling-error')
cy.log('remove word from dictionary')
- cy.get('button').contains('Menu').click()
- cy.get('button#dictionary-settings').contains('Edit').click()
- cy.get('[id="dictionary-modal"]').within(() => {
+ cy.findByRole('navigation', {
+ name: 'Project actions',
+ })
+ .findByRole('button', { name: 'Menu' })
+ .click()
+ cy.findByRole('dialog').within(() => {
+ cy.findByLabelText('Dictionary').click()
+ })
+ cy.findByTestId('dictionary-modal').within(() => {
cy.findByText(word)
.parent()
- .within(() => cy.get('button').click())
+ .within(() =>
+ cy.findByRole('button', { name: 'Remove from dictionary' }).click()
+ )
// the modal has 2 close buttons, this ensures the one with the visible label is
// clicked, otherwise it would need `force: true`
- cy.get('.btn').contains('Close').click()
+ cy.contains('button', /close/i).click()
})
cy.log('close left panel')
- cy.get('[id="left-menu"]').type('{esc}')
+ cy.findByTestId('left-menu').type('{esc}')
cy.log('rewrite word to force spelling error')
cy.get('.cm-line').type('{selectAll}{del}' + word + '{enter}')
@@ -94,7 +112,11 @@ describe('editor', () => {
describe('editor', () => {
it('renders jpg', () => {
- cy.findByTestId('file-tree').findByText('frog.jpg').click()
+ cy.findByRole('navigation', {
+ name: 'Project files and outline',
+ })
+ .findByRole('treeitem', { name: 'frog.jpg' })
+ .click()
cy.get('[alt="frog.jpg"]')
.should('be.visible')
.and('have.prop', 'naturalWidth')
@@ -108,7 +130,7 @@ describe('editor', () => {
force: true,
})
cy.get('button').contains('𝜉').click()
- cy.findByRole('textbox', { name: /Source Editor editing/i }).should(
+ cy.findByRole('textbox', { name: 'Source Editor editing' }).should(
'contain.text',
'\\xi'
)
@@ -120,23 +142,27 @@ describe('editor', () => {
describe('add new file to project', () => {
beforeEach(() => {
- cy.get('button').contains('New file').click({ force: true })
+ cy.findByRole('button', { name: 'New file' }).click()
})
testNewFileUpload()
it('should not display import from URL', () => {
- cy.findByText('From external URL').should('not.exist')
+ cy.findByRole('button', { name: 'From external URL' }).should('not.exist')
})
})
describe('left menu', () => {
beforeEach(() => {
- cy.get('button').contains('Menu').click()
+ cy.findByRole('navigation', {
+ name: 'Project actions',
+ })
+ .findByRole('button', { name: 'Menu' })
+ .click()
})
it('can download project sources', () => {
- cy.get('a').contains('Source').click()
+ cy.findByRole('link', { name: 'Source' }).click()
const zipName = projectName.replaceAll('-', '_')
cy.task('readFileInZip', {
pathToZip: `cypress/downloads/${zipName}.zip`,
@@ -146,10 +172,12 @@ describe('editor', () => {
it('can download project PDF', () => {
cy.log('ensure project is compiled')
- cy.get('.pdf-viewer').should('contain.text', 'Your Paper')
-
- cy.get('.nav-downloads').within(() => {
- cy.findByText('PDF').click()
+ cy.findByRole('region', { name: 'PDF preview and logs' }).should(
+ 'contain.text',
+ 'Your Paper'
+ )
+ cy.findByRole('dialog').within(() => {
+ cy.findByRole('link', { name: 'PDF' }).click()
const pdfName = projectName.replaceAll('-', '_')
cy.task('readPdf', `cypress/downloads/${pdfName}.pdf`).should(
'contain',
@@ -160,11 +188,13 @@ describe('editor', () => {
it('word count', () => {
cy.log('ensure project is compiled')
- cy.get('.pdf-viewer').should('contain.text', 'Your Paper')
+ cy.findByRole('region', { name: 'PDF preview and logs' }).should(
+ 'contain.text',
+ 'Your Paper'
+ )
+ cy.findByRole('button', { name: 'Word Count' }).click()
- cy.findByText('Word Count').click()
-
- cy.get('#word-count-modal').within(() => {
+ cy.findByTestId('word-count-modal').within(() => {
cy.findByText('Total Words:')
cy.findByText('607')
cy.findByText('Headers:')
@@ -179,51 +209,73 @@ describe('editor', () => {
describe('layout selector', () => {
it('show editor only and switch between editor and pdf', () => {
- cy.get('.pdf-viewer').should('be.visible')
+ cy.findByRole('region', { name: 'PDF preview and logs' }).should(
+ 'be.visible'
+ )
cy.get('.cm-editor').should('be.visible')
- cy.findByText('Layout').click()
- cy.findByText('Editor only').click()
+ cy.findByRole('button', { name: 'Layout' }).click()
+ cy.findByRole('menu').within(() => {
+ cy.findByRole('menuitem', { name: /Editor only/ }).click()
+ })
- cy.get('.pdf-viewer').should('not.be.visible')
+ cy.findByRole('region', { name: 'PDF preview and logs' }).should(
+ 'not.be.visible'
+ )
cy.get('.cm-editor').should('be.visible')
- cy.findByText('Switch to PDF').click()
+ cy.findByRole('button', { name: 'Switch to PDF' }).click()
- cy.get('.pdf-viewer').should('be.visible')
+ cy.findByRole('region', { name: 'PDF preview and logs' }).should(
+ 'be.visible'
+ )
cy.get('.cm-editor').should('not.be.visible')
- cy.findByText('Switch to editor').click()
+ cy.findByRole('button', { name: 'Switch to editor' }).click()
- cy.get('.pdf-viewer').should('not.be.visible')
+ cy.findByRole('region', { name: 'PDF preview and logs' }).should(
+ 'not.be.visible'
+ )
cy.get('.cm-editor').should('be.visible')
})
it('show PDF only and go back to Editor & PDF', () => {
- cy.get('.pdf-viewer').should('be.visible')
+ cy.findByRole('region', { name: 'PDF preview and logs' }).should(
+ 'be.visible'
+ )
cy.get('.cm-editor').should('be.visible')
- cy.findByText('Layout').click()
- cy.findByText('PDF only').click()
+ cy.findByRole('button', { name: 'Layout' }).click()
+ cy.findByRole('menu').within(() => {
+ cy.findByRole('menuitem', { name: /PDF only/ }).click()
+ })
- cy.get('.pdf-viewer').should('be.visible')
+ cy.findByRole('region', { name: 'PDF preview and logs' }).should(
+ 'be.visible'
+ )
cy.get('.cm-editor').should('not.be.visible')
- cy.findByText('Layout').click()
- cy.findByText('Editor & PDF').click()
+ cy.findByRole('button', { name: 'Layout' }).click()
+ cy.findByRole('menu').within(() => {
+ cy.findByRole('menuitem', { name: 'Editor & PDF' }).click()
+ })
- cy.get('.pdf-viewer').should('be.visible')
+ cy.findByRole('region', { name: 'PDF preview and logs' }).should(
+ 'be.visible'
+ )
cy.get('.cm-editor').should('be.visible')
})
it('PDF in a separate tab (tests editor only)', () => {
- cy.get('.pdf-viewer').should('be.visible')
+ cy.findByTestId('pdf-viewer').should('be.visible')
cy.get('.cm-editor').should('be.visible')
- cy.findByText('Layout').click()
- cy.findByText('PDF in separate tab').click()
+ cy.findByRole('button', { name: 'Layout' }).click()
+ cy.findByRole('menu').within(() => {
+ cy.findByRole('menuitem', { name: 'PDF in separate tab' }).click()
+ })
- cy.get('.pdf-viewer').should('not.exist')
+ cy.findByTestId('pdf-viewer').should('not.exist')
cy.get('.cm-editor').should('be.visible')
})
})
diff --git a/server-ce/test/filestore-migration.spec.ts b/server-ce/test/filestore-migration.spec.ts
index ed55c71986..43b8528d2e 100644
--- a/server-ce/test/filestore-migration.spec.ts
+++ b/server-ce/test/filestore-migration.spec.ts
@@ -106,7 +106,7 @@ describe('filestore migration', function () {
name: /Create First Project|New Project/,
}).click()
cy.findByRole('link', { name: 'Example Project' }).click()
- cy.findByLabelText(/Project name/i).type(projectName)
+ cy.findByLabelText('Project name').type(projectName)
cy.findByRole('button', { name: 'Create' }).click()
cy.url()
.should('match', /\/project\/[a-fA-F0-9]{24}/)
diff --git a/server-ce/test/git-bridge.spec.ts b/server-ce/test/git-bridge.spec.ts
index 53b1bae54c..4d6a069416 100644
--- a/server-ce/test/git-bridge.spec.ts
+++ b/server-ce/test/git-bridge.spec.ts
@@ -14,6 +14,8 @@ import http from 'isomorphic-git/http/web'
import LightningFS from '@isomorphic-git/lightning-fs'
import { throttledRecompile } from './helpers/compile'
+const USER = 'user@example.com'
+
describe('git-bridge', function () {
const ENABLED_VARS = {
GIT_BRIDGE_ENABLED: 'true',
@@ -35,18 +37,21 @@ describe('git-bridge', function () {
pro: true,
vars: ENABLED_VARS,
})
- ensureUserExists({ email: 'user@example.com' })
+ ensureUserExists({ email: USER })
function clearAllTokens() {
- cy.get('button.linking-git-bridge-revoke-button').each(el => {
- cy.wrap(el).click()
- cy.findByText('Delete token').click()
- })
+ cy.findAllByRole('button', { name: 'Remove' })
+ .not('[disabled]')
+ .each($button => {
+ cy.wrap($button).click()
+ cy.findByRole('button', { name: 'Delete token' }).click()
+ })
+ cy.findByRole('dialog').should('not.exist')
}
function maybeClearAllTokens() {
cy.visit('/user/settings')
- cy.findByText('Git integration')
+ cy.findByRole('heading', { name: 'Git integration' })
cy.get('button')
.contains(/Generate token|Add another token/)
.then(btn => {
@@ -57,66 +62,83 @@ describe('git-bridge', function () {
}
beforeEach(function () {
- login('user@example.com')
+ login(USER)
})
it('should render the git-bridge UI in the settings', () => {
maybeClearAllTokens()
cy.visit('/user/settings')
- cy.findByText('Git integration')
- cy.get('button').contains('Generate token').click()
- cy.get('code')
+ cy.findByRole('heading', { name: 'Git integration' })
+ cy.findByRole('button', {
+ name: 'Git integration Generate token',
+ }).click()
+ cy.findByLabelText('Git authentication token')
.contains(/olp_[a-zA-Z0-9]{16}/)
+ .then(el => el.text())
.as('newToken')
cy.findAllByText('Close').last().click()
cy.get('@newToken').then(token => {
// There can be more than one token with the same prefix when retrying
cy.findAllByText(
- `${token.text().slice(0, 'olp_1234'.length)}${'*'.repeat(12)}`
+ `${token.slice(0, 'olp_1234'.length)}${'*'.repeat(12)}`
).should('have.length.at.least', 1)
})
- cy.get('button').contains('Generate token').should('not.exist')
- cy.get('button').contains('Add another token').should('exist')
+ cy.findByRole('button', {
+ name: 'Git integration Generate token',
+ }).should('not.exist')
+ cy.findByRole('button', { name: 'Add another token' }).should('exist')
clearAllTokens()
- cy.get('button').contains('Generate token').should('exist')
- cy.get('button').contains('Add another token').should('not.exist')
+ cy.findByRole('button', {
+ name: 'Git integration Generate token',
+ }).should('exist')
+ cy.findByRole('button', { name: 'Add another token' }).should('not.exist')
})
it('should render the git-bridge UI in the editor', function () {
maybeClearAllTokens()
createProject('git').as('projectId')
cy.findByRole('navigation', {
- name: /Project actions/i,
+ name: 'Project actions',
})
- .findByRole('button', { name: /Menu/i })
+ .findByRole('button', { name: 'Menu' })
.click()
- cy.findByText('Sync')
- cy.findByText('Git').click()
+ cy.findByTestId('left-menu').within(() => {
+ cy.findByRole('heading', { name: 'Sync' })
+ cy.findByRole('button', { name: 'Git' }).click()
+ })
cy.findByTestId('git-bridge-modal').within(() => {
cy.get('@projectId').then(id => {
- cy.get('code').contains(`git clone ${gitURL(id.toString())}`)
+ cy.findByLabelText('Git clone project command').contains(
+ `git clone ${gitURL(id.toString())}`
+ )
})
cy.findByRole('button', {
- name: /generate token/i,
+ name: 'Generate token',
}).click()
- cy.get('code').contains(/olp_[a-zA-Z0-9]{16}/)
+ cy.findByLabelText('Git authentication token').contains(
+ /olp_[a-zA-Z0-9]{16}/
+ )
})
// Re-open
cy.url().then(url => cy.visit(url))
cy.findByRole('navigation', {
- name: /Project actions/i,
+ name: 'Project actions',
})
- .findByRole('button', { name: /Menu/i })
+ .findByRole('button', { name: 'Menu' })
.click()
- cy.findByText('Git').click()
+ cy.findByTestId('left-menu').within(() => {
+ cy.findByRole('button', { name: 'Git' }).click()
+ })
cy.findByTestId('git-bridge-modal').within(() => {
cy.get('@projectId').then(id => {
cy.get('code').contains(`git clone ${gitURL(id.toString())}`)
})
- cy.findByText('Generate token').should('not.exist')
+ cy.findByRole('button', {
+ name: 'Generate token',
+ }).should('not.exist')
cy.findByText(/generate a new one in Account settings/)
- cy.findByText('Go to settings')
+ cy.findByRole('link', { name: 'Go to settings' })
.should('have.attr', 'target', '_blank')
.and('have.attr', 'href', '/user/settings')
})
@@ -197,18 +219,23 @@ describe('git-bridge', function () {
const recompile = throttledRecompile()
cy.findByRole('navigation', {
- name: /Project actions/i,
+ name: 'Project actions',
})
- .findByRole('button', { name: /Menu/i })
+ .findByRole('button', { name: 'Menu' })
.click()
- cy.findByText('Sync')
- cy.findByText('Git').click()
+ cy.findByTestId('left-menu').within(() => {
+ cy.findByRole('heading', { name: 'Sync' })
+ cy.findByRole('button', { name: 'Git' }).click()
+ })
cy.get('@projectId').then(projectId => {
cy.findByTestId('git-bridge-modal').within(() => {
- cy.get('code').contains(`git clone ${gitURL(projectId.toString())}`)
+ cy.findByLabelText('Git clone project command').contains(
+ `git clone ${gitURL(projectId.toString())}`
+ )
})
+ cy.findByRole('heading', { name: 'Clone with Git' })
cy.findByRole('button', {
- name: /generate token/i,
+ name: 'Generate token',
}).click()
cy.get('code')
.contains(/olp_[a-zA-Z0-9]{16}/)
@@ -255,8 +282,8 @@ describe('git-bridge', function () {
},
}
const authorOptions = {
- author: { name: 'user', email: 'user@example.com' },
- committer: { name: 'user', email: 'user@example.com' },
+ author: { name: 'user', email: USER },
+ committer: { name: 'user', email: USER },
}
const mainTex = `${dir}/main.tex`
@@ -372,24 +399,26 @@ Hello world
})
function checkDisabled() {
- ensureUserExists({ email: 'user@example.com' })
+ ensureUserExists({ email: USER })
it('should not render the git-bridge UI in the settings', () => {
- login('user@example.com')
+ login(USER)
cy.visit('/user/settings')
- cy.findByText('Git integration').should('not.exist')
+ cy.findByRole('heading', { name: 'Git integration' }).should('not.exist')
})
it('should not render the git-bridge UI in the editor', function () {
- login('user@example.com')
+ login(USER)
createProject('maybe git')
cy.findByRole('navigation', {
- name: /Project actions/i,
+ name: 'Project actions',
})
- .findByRole('button', { name: /Menu/i })
+ .findByRole('button', { name: 'Menu' })
.click()
- cy.findByText('Word Count') // wait for lazy loading
- cy.findByText('Sync').should('not.exist')
- cy.findByText('Git').should('not.exist')
+ cy.findByTestId('left-menu').within(() => {
+ cy.findByRole('button', { name: 'Word Count' }) // wait for lazy loading
+ cy.findByRole('heading', { name: 'Sync' }).should('not.exist')
+ cy.findByRole('button', { name: 'Git' }).should('not.exist')
+ })
})
}
diff --git a/server-ce/test/helpers/compile.ts b/server-ce/test/helpers/compile.ts
index d41e43221f..742cc83b92 100644
--- a/server-ce/test/helpers/compile.ts
+++ b/server-ce/test/helpers/compile.ts
@@ -32,7 +32,7 @@ export function prepareWaitForNextCompileSlot() {
queueReset()
triggerCompile()
cy.log('Wait for compile to finish')
- cy.findByText('Recompile').should('be.visible')
+ cy.findByRole('button', { name: 'Recompile' }).should('be.visible')
})
}
function recompile() {
diff --git a/server-ce/test/helpers/project.ts b/server-ce/test/helpers/project.ts
index 7f15b959e8..107cca0d95 100644
--- a/server-ce/test/helpers/project.ts
+++ b/server-ce/test/helpers/project.ts
@@ -2,11 +2,13 @@ import { login } from './login'
import { openEmail } from './email'
import { v4 as uuid } from 'uuid'
+export const NEW_PROJECT_BUTTON_MATCHER = /new project/i
+
export function createProject(
name: string,
{
type = 'Blank project',
- newProjectButtonMatcher = /new project/i,
+ newProjectButtonMatcher = NEW_PROJECT_BUTTON_MATCHER,
open = true,
}: {
type?: 'Blank project' | 'Example project'
@@ -41,7 +43,7 @@ export function createProject(
cy.findAllByText(type, { exact: false }).first().click()
cy.findByRole('dialog').within(() => {
cy.get('input').type(name)
- cy.findByText('Create').click()
+ cy.findByRole('button', { name: 'Create' }).click()
})
if (open) {
cy.url().should('match', /\/project\/[a-fA-F0-9]{24}/)
@@ -104,7 +106,7 @@ function shareProjectByEmail(
level: 'Viewer' | 'Editor'
) {
openProjectByName(projectName)
- cy.findByText('Share').click()
+ cy.findByRole('button', { name: 'Share' }).click()
cy.findByRole('dialog').within(() => {
cy.findByLabelText('Add email address', { selector: 'input' }).type(
`${email},`
@@ -115,10 +117,10 @@ function shareProjectByEmail(
cy.findByTestId('add-collaborator-select')
.click()
.then(() => {
- cy.findByText(level).click()
+ cy.findByRole('option', { name: level }).click()
})
})
- cy.findByText('Invite').click({ force: true })
+ cy.findByRole('button', { name: 'Invite' }).click()
cy.findByText('Invite not yet accepted.')
})
}
@@ -203,7 +205,9 @@ export function waitForMainDocToLoad() {
export function openFile(fileName: string, waitFor: string) {
// force: The file-tree pane is too narrow to display the full name.
- cy.findByTestId('file-tree').findByText(fileName).click({ force: true })
+ cy.findByRole('navigation', { name: 'Project files and outline' })
+ .findByRole('treeitem', { name: fileName })
+ .click({ force: true })
// wait until we've switched to the selected file
cy.findByText('Loading…').should('not.exist')
@@ -221,7 +225,9 @@ export function createNewFile() {
cy.findByText('Create').click()
})
// force: The file-tree pane is too narrow to display the full name.
- cy.findByTestId('file-tree').findByText(fileName).click({ force: true })
+ cy.findByTestId('file-tree')
+ .findByRole('treeitem', { name: fileName })
+ .click({ force: true })
// wait until we've switched to the newly created empty file
cy.findByText('Loading…').should('not.exist')
diff --git a/server-ce/test/history.spec.ts b/server-ce/test/history.spec.ts
index 485f7c8c58..2f83c9890b 100644
--- a/server-ce/test/history.spec.ts
+++ b/server-ce/test/history.spec.ts
@@ -13,29 +13,49 @@ describe('History', function () {
function addLabel(name: string) {
cy.log(`add label ${JSON.stringify(name)}`)
- cy.findByText('Labels').click()
- cy.findAllByTestId('history-version-details')
- .first()
- .within(() => {
- cy.get('button').click() // TODO: add test-id or aria-label
- cy.findByText('Label this version').click()
+ // The input is not clickable due to being visually hidden, click its label instead
+ cy.findByRole('complementary', {
+ name: 'Project history and labels',
+ }).within(() => {
+ cy.findByRole('group', {
+ name: 'Show all of the project history or only labelled versions.',
+ }).within(() => {
+ cy.findByText('Labels').click()
})
+ cy.findByRole('radio', { name: 'Labels' }).should('be.checked')
+ cy.findByRole('radio', { name: 'All history' }).should('not.be.checked')
+ cy.findAllByTestId('history-version-details')
+ .first()
+ .within(() => {
+ cy.findByRole('button', { name: 'More actions' }).click()
+ cy.findByRole('menuitem', { name: 'Label this version' }).click()
+ })
+ })
cy.findByRole('dialog').within(() => {
- cy.findByLabelText(/New label name/i)
- .as('input')
- .type(`${name}{enter}`)
+ cy.findByLabelText('New label name').type(`${name}{enter}`)
})
}
function downloadVersion(name: string) {
cy.log(`download version ${JSON.stringify(name)}`)
- cy.findByText('Labels').click()
- cy.findByText(name)
- .closest('[data-testid="history-version-details"]')
- .within(() => {
- cy.get('.history-version-dropdown-menu-btn').click()
- cy.findByText('Download this version').click()
+ // The input is not clickable due to being visually hidden, click its label instead
+ cy.findByRole('complementary', {
+ name: 'Project history and labels',
+ }).within(() => {
+ cy.findByRole('group', {
+ name: 'Show all of the project history or only labelled versions.',
+ }).within(() => {
+ cy.findByText('Labels').click()
})
+ cy.findByRole('radio', { name: 'Labels' }).should('be.checked')
+ cy.findByRole('radio', { name: 'All history' }).should('not.be.checked')
+ cy.findByText(name)
+ .closest('[data-testid="history-version-details"]')
+ .within(() => {
+ cy.findByRole('button', { name: 'More actions' }).click()
+ cy.findByRole('menuitem', { name: 'Download this version' }).click()
+ })
+ })
}
const CLASS_ADDITION = 'ol-cm-addition-marker'
@@ -46,11 +66,13 @@ describe('History', function () {
const recompile = throttledRecompile()
cy.log('add content, including a line that will get removed soon')
- cy.findByText('\\maketitle').parent().click()
- cy.findByText('\\maketitle').parent().type('\n% added')
- cy.findByText('\\maketitle').parent().type('\n% to be removed')
+ cy.findByRole('textbox', { name: 'Source Editor editing' }).within(() => {
+ cy.findByText('\\maketitle').parent().click()
+ cy.findByText('\\maketitle').parent().type('\n% added')
+ cy.findByText('\\maketitle').parent().type('\n% to be removed')
+ })
recompile()
- cy.findByText('History').click()
+ cy.findByRole('button', { name: 'History' }).click()
cy.log('expect to see additions in history')
cy.get('.document-diff-container').within(() => {
@@ -61,10 +83,10 @@ describe('History', function () {
addLabel('Before removal')
cy.log('remove content')
- cy.findByText('Back to editor').click()
+ cy.findByRole('button', { name: 'Back to editor' }).click()
cy.findByText('% to be removed').parent().type('{end}{shift}{upArrow}{del}')
recompile()
- cy.findByText('History').click()
+ cy.findByRole('button', { name: 'History' }).click()
cy.log('expect to see annotation for newly removed content in history')
cy.get('.document-diff-container').within(() => {
@@ -75,18 +97,32 @@ describe('History', function () {
addLabel('After removal')
cy.log('add more content after labeling')
- cy.findByText('Back to editor').click()
- cy.findByText('\\maketitle').parent().click()
- cy.findByText('\\maketitle').parent().type('\n% more')
+ cy.findByRole('button', { name: 'Back to editor' }).click()
+ cy.findByRole('textbox', { name: 'Source Editor editing' }).within(() => {
+ cy.findByText('\\maketitle').parent().click()
+ cy.findByText('\\maketitle').parent().type('\n% more')
+ })
recompile()
cy.log('compare non current versions')
- cy.findByText('History').click()
- cy.findByText('Labels').click()
- cy.findAllByTestId('compare-icon-version').last().click()
- cy.findAllByTestId('compare-icon-version').filter(':visible').click()
- cy.findByText('Compare up to this version').click()
-
+ cy.findByRole('button', { name: 'History' }).click()
+ // The input is not clickable due to being visually hidden, click its label instead
+ cy.findByRole('complementary', {
+ name: 'Project history and labels',
+ }).within(() => {
+ cy.findByRole('group', {
+ name: 'Show all of the project history or only labelled versions.',
+ }).within(() => {
+ cy.findByText('Labels').click()
+ })
+ cy.findByRole('radio', { name: 'Labels' }).should('be.checked')
+ cy.findByRole('radio', { name: 'All history' }).should('not.be.checked')
+ cy.findAllByTestId('compare-icon-version').last().click()
+ cy.findAllByTestId('compare-icon-version').filter(':visible').click()
+ cy.findByRole('menuitem', {
+ name: 'Compare up to this version',
+ }).click()
+ })
cy.log(
'expect to see annotation for removed content between the two versions'
)
diff --git a/server-ce/test/learn-wiki.spec.ts b/server-ce/test/learn-wiki.spec.ts
index c0cc8729fe..1d8ce44812 100644
--- a/server-ce/test/learn-wiki.spec.ts
+++ b/server-ce/test/learn-wiki.spec.ts
@@ -27,40 +27,49 @@ describe('LearnWiki', function () {
it('should add a documentation entry to the nav bar', () => {
login(REGULAR_USER)
cy.visit('/project')
- cy.get('nav').findByText('Documentation')
+ cy.findByRole('menuitem', { name: 'Documentation' }).should(
+ 'have.attr',
+ 'href',
+ '/learn'
+ )
})
it('should display a tutorial link in the welcome page', () => {
login(WITHOUT_PROJECTS_USER)
cy.visit('/project')
- cy.findByText(LABEL_LEARN_LATEX)
+ cy.findByRole('link', { name: LABEL_LEARN_LATEX })
+ .should('have.attr', 'href', '/learn/latex/Learn_LaTeX_in_30_minutes')
+ .and('have.attr', 'target', '_blank')
+ .within(() => {
+ cy.get('img').should('have.attr', 'src').and('not.be.empty')
+ })
})
it('should render wiki page', () => {
login(REGULAR_USER)
cy.visit(UPLOADING_A_PROJECT_URL)
// Wiki content
- cy.get('.page').findByText('Uploading a project')
- cy.get('.page').contains(/how to create an Overleaf project/)
- cy.get('img[alt="Creating a new project on Overleaf"]')
+ cy.findByRole('heading', { name: 'Uploading a project' })
+ cy.contains(/how to create an Overleaf project/)
+ cy.findByRole('img', { name: 'Creating a new project on Overleaf' })
.should('be.visible')
.and((el: any) => {
expect(el[0].naturalWidth, 'renders image').to.be.greaterThan(0)
})
// Wiki navigation
- cy.get('.contents').findByText('Copying a project')
+ cy.findByRole('link', { name: 'Copying a project' }).should('exist')
})
it('should navigate back and forth', function () {
login(REGULAR_USER)
cy.visit(COPYING_A_PROJECT_URL)
- cy.get('.page').findByText('Copying a project')
- cy.get('.contents').findByText('Uploading a project').click()
+ cy.findByRole('heading', { name: 'Copying a project' })
+ cy.findByRole('link', { name: 'Uploading a project' }).click()
cy.url().should('contain', UPLOADING_A_PROJECT_URL)
- cy.get('.page').findByText('Uploading a project')
- cy.get('.contents').findByText('Copying a project').click()
+ cy.findByRole('heading', { name: 'Uploading a project' })
+ cy.findByRole('link', { name: 'Copying a project' }).click()
cy.url().should('contain', COPYING_A_PROJECT_URL)
- cy.get('.page').findByText('Copying a project')
+ cy.findByRole('heading', { name: 'Copying a project' })
})
})
diff --git a/server-ce/test/project-list.spec.ts b/server-ce/test/project-list.spec.ts
index 998fcf9ffb..443a3c41af 100644
--- a/server-ce/test/project-list.spec.ts
+++ b/server-ce/test/project-list.spec.ts
@@ -21,8 +21,10 @@ describe('Project List', () => {
it("'Import from GitHub' is not displayed in the welcome page", () => {
login(WITHOUT_PROJECTS_USER)
cy.visit('/project')
- cy.findByText('Create a new project').click()
- cy.findByText(/Import from GitHub/i).should('not.exist')
+ cy.findByRole('button', { name: 'Create a new project' }).click()
+ cy.findByRole('menuitem', { name: 'Import from GitHub' }).should(
+ 'not.exist'
+ )
})
})
@@ -66,42 +68,50 @@ describe('Project List', () => {
it('can assign and remove tags to projects', () => {
const tagName = uuid().slice(0, 7) // long tag names are truncated in the UI, which affects selectors
cy.log('select project')
- cy.get(`[aria-label="Select ${projectName}"]`).click()
+ cy.findByRole('checkbox', { name: `Select ${projectName}` }).check()
cy.log('add tag to project')
- cy.get('button[aria-label="Tags"]').click()
- cy.findByText('Create new tag').click()
- cy.get('input[name="new-tag-form-name"]').type(`${tagName}{enter}`)
- cy.get(`button[aria-label="Select tag ${tagName}"]`) // tag label in project row
+ cy.findByRole('button', { name: 'Tags' }).click()
+ cy.findByRole('menuitem', { name: 'Create new tag' }).click()
+ cy.findByRole('dialog').within(() => {
+ cy.findByRole('heading', { name: 'Create new tag' })
+ cy.findByLabelText('New tag name').type(`${tagName}{enter}`)
+ })
+ cy.findByRole('button', { name: `Select tag ${tagName}` }) // tag label in project row
cy.log('remove tag')
- cy.get(`button[aria-label="Remove tag ${tagName}"]`)
+ cy.findByRole('button', { name: `Remove tag ${tagName}` })
.first()
- .click({ force: true })
- cy.get(`button[aria-label="Select tag ${tagName}"]`).should('not.exist')
+ .click()
+ cy.findByRole('button', { name: `Select tag ${tagName}` }).should(
+ 'not.exist'
+ )
})
it('can filter by tag', () => {
cy.log('create a separate project to filter')
const nonTaggedProjectName = `project-${uuid()}`
- login(REGULAR_USER)
createProject(nonTaggedProjectName, { open: false })
cy.log('select project')
- cy.get(`[aria-label="Select ${projectName}"]`).click()
+ cy.findByRole('checkbox', { name: `Select ${projectName}` }).check()
cy.log('add tag to project')
const tagName = uuid().slice(0, 7) // long tag names are truncated in the UI, which affects selectors
- cy.get('button[aria-label="Tags"]').click()
- cy.findByText('Create new tag').click()
- cy.get('input[name="new-tag-form-name"]').type(`${tagName}{enter}`)
+ cy.findByRole('button', { name: 'Tags' }).click()
+ cy.findByRole('menuitem', { name: 'Create new tag' }).click()
+
+ cy.findByRole('dialog').within(() => {
+ cy.findByRole('heading', { name: 'Create new tag' })
+ cy.findByLabelText('New tag name').type(`${tagName}{enter}`)
+ })
cy.log(
'check the non-tagged project is filtered out after clicking the tag'
)
- cy.findByText(nonTaggedProjectName).should('exist')
- cy.get('button').contains(tagName).click({ force: true })
- cy.findByText(nonTaggedProjectName).should('not.exist')
+ cy.findByRole('link', { name: nonTaggedProjectName }).should('exist')
+ cy.findByRole('button', { name: `Select tag ${tagName}` }).click()
+ cy.findByRole('link', { name: nonTaggedProjectName }).should('not.exist')
})
})
})
diff --git a/server-ce/test/project-sharing.spec.ts b/server-ce/test/project-sharing.spec.ts
index 2a90df7368..003ee4f334 100644
--- a/server-ce/test/project-sharing.spec.ts
+++ b/server-ce/test/project-sharing.spec.ts
@@ -43,7 +43,7 @@ describe('Project Sharing', function () {
createProject(projectName)
// Add chat message
- cy.findByText('Chat').click()
+ cy.findByRole('button', { name: 'Chat' }).click()
// wait for lazy loading of the chat pane
cy.findByText('Send your first message to your collaborators')
cy.get(
@@ -61,11 +61,11 @@ describe('Project Sharing', function () {
function expectContentReadOnlyAccess() {
cy.url().should('match', /\/project\/[a-fA-F0-9]{24}/)
- cy.findByRole('textbox', { name: /Source Editor editing/i }).should(
+ cy.findByRole('textbox', { name: 'Source Editor editing' }).should(
'contain.text',
'\\maketitle'
)
- cy.findByRole('textbox', { name: /Source Editor editing/i }).should(
+ cy.findByRole('textbox', { name: 'Source Editor editing' }).should(
'have.attr',
'contenteditable',
'false'
@@ -77,12 +77,12 @@ describe('Project Sharing', function () {
cy.url().should('match', /\/project\/[a-fA-F0-9]{24}/)
const recompile = throttledRecompile()
// wait for the editor to finish loading
- cy.findByRole('textbox', { name: /Source Editor editing/i }).should(
+ cy.findByRole('textbox', { name: 'Source Editor editing' }).should(
'contain.text',
'\\maketitle'
)
// the editor should be writable
- cy.findByRole('textbox', { name: /Source Editor editing/i }).should(
+ cy.findByRole('textbox', { name: 'Source Editor editing' }).should(
'have.attr',
'contenteditable',
'true'
@@ -90,14 +90,20 @@ describe('Project Sharing', function () {
cy.findByText('\\maketitle').parent().click()
cy.findByText('\\maketitle').parent().type(`\n\\section{{}${section}}`)
// should have written
- cy.findByRole('textbox', { name: /Source Editor editing/i }).should(
+ cy.findByRole('textbox', { name: 'Source Editor editing' }).should(
'contain.text',
`\\section{${section}}`
)
// check PDF
recompile()
- cy.get('.pdf-viewer').should('contain.text', projectName)
- cy.get('.pdf-viewer').should('contain.text', section)
+ cy.findByRole('region', { name: 'PDF preview and logs' }).within(() => {
+ cy.findByLabelText(/Page.*1/i).should('be.visible')
+ cy.findByText(projectName).should('be.visible')
+ })
+ cy.findByRole('region', { name: 'PDF preview and logs' }).within(() => {
+ cy.findByLabelText(/Page.*1/i).should('be.visible')
+ cy.contains(section)
+ })
}
function expectNoAccess() {
@@ -117,7 +123,7 @@ describe('Project Sharing', function () {
}
function expectChatAccess() {
- cy.findByText('Chat').click()
+ cy.findByRole('button', { name: 'Chat' }).click()
cy.findByText('New Chat Message')
}
@@ -132,17 +138,17 @@ describe('Project Sharing', function () {
}
function expectNoChatAccess() {
- cy.findByText('Layout') // wait for lazy loading
- cy.findByText('Chat').should('not.exist')
+ cy.findByRole('button', { name: 'Layout' }) // wait for lazy loading
+ cy.findByRole('button', { name: 'Chat' }).should('not.exist')
}
function expectNoHistoryAccess() {
- cy.findByText('Layout') // wait for lazy loading
- cy.findByText('History').should('not.exist')
+ cy.findByRole('button', { name: 'Layout' }) // wait for lazy loading
+ cy.findByRole('button', { name: 'History' }).should('not.exist')
}
function expectCommentAccess() {
- cy.findByRole('textbox', { name: /Source Editor editing/i }).should(
+ cy.findByRole('textbox', { name: 'Source Editor editing' }).should(
'contain.text',
'\\maketitle'
)
@@ -151,11 +157,11 @@ describe('Project Sharing', function () {
cy.findByRole('button', { name: 'Add comment' }).should('be.visible')
- cy.findByRole('textbox', { name: /Source Editor editing/i }).click()
+ cy.findByRole('textbox', { name: 'Source Editor editing' }).click()
}
function expectNoCommentAccess() {
- cy.findByRole('textbox', { name: /Source Editor editing/i }).should(
+ cy.findByRole('textbox', { name: 'Source Editor editing' }).should(
'contain.text',
'\\maketitle'
)
@@ -163,7 +169,7 @@ describe('Project Sharing', function () {
cy.findByText('\\maketitle').parent().dblclick()
cy.findByRole('button', { name: 'Add comment' }).should('not.exist')
- cy.findByRole('textbox', { name: /Source Editor editing/i }).click()
+ cy.findByRole('textbox', { name: 'Source Editor editing' }).click()
}
function expectFullReadOnlyAccess() {
@@ -200,12 +206,15 @@ describe('Project Sharing', function () {
}
function expectEditAuthoredAs(author: string) {
- cy.findByText('History').click()
- cy.findAllByTestId('history-version-metadata-users')
- .first()
- .should('contain.text', author) // might have other edits in the same group
+ cy.findByRole('button', { name: 'History' }).click()
+ cy.findByRole('complementary', {
+ name: 'Project history and labels',
+ }).within(() => {
+ cy.findAllByTestId('history-version-metadata-users')
+ .first()
+ .should('contain.text', author) // might have other edits in the same group
+ })
}
-
describe('via email', function () {
const email = 'collaborator-email@example.com'
ensureUserExists({ email })
diff --git a/server-ce/test/sandboxed-compiles.spec.ts b/server-ce/test/sandboxed-compiles.spec.ts
index 06f516c765..8599809c7c 100644
--- a/server-ce/test/sandboxed-compiles.spec.ts
+++ b/server-ce/test/sandboxed-compiles.spec.ts
@@ -30,30 +30,35 @@ describe('SandboxedCompiles', function () {
createProject('sandboxed')
const recompile = throttledRecompile()
cy.log('wait for compile')
- cy.get('.pdf-viewer').should('contain.text', 'sandboxed')
+ cy.findByRole('region', { name: 'PDF preview and logs' }).should(
+ 'contain.text',
+ 'sandboxed'
+ )
cy.log('Check which compiler version was used, expect 2023')
- cy.get('[aria-label="View logs"]').click()
+ cy.findByRole('button', { name: 'View logs' }).click()
cy.findByText(/This is pdfTeX, Version .+ \(TeX Live 2023\) /)
cy.log('Switch TeXLive version from 2023 to 2022')
cy.findByRole('navigation', {
- name: /Project actions/i,
+ name: 'Project actions',
})
- .findByRole('button', { name: /Menu/i })
+ .findByRole('button', { name: 'Menu' })
.click()
- cy.findByText(LABEL_TEX_LIVE_VERSION)
- .parent()
- .findByText('2023')
- .parent()
- .select('2022')
- cy.get('.left-menu-modal-backdrop').click()
+ cy.findByRole('dialog').within(() => {
+ cy.findByRole('option', { name: '2023' }).should('be.selected')
+ cy.findByRole('combobox', { name: LABEL_TEX_LIVE_VERSION }).select(
+ '2022'
+ )
+ })
+ cy.get('body').type('{esc}')
+ cy.findByRole('dialog').should('not.exist')
cy.log('Trigger compile with other TeX Live version')
recompile()
cy.log('Check which compiler version was used, expect 2022')
- cy.get('[aria-label="View logs"]').click()
+ cy.findByRole('button', { name: 'View logs' }).click()
cy.findByText(/This is pdfTeX, Version .+ \(TeX Live 2022\) /)
})
@@ -101,39 +106,43 @@ describe('SandboxedCompiles', function () {
projectName = `Project ${uuid()}`
createProject(projectName)
const recompile = throttledRecompile()
- cy.findByText('\\maketitle').parent().click()
- cy.findByText('\\maketitle')
- .parent()
- .type(
- `\n\\pagebreak\n\\section{{}Section A}\n\\pagebreak\n\\section{{}Section B}\n\\pagebreak`
- )
+ cy.findByRole('textbox', { name: 'Source Editor editing' }).within(
+ () => {
+ cy.findByText('\\maketitle').parent().click()
+ cy.findByText('\\maketitle')
+ .parent()
+ .type(
+ `\n\\pagebreak\n\\section{{}Section A}\n\\pagebreak\n\\section{{}Section B}\n\\pagebreak`
+ )
+ }
+ )
recompile()
cy.log('wait for pdf-rendering')
- cy.get('.pdf-viewer').within(() => {
- cy.findByText(projectName)
- })
+ cy.findByRole('region', { name: 'PDF preview and logs' }).findByText(
+ projectName
+ )
})
it('should sync to code', function () {
cy.log('navigate to \\maketitle using double click in PDF')
- cy.get('.pdf-viewer').within(() => {
- cy.findByText(projectName).dblclick()
- })
+ cy.findByRole('region', { name: 'PDF preview and logs' })
+ .findByText(projectName)
+ .dblclick()
cy.get('.cm-activeLine').should('have.text', '\\maketitle')
cy.log('navigate to Section A using double click in PDF')
- cy.get('.pdf-viewer').within(() => {
- cy.findByText('Section A').dblclick()
- })
+ cy.findByRole('region', { name: 'PDF preview and logs' })
+ .findByText('Section A')
+ .dblclick()
cy.get('.cm-activeLine').should('have.text', '\\section{Section A}')
cy.log('navigate to Section B using arrow button')
- cy.get('.pdfjs-viewer-inner')
+ cy.findByTestId('pdfjs-viewer-inner')
.should('have.prop', 'scrollTop')
.as('start')
- cy.get('.pdf-viewer').within(() => {
- cy.findByText('Section B').scrollIntoView()
- })
+ cy.findByRole('region', { name: 'PDF preview and logs' })
+ .findByText('Section B')
+ .scrollIntoView()
cy.get('@start').then((start: any) => {
waitUntilScrollingFinished('.pdfjs-viewer-inner', start)
})
@@ -141,21 +150,27 @@ describe('SandboxedCompiles', function () {
// Cypress appears to click on a button that references a stale position.
// Adding a cy.wait() statement is the most reliable "fix" so far :/
cy.wait(1000)
- cy.get('[aria-label^="Go to PDF location in code"]').click()
+ cy.findByRole('button', {
+ name: 'Go to PDF location in code (Tip: double click on the PDF for best results)',
+ }).click()
cy.get('.cm-activeLine').should('have.text', '\\section{Section B}')
})
it('should sync to pdf', function () {
cy.log('zoom in')
- cy.findByText('45%').click()
- cy.findByText('400%').click()
+ cy.findByRole('button', { name: /^\d+%$/ }).click() // TODO: ARIA label
+ cy.findByRole('menuitem', { name: '400%' }).click()
cy.log('scroll to top')
- cy.get('.pdfjs-viewer-inner').scrollTo('top')
+ cy.findByTestId('pdfjs-viewer-inner').scrollTo('top')
waitUntilScrollingFinished('.pdfjs-viewer-inner', -1).as('start')
cy.log('navigate to title')
- cy.findByText('\\maketitle').parent().click()
- cy.get('[aria-label="Go to code location in PDF"]').click()
+ cy.findByRole('textbox', { name: 'Source Editor editing' }).within(
+ () => {
+ cy.findByText('\\maketitle').parent().click()
+ }
+ )
+ cy.findByRole('button', { name: 'Go to code location in PDF' }).click()
cy.get('@start').then((start: any) => {
waitUntilScrollingFinished('.pdfjs-viewer-inner', start)
.as('title')
@@ -163,10 +178,10 @@ describe('SandboxedCompiles', function () {
})
cy.log('navigate to Section A')
- cy.findByRole('textbox', { name: /Source Editor editing/i }).within(
- () => cy.findByText('Section A').click()
+ cy.findByRole('textbox', { name: 'Source Editor editing' }).within(() =>
+ cy.findByText('Section A').click()
)
- cy.get('[aria-label="Go to code location in PDF"]').click()
+ cy.findByRole('button', { name: 'Go to code location in PDF' }).click()
cy.get('@title').then((title: any) => {
waitUntilScrollingFinished('.pdfjs-viewer-inner', title)
.as('sectionA')
@@ -174,10 +189,10 @@ describe('SandboxedCompiles', function () {
})
cy.log('navigate to Section B')
- cy.findByRole('textbox', { name: /Source Editor editing/i }).within(
- () => cy.findByText('Section B').click()
+ cy.findByRole('textbox', { name: 'Source Editor editing' }).within(() =>
+ cy.findByText('Section B').click()
)
- cy.get('[aria-label="Go to code location in PDF"]').click()
+ cy.findByRole('button', { name: 'Go to code location in PDF' }).click()
cy.get('@sectionA').then((title: any) => {
waitUntilScrollingFinished('.pdfjs-viewer-inner', title)
.as('sectionB')
@@ -192,14 +207,18 @@ describe('SandboxedCompiles', function () {
login('user@example.com')
createProject('test-project')
const recompile = throttledRecompile()
- cy.findByText('\\maketitle').parent().click()
- cy.findByText('\\maketitle')
- .parent()
- .type('\n\\fakeCommand{} \n\\section{{}Test Section}')
+ cy.findByRole('textbox', { name: 'Source Editor editing' }).within(() => {
+ cy.findByText('\\maketitle').parent().click()
+ cy.findByText('\\maketitle')
+ .parent()
+ .type('\n\\fakeCommand{} \n\\section{{}Test Section}')
+ })
recompile()
recompile()
- cy.get('.pdf-viewer').should('contain.text', 'Test Section')
- cy.get('.logs-pane').should('not.contain.text', 'No PDF')
+ cy.findByRole('region', { name: 'PDF preview and logs' }).within(() => {
+ cy.findByText('Test Section').should('contain.text', 'Test Section')
+ })
+ cy.findByTestId('logs-pane').should('not.contain.text', 'No PDF')
})
}
@@ -208,30 +227,32 @@ describe('SandboxedCompiles', function () {
createProject('XeLaTeX')
const recompile = throttledRecompile()
cy.log('wait for compile')
- cy.get('.pdf-viewer').should('contain.text', 'XeLaTeX')
-
+ cy.findByRole('region', { name: 'PDF preview and logs' }).should(
+ 'contain.text',
+ 'XeLaTeX'
+ )
cy.log('Check which compiler was used, expect pdfLaTeX')
- cy.get('[aria-label="View logs"]').click()
+ cy.findByRole('button', { name: 'View logs' }).click()
cy.findByText(/This is pdfTeX/)
cy.log('Switch compiler to from pdfLaTeX to XeLaTeX')
cy.findByRole('navigation', {
- name: /Project actions/i,
+ name: 'Project actions',
})
- .findByRole('button', { name: /Menu/i })
+ .findByRole('button', { name: 'Menu' })
.click()
- cy.findByText('Compiler')
- .parent()
- .findByText('pdfLaTeX')
- .parent()
- .select('XeLaTeX')
- cy.get('.left-menu-modal-backdrop').click()
+ cy.findByRole('dialog').within(() => {
+ cy.findByRole('option', { name: 'pdfLaTeX' }).should('be.selected')
+ cy.findByRole('combobox', { name: 'Compiler' }).select('XeLaTeX')
+ })
+ cy.get('body').type('{esc}')
+ cy.findByRole('dialog').should('not.exist')
cy.log('Trigger compile with other compiler')
recompile()
cy.log('Check which compiler was used, expect XeLaTeX')
- cy.get('[aria-label="View logs"]').click()
+ cy.findByRole('button', { name: 'View logs' }).click()
cy.findByText(/This is XeTeX/)
})
}
@@ -252,9 +273,9 @@ describe('SandboxedCompiles', function () {
cy.log('Check that there is no TeX Live version toggle')
cy.findByRole('navigation', {
- name: /Project actions/i,
+ name: 'Project actions',
})
- .findByRole('button', { name: /Menu/i })
+ .findByRole('button', { name: 'Menu' })
.click()
cy.findByText('Word Count') // wait for lazy loading
cy.findByText(LABEL_TEX_LIVE_VERSION).should('not.exist')
diff --git a/server-ce/test/templates.spec.ts b/server-ce/test/templates.spec.ts
index 2d6287d0d8..2e61c67954 100644
--- a/server-ce/test/templates.spec.ts
+++ b/server-ce/test/templates.spec.ts
@@ -1,6 +1,6 @@
import { isExcludedBySharding, startWith } from './helpers/config'
import { ensureUserExists, login } from './helpers/login'
-import { createProject } from './helpers/project'
+import { createProject, NEW_PROJECT_BUTTON_MATCHER } from './helpers/project'
const WITHOUT_PROJECTS_USER = 'user-without-projects@example.com'
const ADMIN_USER = 'admin@example.com'
@@ -43,7 +43,9 @@ describe('Templates', () => {
it('should show templates link on welcome page', () => {
login(WITHOUT_PROJECTS_USER)
cy.visit('/')
- cy.findByText(LABEL_BROWSE_TEMPLATES).click()
+ cy.findByRole('link', { name: LABEL_BROWSE_TEMPLATES })
+ .should('have.attr', 'href', '/templates')
+ .click()
cy.url().should('match', /\/templates$/)
})
@@ -56,9 +58,9 @@ describe('Templates', () => {
createProject(name, { type: 'Example project' }).as('templateProjectId')
cy.findByRole('navigation', {
- name: /Project actions/i,
+ name: 'Project actions',
})
- .findByRole('button', { name: /Menu/i })
+ .findByRole('button', { name: 'Menu' })
.click()
cy.findByText('Manage Template').click()
@@ -139,9 +141,9 @@ describe('Templates', () => {
cy.visit(`/project/${projectId}`)
)
cy.findByRole('navigation', {
- name: /Project actions/i,
+ name: 'Project actions',
})
- .findByRole('button', { name: /Menu/i })
+ .findByRole('button', { name: 'Menu' })
.click()
cy.findByText('Manage Template').click()
cy.findByText('Publish').click()
@@ -168,9 +170,9 @@ describe('Templates', () => {
cy.url().should('match', /\/project\/[a-f0-9]{24}$/)
cy.get('.project-name').should('contain.text', 'Your Paper') // might have (1) suffix
cy.findByRole('navigation', {
- name: /Project actions/i,
+ name: 'Project actions',
})
- .findByRole('button', { name: /Menu/i })
+ .findByRole('button', { name: 'Menu' })
.click()
cy.findByText('Word Count') // wait for lazy loading
cy.findByText('Manage Template').should('not.exist')
@@ -191,9 +193,9 @@ describe('Templates', () => {
cy.visit(`/project/${projectId}`)
)
cy.findByRole('navigation', {
- name: /Project actions/i,
+ name: 'Project actions',
})
- .findByRole('button', { name: /Menu/i })
+ .findByRole('button', { name: 'Menu' })
.click()
cy.findByText('Manage Template').click()
cy.findByText('Unpublish')
@@ -206,9 +208,9 @@ describe('Templates', () => {
cy.visit(`/project/${projectId}`)
)
cy.findByRole('navigation', {
- name: /Project actions/i,
+ name: 'Project actions',
})
- .findByRole('button', { name: /Menu/i })
+ .findByRole('button', { name: 'Menu' })
.click()
cy.findByText('Manage Template').click()
cy.findByText('Unpublish').click()
@@ -218,9 +220,7 @@ describe('Templates', () => {
// check for template links, after creating the first project
cy.visit('/')
- cy.findAllByRole('button')
- .contains(/new project/i)
- .click()
+ cy.findAllByRole('button', { name: NEW_PROJECT_BUTTON_MATCHER }).click()
cy.findAllByText('All Templates')
.first()
.parent()
@@ -236,9 +236,9 @@ describe('Templates', () => {
createProject('maybe templates')
cy.findByRole('navigation', {
- name: /Project actions/i,
+ name: 'Project actions',
})
- .findByRole('button', { name: /Menu/i })
+ .findByRole('button', { name: 'Menu' })
.click()
cy.findByText('Word Count') // wait for lazy loading
cy.findByText('Manage Template').should('not.exist')
@@ -250,16 +250,14 @@ describe('Templates', () => {
// check for template links, after creating the first project
cy.visit('/')
- cy.findAllByRole('button')
- .contains(/new project/i)
- .click()
+ cy.findAllByRole('button', { name: NEW_PROJECT_BUTTON_MATCHER }).click()
cy.findAllByText('All Templates').should('not.exist')
})
it('should not show templates link on welcome page', () => {
login(WITHOUT_PROJECTS_USER)
cy.visit('/')
- cy.findByText(/new project/i) // wait for lazy loading
+ cy.findByText(NEW_PROJECT_BUTTON_MATCHER) // wait for lazy loading
cy.findByText(LABEL_BROWSE_TEMPLATES).should('not.exist')
})
}
diff --git a/server-ce/test/upgrading.spec.ts b/server-ce/test/upgrading.spec.ts
index 5edc260d5f..ace62c1386 100644
--- a/server-ce/test/upgrading.spec.ts
+++ b/server-ce/test/upgrading.spec.ts
@@ -56,9 +56,9 @@ describe('Upgrading', function () {
cy.log('Trigger full flush')
recompile()
cy.findByRole('navigation', {
- name: /Project Layout, Sharing, and Submission/i,
+ name: 'Project Layout, Sharing, and Submission',
})
- .findByRole('button', { name: /Menu/i })
+ .findByRole('button', { name: 'Menu' })
.click()
cy.findByText('Source').click()
cy.get('.left-menu-modal-backdrop').click({ force: true })
@@ -121,7 +121,7 @@ describe('Upgrading', function () {
cy.url().should('match', /\/project\/[a-fA-F0-9]{24}/)
cy.findByRole('navigation', {
- name: /Project actions/i,
+ name: 'Project actions',
}).within(() => {
cy.findByText(PROJECT_NAME)
})
diff --git a/services/web/frontend/extracted-translations.json b/services/web/frontend/extracted-translations.json
index 11d23fe9ee..1e965a6a73 100644
--- a/services/web/frontend/extracted-translations.json
+++ b/services/web/frontend/extracted-translations.json
@@ -665,7 +665,7 @@
"git_bridge_modal_review_access": "",
"git_bridge_modal_see_once": "",
"git_bridge_modal_use_previous_token": "",
- "git_clone_project": "",
+ "git_clone_project_command": "",
"git_clone_this_project": "",
"git_integration": "",
"git_integration_info": "",
diff --git a/services/web/frontend/js/features/settings/components/linking/integration-widget.tsx b/services/web/frontend/js/features/settings/components/linking/integration-widget.tsx
index d38e79d92e..70fe6fdf57 100644
--- a/services/web/frontend/js/features/settings/components/linking/integration-widget.tsx
+++ b/services/web/frontend/js/features/settings/components/linking/integration-widget.tsx
@@ -121,7 +121,9 @@ function ActionButton({
titleId,
}: ActionButtonProps) {
const { t } = useTranslation()
+ const upgradeTextId = `${titleId}-upgrade`
const linkTextId = `${titleId}-link`
+ const unlinkTextId = `${titleId}-unlink`
if (!hasFeature) {
return (
@@ -129,17 +131,19 @@ function ActionButton({
variant="primary"
href="/user/subscription/plans"
onClick={() => trackUpgradeClick(integration)}
- aria-labelledby={`${titleId} ${linkTextId}`}
+ aria-labelledby={`${titleId} ${upgradeTextId}`}
>
- {t('upgrade')}
+ {t('upgrade')}
)
} else if (linked) {
return (
{t('unlink')}
@@ -148,7 +152,12 @@ function ActionButton({
return (
<>
{disabled ? (
-
+
{t('link')}
) : (
@@ -156,6 +165,8 @@ function ActionButton({
variant="secondary"
href={linkPath}
onClick={() => trackLinkingClick(integration)}
+ aria-labelledby={`${linkTextId} ${titleId}`}
+ id={linkTextId}
>
{t('link')}
diff --git a/services/web/locales/en.json b/services/web/locales/en.json
index c93e9cb013..241f61291f 100644
--- a/services/web/locales/en.json
+++ b/services/web/locales/en.json
@@ -868,7 +868,7 @@
"git_bridge_modal_review_access": "<0>You have review access to this project.0> This means you can pull from __appName__ but you can’t push any changes you make back to this project.",
"git_bridge_modal_see_once": "You’ll only see this token once. To delete it or generate a new one, visit Account settings. For detailed instructions and troubleshooting, read our <0>help page0>.",
"git_bridge_modal_use_previous_token": "If you’re prompted for a password, you can use a previously generated Git authentication token. Or you can generate a new one in Account settings. For more support, read our <0>help page0>.",
- "git_clone_project": "Git clone project",
+ "git_clone_project_command": "Git clone project command",
"git_clone_this_project": "Git clone this project.",
"git_gitHub_dropbox_mendeley_papers_and_zotero_integrations": "Git, GitHub, Dropbox, Papers, Zotero, and Mendeley integrations",
"git_integration": "Git integration",
diff --git a/services/web/test/frontend/features/history/components/change-list.spec.tsx b/services/web/test/frontend/features/history/components/change-list.spec.tsx
index e27291ff1e..a2928a8212 100644
--- a/services/web/test/frontend/features/history/components/change-list.spec.tsx
+++ b/services/web/test/frontend/features/history/components/change-list.spec.tsx
@@ -148,7 +148,7 @@ describe('change list', function () {
name: /Project history and labels/i,
}).within(() => {
cy.findByRole('group', {
- name: /Show all of the project history/i,
+ name: 'Show all of the project history or only labelled versions.',
}).within(() => {
cy.findByText(/Labels/i).click()
})
@@ -353,7 +353,7 @@ describe('change list', function () {
name: /Project history and labels/i,
}).within(() => {
cy.findByRole('group', {
- name: /Show all of the project history/i,
+ name: 'Show all of the project history or only labelled versions.',
}).within(() => {
cy.findByText(/Labels/i).click()
})
@@ -716,7 +716,7 @@ describe('change list', function () {
name: /Project history and labels/i,
}).within(() => {
cy.findByRole('group', {
- name: /Show all of the project history/i,
+ name: 'Show all of the project history or only labelled versions.',
}).within(() => {
cy.findByText(/Labels/i).click()
})
diff --git a/services/web/test/frontend/features/settings/components/account-info-section.test.tsx b/services/web/test/frontend/features/settings/components/account-info-section.test.tsx
index fc6adebcda..cec460bae1 100644
--- a/services/web/test/frontend/features/settings/components/account-info-section.test.tsx
+++ b/services/web/test/frontend/features/settings/components/account-info-section.test.tsx
@@ -47,7 +47,7 @@ describe('', function () {
})
fireEvent.click(
screen.getByRole('button', {
- name: /update/i,
+ name: 'Update account info',
})
)
expect(updateMock.callHistory.called()).to.be.true
@@ -68,7 +68,7 @@ describe('', function () {
target: { value: 'john' },
})
const button = screen.getByRole('button', {
- name: /update/i,
+ name: 'Update account info',
}) as HTMLButtonElement
expect(button.disabled).to.be.true
diff --git a/services/web/test/frontend/features/settings/components/emails/emails-section-add-new-email.test.tsx b/services/web/test/frontend/features/settings/components/emails/emails-section-add-new-email.test.tsx
index 1fd4542f76..3458ab4747 100644
--- a/services/web/test/frontend/features/settings/components/emails/emails-section-add-new-email.test.tsx
+++ b/services/web/test/frontend/features/settings/components/emails/emails-section-add-new-email.test.tsx
@@ -63,17 +63,16 @@ function resetFetchMock() {
}
async function confirmCodeForEmail(email: string) {
- await screen.findByText(
- `Enter the 6-digit confirmation code sent to ${email}.`
- )
- const inputCode = screen.getByLabelText(/6-digit confirmation code/i)
+ const inputCode = await screen.findByRole('textbox', {
+ name: `Enter the 6-digit confirmation code sent to ${email}.`,
+ })
fireEvent.change(inputCode, { target: { value: '123456' } })
const submitCodeBtn = screen.getByRole('button', {
name: 'Confirm',
})
fireEvent.click(submitCodeBtn)
await waitForElementToBeRemoved(() =>
- screen.getByRole('button', { name: /confirming/i })
+ screen.getByRole('button', { name: 'Confirming' })
)
}
@@ -96,7 +95,7 @@ describe('', function () {
fetchMock.get('/user/emails?ensureAffiliation=true', [])
render()
- await screen.findByRole('button', { name: /add another email/i })
+ await screen.findByRole('button', { name: 'Add another email' })
})
it('renders input', async function () {
@@ -105,11 +104,11 @@ describe('', function () {
await fetchMock.callHistory.flush(true)
const button = await screen.findByRole('button', {
- name: /add another email/i,
+ name: 'Add another email',
})
fireEvent.click(button)
- await screen.findByLabelText(/email/i, { selector: 'input' })
+ await screen.findByRole('textbox', { name: 'Email' })
})
it('renders "Start adding your address" until a valid email is typed', async function () {
@@ -120,17 +119,17 @@ describe('', function () {
await fetchMock.callHistory.flush(true)
const button = await screen.findByRole('button', {
- name: /add another email/i,
+ name: 'Add another email',
})
fireEvent.click(button)
- const input = screen.getByLabelText(/email/i, { selector: 'input' })
+ const input = screen.getByRole('textbox', { name: 'Email' })
// initially the text is displayed and the "add email" button disabled
screen.getByText('Start by adding your email address.')
expect(
screen.getByRole('button', {
- name: /add new email/i,
+ name: 'Add new email',
}).disabled
).to.be.true
@@ -141,7 +140,7 @@ describe('', function () {
screen.getByText('Start by adding your email address.')
expect(
screen.getByRole('button', {
- name: /add new email/i,
+ name: 'Add new email',
}).disabled
).to.be.true
@@ -152,7 +151,7 @@ describe('', function () {
expect(screen.queryByText('Start by adding your email address.')).to.be.null
expect(
screen.getByRole('button', {
- name: /add new email/i,
+ name: 'Add new email',
}).disabled
).to.be.false
})
@@ -162,11 +161,11 @@ describe('', function () {
render()
const button = await screen.findByRole('button', {
- name: /add another email/i,
+ name: 'Add another email',
})
fireEvent.click(button)
- screen.getByRole('button', { name: /add new email/i })
+ screen.getByRole('button', { name: 'Add new email' })
})
it('prevent users from adding new emails when the limit is reached', async function () {
@@ -182,7 +181,7 @@ describe('', function () {
'You can have a maximum of 10 email addresses on this account. To add another email address, please delete an existing one.'
)
- expect(screen.queryByRole('button', { name: /add another email/i })).to.not
+ expect(screen.queryByRole('button', { name: 'Add another email' })).to.not
.exist
})
@@ -192,7 +191,7 @@ describe('', function () {
const addAnotherEmailBtn = await screen.findByRole(
'button',
- { name: /add another email/i }
+ { name: 'Add another email' }
)
await fetchMock.callHistory.flush(true)
@@ -203,14 +202,14 @@ describe('', function () {
.post('/user/emails/confirm-secondary', 200)
fireEvent.click(addAnotherEmailBtn)
- const input = screen.getByLabelText(/email/i, { selector: 'input' })
+ const input = screen.getByRole('textbox', { name: 'Email' })
fireEvent.change(input, {
target: { value: userEmailData.email },
})
const submitBtn = screen.getByRole('button', {
- name: /add new email/i,
+ name: 'Add new email',
})
expect(submitBtn.disabled).to.be.false
@@ -221,7 +220,7 @@ describe('', function () {
await waitForElementToBeRemoved(() =>
screen.getByRole('button', {
- name: /Loading/i,
+ name: 'Loading',
})
)
@@ -235,7 +234,7 @@ describe('', function () {
const addAnotherEmailBtn = await screen.findByRole(
'button',
- { name: /add another email/i }
+ { name: 'Add another email' }
)
await fetchMock.callHistory.flush(true)
@@ -245,14 +244,14 @@ describe('', function () {
.post('/user/emails/secondary', 400)
fireEvent.click(addAnotherEmailBtn)
- const input = screen.getByLabelText(/email/i, { selector: 'input' })
+ const input = screen.getByRole('textbox', { name: 'Email' })
fireEvent.change(input, {
target: { value: userEmailData.email },
})
const submitBtn = screen.getByRole('button', {
- name: /add new email/i,
+ name: 'Add new email',
})
expect(submitBtn.disabled).to.be.false
@@ -262,7 +261,7 @@ describe('', function () {
expect(submitBtn.disabled).to.be.true
await screen.findByText(
- /Invalid Request. Please correct the data and try again./i
+ 'Invalid Request. Please correct the data and try again.'
)
expect(submitBtn).to.not.be.null
expect(submitBtn.disabled).to.be.false
@@ -273,7 +272,7 @@ describe('', function () {
render()
const button = await screen.findByRole('button', {
- name: /add another email/i,
+ name: 'Add another email',
})
await fetchMock.callHistory.flush(true)
@@ -282,7 +281,7 @@ describe('', function () {
await userEvent.click(button)
- const input = screen.getByLabelText(/email/i, { selector: 'input' })
+ const input = screen.getByRole('textbox', { name: 'Email' })
fireEvent.change(input, {
target: { value: 'user@autocomplete.edu' },
})
@@ -297,7 +296,7 @@ describe('', function () {
render()
const button = await screen.findByRole('button', {
- name: /add another email/i,
+ name: 'Add another email',
})
await fetchMock.callHistory.flush(true)
@@ -306,14 +305,14 @@ describe('', function () {
await userEvent.click(button)
await userEvent.type(
- screen.getByLabelText(/email/i, { selector: 'input' }),
+ screen.getByRole('textbox', { name: 'Email' }),
userEmailData.email
)
- await userEvent.click(screen.getByRole('button', { name: /let us know/i }))
+ await userEvent.click(screen.getByRole('button', { name: 'Let us know' }))
const universityInput = screen.getByRole('combobox', {
- name: /university/i,
+ name: 'University',
})
expect(universityInput.disabled).to.be.true
@@ -330,7 +329,7 @@ describe('', function () {
// Select the country from dropdown
await userEvent.type(
screen.getByRole('combobox', {
- name: /country/i,
+ name: 'Country',
}),
country
)
@@ -347,10 +346,10 @@ describe('', function () {
await screen.findByText(userEmailData.affiliation.institution.name)
)
- const roleInput = screen.getByRole('combobox', { name: /role/i })
+ const roleInput = screen.getByRole('combobox', { name: 'Role' })
await userEvent.type(roleInput, userEmailData.affiliation.role!)
const departmentInput = screen.getByRole('combobox', {
- name: /department/i,
+ name: 'Department',
})
await userEvent.click(departmentInput)
await userEvent.click(screen.getByText(customDepartment))
@@ -370,7 +369,7 @@ describe('', function () {
await userEvent.click(
screen.getByRole('button', {
- name: /add new email/i,
+ name: 'Add new email',
})
)
@@ -402,7 +401,7 @@ describe('', function () {
render()
const button = await screen.findByRole('button', {
- name: /add another email/i,
+ name: 'Add another email',
})
await fetchMock.callHistory.flush(true)
@@ -422,14 +421,14 @@ describe('', function () {
// open "add new email" section and click "let us know" to open the Country/University form
await userEvent.click(button)
await userEvent.type(
- screen.getByLabelText(/email/i, { selector: 'input' }),
+ screen.getByRole('textbox', { name: 'Email' }),
userEmailData.email
)
- await userEvent.click(screen.getByRole('button', { name: /let us know/i }))
+ await userEvent.click(screen.getByRole('button', { name: 'Let us know' }))
// select a country
const countryInput = screen.getByRole('combobox', {
- name: /country/i,
+ name: 'Country',
})
await userEvent.click(countryInput)
await userEvent.type(countryInput, 'Germ')
@@ -437,7 +436,7 @@ describe('', function () {
// match several universities on initial typing
const universityInput = screen.getByRole('combobox', {
- name: /university/i,
+ name: 'University',
})
await userEvent.click(universityInput)
await userEvent.type(universityInput, 'bo')
@@ -458,7 +457,7 @@ describe('', function () {
render()
const button = await screen.findByRole('button', {
- name: /add another email/i,
+ name: 'Add another email',
})
await fetchMock.callHistory.flush(true)
@@ -467,14 +466,14 @@ describe('', function () {
await userEvent.click(button)
await userEvent.type(
- screen.getByLabelText(/email/i, { selector: 'input' }),
+ screen.getByRole('textbox', { name: 'Email' }),
userEmailData.email
)
- await userEvent.click(screen.getByRole('button', { name: /let us know/i }))
+ await userEvent.click(screen.getByRole('button', { name: 'Let us know' }))
const universityInput = screen.getByRole('combobox', {
- name: /university/i,
+ name: 'University',
})
expect(universityInput.disabled).to.be.true
@@ -491,7 +490,7 @@ describe('', function () {
// Select the country from dropdown
await userEvent.type(
screen.getByRole('combobox', {
- name: /country/i,
+ name: 'Country',
}),
country
)
@@ -505,10 +504,10 @@ describe('', function () {
// Enter the university manually
await userEvent.type(universityInput, newUniversity)
- const roleInput = screen.getByRole('combobox', { name: /role/i })
+ const roleInput = screen.getByRole('combobox', { name: 'Role' })
await userEvent.type(roleInput, userEmailData.affiliation.role!)
const departmentInput = screen.getByRole('combobox', {
- name: /department/i,
+ name: 'Department',
})
await userEvent.type(departmentInput, userEmailData.affiliation.department!)
@@ -530,7 +529,7 @@ describe('', function () {
await userEvent.click(
screen.getByRole('button', {
- name: /add new email/i,
+ name: 'Add new email',
})
)
@@ -573,7 +572,7 @@ describe('', function () {
render()
const button = await screen.findByRole('button', {
- name: /add another email/i,
+ name: 'Add another email',
})
await fetchMock.callHistory.flush(true)
@@ -586,7 +585,7 @@ describe('', function () {
await userEvent.click(button)
await userEvent.type(
- screen.getByLabelText(/email/i, { selector: 'input' }),
+ screen.getByRole('textbox', { name: 'Email' }),
`user@${hostnameFirstChar}`
)
@@ -596,37 +595,37 @@ describe('', function () {
expect(
screen.queryByRole('combobox', {
- name: /country/i,
+ name: 'Country',
})
).to.be.null
expect(
screen.queryByRole('combobox', {
- name: /university/i,
+ name: 'University',
})
).to.be.null
screen.getByRole('combobox', {
- name: /role/i,
+ name: 'Role',
})
screen.getByRole('combobox', {
- name: /department/i,
+ name: 'Department',
})
- await userEvent.click(screen.getByRole('button', { name: /change/i }))
+ await userEvent.click(screen.getByRole('button', { name: 'Change' }))
screen.getByRole('combobox', {
- name: /country/i,
+ name: 'Country',
})
screen.getByRole('combobox', {
- name: /university/i,
+ name: 'University',
})
expect(
screen.queryByRole('combobox', {
- name: /role/i,
+ name: 'Role',
})
).to.be.null
expect(
screen.queryByRole('combobox', {
- name: /department/i,
+ name: 'Department',
})
).to.be.null
})
@@ -646,7 +645,7 @@ describe('', function () {
render()
const button = await screen.findByRole('button', {
- name: /add another email/i,
+ name: 'Add another email',
})
await fetchMock.callHistory.flush(true)
@@ -659,7 +658,7 @@ describe('', function () {
await userEvent.click(button)
await userEvent.type(
- screen.getByLabelText(/email/i, { selector: 'input' }),
+ screen.getByRole('textbox', { name: 'Email' }),
`user@${hostnameFirstChar}`
)
@@ -686,16 +685,16 @@ describe('', function () {
.post('/user/emails/confirm-secondary', 200)
await userEvent.type(
- screen.getByRole('combobox', { name: /role/i }),
+ screen.getByRole('combobox', { name: 'Role' }),
userEmailData.affiliation.role!
)
await userEvent.type(
- screen.getByRole('combobox', { name: /department/i }),
+ screen.getByRole('combobox', { name: 'Department' }),
userEmailData.affiliation.department!
)
await userEvent.click(
screen.getByRole('button', {
- name: /add new email/i,
+ name: 'Add new email',
})
)
@@ -743,12 +742,12 @@ describe('', function () {
render()
const button = await screen.findByRole('button', {
- name: /add another email/i,
+ name: 'Add another email',
})
await userEvent.click(button)
- const input = screen.getByLabelText(/email/i, { selector: 'input' })
+ const input = screen.getByRole('textbox', { name: 'Email' })
fireEvent.change(input, {
target: { value: 'user@autocomplete.edu' },
})
@@ -786,12 +785,12 @@ describe('', function () {
render()
const button = await screen.findByRole('button', {
- name: /add another email/i,
+ name: 'Add another email',
})
await userEvent.click(button)
- const input = screen.getByLabelText(/email/i, { selector: 'input' })
+ const input = screen.getByRole('textbox', { name: 'Email' })
fireEvent.change(input, {
target: { value: 'user@autocomplete.edu' },
})
@@ -833,12 +832,12 @@ describe('', function () {
render()
const button = await screen.findByRole('button', {
- name: /add another email/i,
+ name: 'Add another email',
})
await userEvent.click(button)
- const input = screen.getByLabelText(/email/i, { selector: 'input' })
+ const input = screen.getByRole('textbox', { name: 'Email' })
fireEvent.change(input, {
target: { value: 'user@autocomplete.edu' },
})
diff --git a/services/web/test/frontend/features/settings/components/linking-section.test.tsx b/services/web/test/frontend/features/settings/components/linking-section.test.tsx
index 49970cc2f3..ecd0098014 100644
--- a/services/web/test/frontend/features/settings/components/linking-section.test.tsx
+++ b/services/web/test/frontend/features/settings/components/linking-section.test.tsx
@@ -61,17 +61,17 @@ describe('', function () {
screen.getByText('Google')
screen.getByText('Log in with Google.')
- screen.getByRole('button', { name: /unlink/i })
+ screen.getByRole('button', { name: 'Unlink Google' })
screen.getByText('ORCID')
screen.getByText(
/Securely establish your identity by linking your ORCID iD/
)
const helpLink = screen.getByRole('link', {
- name: /learn more about orcid/i,
+ name: 'Learn more about ORCID',
})
expect(helpLink.getAttribute('href')).to.equal('/blog/434')
- const linkButton = screen.getByRole('link', { name: /link orcid/i })
+ const linkButton = screen.getByRole('link', { name: 'Link ORCID' })
expect(linkButton.getAttribute('href')).to.equal('/auth/orcid?intent=link')
})
diff --git a/services/web/test/frontend/features/settings/components/linking/integration-widget.test.tsx b/services/web/test/frontend/features/settings/components/linking/integration-widget.test.tsx
index 1a623ba7b7..e8e60c80ba 100644
--- a/services/web/test/frontend/features/settings/components/linking/integration-widget.test.tsx
+++ b/services/web/test/frontend/features/settings/components/linking/integration-widget.test.tsx
@@ -33,7 +33,9 @@ describe('', function () {
})
it('should render an upgrade link and track clicks', function () {
- const upgradeLink = screen.getByRole('link', { name: /upgrade/i })
+ const upgradeLink = screen.getByRole('link', {
+ name: 'Integration Upgrade',
+ })
expect(upgradeLink.getAttribute('href')).to.equal(
'/user/subscription/plans'
)
@@ -52,7 +54,9 @@ describe('', function () {
it('should render a link to initiate integration linking', function () {
expect(
- screen.getByRole('link', { name: 'Link' }).getAttribute('href')
+ screen
+ .getByRole('link', { name: 'Link Integration' })
+ .getAttribute('href')
).to.equal('/link')
})
@@ -86,11 +90,13 @@ describe('', function () {
})
it('should display an `unlink` button', function () {
- screen.getByRole('button', { name: 'Unlink' })
+ screen.getByRole('button', { name: 'Unlink Integration' })
})
it('should open a modal with a link to confirm integration unlinking', function () {
- fireEvent.click(screen.getByRole('button', { name: 'Unlink' }))
+ fireEvent.click(
+ screen.getByRole('button', { name: 'Unlink Integration' })
+ )
const withinModal = within(screen.getByRole('dialog'))
withinModal.getByText('confirm unlink')
withinModal.getByText('you will be unlinked')
@@ -99,7 +105,9 @@ describe('', function () {
})
it('should cancel unlinking when clicking "cancel" in the confirmation modal', async function () {
- fireEvent.click(screen.getByRole('button', { name: 'Unlink' }))
+ fireEvent.click(
+ screen.getByRole('button', { name: 'Unlink Integration' })
+ )
screen.getByText('confirm unlink')
const cancelBtn = screen.getByRole('button', {
name: 'Cancel',
diff --git a/services/web/test/frontend/features/settings/components/linking/sso-widget.test.tsx b/services/web/test/frontend/features/settings/components/linking/sso-widget.test.tsx
index 68c3f35c27..b5d2fe5500 100644
--- a/services/web/test/frontend/features/settings/components/linking/sso-widget.test.tsx
+++ b/services/web/test/frontend/features/settings/components/linking/sso-widget.test.tsx
@@ -13,8 +13,8 @@ import { SSOLinkingWidget } from '../../../../../../frontend/js/features/setting
describe('', function () {
const defaultProps = {
providerId: 'integration_id',
- title: 'integration',
- description: 'integration description',
+ title: 'Integration',
+ description: 'Integration description',
helpPath: '/help/integration',
linkPath: '/integration/link',
onUnlink: () => Promise.resolve(),
@@ -22,10 +22,12 @@ describe('', function () {
it('should render', function () {
render()
- screen.getByText('integration')
- screen.getByText('integration description')
+ screen.getByText('Integration')
+ screen.getByText('Integration description')
expect(
- screen.getByRole('link', { name: /learn more/i }).getAttribute('href')
+ screen
+ .getByRole('link', { name: 'Learn more about Integration' })
+ .getAttribute('href')
).to.equal('/help/integration')
})
@@ -33,7 +35,9 @@ describe('', function () {
it('should render a link to `linkPath`', function () {
render()
expect(
- screen.getByRole('link', { name: /link/i }).getAttribute('href')
+ screen
+ .getByRole('link', { name: 'Link Integration' })
+ .getAttribute('href')
).to.equal('/integration/link?intent=link')
})
})
@@ -49,19 +53,23 @@ describe('', function () {
})
it('should display an `unlink` button', function () {
- screen.getByRole('button', { name: /unlink/i })
+ screen.getByRole('button', { name: 'Unlink Integration' })
})
it('should open a modal to confirm integration unlinking', function () {
- fireEvent.click(screen.getByRole('button', { name: /unlink/i }))
- screen.getByText('Unlink integration Account')
+ fireEvent.click(
+ screen.getByRole('button', { name: 'Unlink Integration' })
+ )
+ screen.getByText('Unlink Integration Account')
screen.getByText(
- 'Warning: When you unlink your account from integration you will not be able to sign in using integration anymore.'
+ 'Warning: When you unlink your account from Integration you will not be able to sign in using Integration anymore.'
)
})
it('should cancel unlinking when clicking cancel in the confirmation modal', async function () {
- fireEvent.click(screen.getByRole('button', { name: /unlink/i }))
+ fireEvent.click(
+ screen.getByRole('button', { name: 'Unlink Integration' })
+ )
const cancelBtn = screen.getByRole('button', {
name: 'Cancel',
hidden: false,
@@ -80,9 +88,11 @@ describe('', function () {
render(
)
- fireEvent.click(screen.getByRole('button', { name: /unlink/i }))
+ fireEvent.click(
+ screen.getByRole('button', { name: 'Unlink Integration' })
+ )
confirmBtn = within(screen.getByRole('dialog')).getByRole('button', {
- name: /unlink/i,
+ name: 'Unlink',
hidden: false,
})
})
@@ -114,11 +124,13 @@ describe('', function () {
render(
)
- fireEvent.click(screen.getByRole('button', { name: /unlink/i }))
+ fireEvent.click(
+ screen.getByRole('button', { name: 'Unlink Integration' })
+ )
const confirmBtn = within(screen.getByRole('dialog')).getByRole(
'button',
{
- name: /unlink/i,
+ name: 'Unlink',
hidden: false,
}
)
@@ -130,7 +142,7 @@ describe('', function () {
})
it('should display the unlink button ', async function () {
- await screen.findByRole('button', { name: /unlink/i })
+ await screen.findByRole('button', { name: 'Unlink Integration' })
})
})
})