mirror of
https://github.com/yu-i-i/overleaf-cep.git
synced 2026-05-23 09:09:36 +02:00
Improve Server Pro tests to use semantic selectors (#29790)
* Replace placeholders with labels * Add 'Close dialog' label to modal close button to distinguish from footer Close button * Add and translate heading on the not found page * Update textarea to have id matching label's for attribute Simplify test for template description textarea * Label PDF zoom level dropdown button * Improve test selectors to use semantic roles and accessible names GitOrigin-RevId: d215ddca30ddf844cfffbcf0e528a601b134d772
This commit is contained in:
@@ -25,13 +25,9 @@ describe('Accounts', function () {
|
||||
cy.get('@url').then(url => {
|
||||
cy.visit(`${url}`)
|
||||
cy.url().should('contain', '/user/activate')
|
||||
cy.findByText('Please set a password')
|
||||
cy.get('input[autocomplete="username"]').should(
|
||||
'have.attr',
|
||||
'value',
|
||||
email
|
||||
)
|
||||
cy.get('input[name="password"]')
|
||||
cy.findByRole('heading', { name: 'Please set a password' })
|
||||
cy.findByLabelText('Email').should('be.visible')
|
||||
cy.findByLabelText('Password').should('be.visible')
|
||||
cy.findByRole('button', { name: 'Activate' })
|
||||
})
|
||||
})
|
||||
|
||||
@@ -16,12 +16,10 @@ describe('admin panel', function () {
|
||||
const user = `${uuid()}@example.com`
|
||||
cy.findByLabelText('Emails to register new users').type(user + '{enter}')
|
||||
|
||||
cy.get('td')
|
||||
.contains(/\/user\/activate/)
|
||||
.then($td => {
|
||||
const url = $td.text().trim()
|
||||
activateUser(url)
|
||||
})
|
||||
cy.findByRole('cell', { name: /\/user\/activate/ }).then($td => {
|
||||
const url = $td.text().trim()
|
||||
activateUser(url)
|
||||
})
|
||||
})
|
||||
|
||||
it('via GUI and email', function () {
|
||||
@@ -29,17 +27,15 @@ describe('admin panel', function () {
|
||||
cy.findByLabelText('Emails to register new users').type(user + '{enter}')
|
||||
|
||||
let url: string
|
||||
cy.get('td')
|
||||
.contains(/\/user\/activate/)
|
||||
.then($td => {
|
||||
url = $td.text().trim()
|
||||
})
|
||||
cy.findByRole('cell', { name: /\/user\/activate/ }).then($td => {
|
||||
url = $td.text().trim()
|
||||
})
|
||||
|
||||
cy.then(() => {
|
||||
openEmail(
|
||||
'Activate your E2E test Account',
|
||||
(frame, { url }) => {
|
||||
frame.contains('Set password').then(el => {
|
||||
frame.contains('a', 'Set password').then(el => {
|
||||
expect(el.attr('href')!).to.equal(url)
|
||||
})
|
||||
},
|
||||
@@ -69,7 +65,7 @@ describe('admin panel', function () {
|
||||
openEmail(
|
||||
'Activate your E2E test Account',
|
||||
(frame, { url }) => {
|
||||
frame.contains('Set password').then(el => {
|
||||
frame.contains('a', 'Set password').then(el => {
|
||||
expect(el.attr('href')!).to.equal(url)
|
||||
})
|
||||
},
|
||||
@@ -145,10 +141,10 @@ describe('admin panel', function () {
|
||||
const menuitems = ['Manage Site', 'Manage Users', 'Project URL Lookup']
|
||||
menuitems.forEach(name => {
|
||||
cy.findByRole('menuitem', { name: 'Admin' }).click()
|
||||
cy.get('ul[role="menu"]')
|
||||
cy.findByRole('menu')
|
||||
.findAllByRole('menuitem')
|
||||
.should('have.length', menuitems.length)
|
||||
cy.get('ul[role="menu"]').findByRole('menuitem', { name }).click()
|
||||
cy.findByRole('menu').findByRole('menuitem', { name }).click()
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -206,7 +202,7 @@ describe('admin panel', function () {
|
||||
})
|
||||
|
||||
it('license usage tab', function () {
|
||||
cy.get('a').contains('License Usage').click()
|
||||
cy.findByRole('tab', { name: 'License Usage' }).click()
|
||||
cy.findByText(
|
||||
'An active user is one who has opened a project in this Server Pro instance in the last 12 months.'
|
||||
)
|
||||
@@ -214,7 +210,7 @@ describe('admin panel', function () {
|
||||
|
||||
describe('create users', function () {
|
||||
beforeEach(function () {
|
||||
cy.get('a').contains('New User').click()
|
||||
cy.findByRole('link', { name: 'New User' }).click()
|
||||
})
|
||||
registrationTests()
|
||||
})
|
||||
@@ -263,8 +259,8 @@ describe('admin panel', function () {
|
||||
|
||||
it('displays required sections', function () {
|
||||
// not exhaustive list, checks the tab content is rendered
|
||||
cy.findByText('Profile')
|
||||
cy.findByText('Editor Settings')
|
||||
cy.findByRole('heading', { name: 'Profile' })
|
||||
cy.findByRole('heading', { name: 'Editor Settings' })
|
||||
})
|
||||
|
||||
it('should not display SaaS-only sections', function () {
|
||||
@@ -290,9 +286,12 @@ describe('admin panel', function () {
|
||||
cy.findByRole('tablist').within(() => {
|
||||
cy.findByRole('tab', { name: 'Projects' }).click()
|
||||
})
|
||||
cy.get(`a[href="/admin/project/${testProjectId}"]`)
|
||||
.should('contain.text', 'Project information')
|
||||
.click()
|
||||
cy.findByRole('link', { name: testProjectName })
|
||||
.parent()
|
||||
.parent()
|
||||
.within(() => {
|
||||
cy.findByRole('link', { name: 'Project information' }).click()
|
||||
})
|
||||
|
||||
cy.findByRole('button', { name: 'Transfer Ownership' }).click()
|
||||
cy.findByRole('dialog').within(() => {
|
||||
@@ -319,10 +318,12 @@ describe('admin panel', function () {
|
||||
cy.findByRole('tablist').within(() => {
|
||||
cy.findByRole('tab', { name: 'Projects' }).click()
|
||||
})
|
||||
cy.get(`a[href="/admin/project/${testProjectId}"]`).should(
|
||||
'contain.text',
|
||||
'Project information'
|
||||
)
|
||||
cy.findByRole('link', { name: testProjectName })
|
||||
.parent()
|
||||
.parent()
|
||||
.within(() => {
|
||||
cy.findByRole('link', { name: 'Project information' }).click()
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
@@ -123,7 +123,9 @@ describe('Project creation and compilation', function () {
|
||||
cy.findByRole('button', { name: 'Share' }).click()
|
||||
})
|
||||
cy.findByRole('dialog').within(() => {
|
||||
cy.findByTestId('collaborator-email-input').type(COLLABORATOR + ',')
|
||||
cy.findByRole('combobox', { name: 'Add email address' }).type(
|
||||
COLLABORATOR + ','
|
||||
)
|
||||
cy.findByRole('button', { name: 'Invite' }).click()
|
||||
cy.findByText('Invite not yet accepted.')
|
||||
})
|
||||
|
||||
@@ -8,7 +8,9 @@ describe('Customization', function () {
|
||||
|
||||
it('should display the default right footer', function () {
|
||||
cy.visit('/')
|
||||
cy.get('footer').findByRole('link', { name: 'Fork on GitHub!' })
|
||||
cy.findByRole('contentinfo').findByRole('link', {
|
||||
name: 'Fork on GitHub!',
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -25,16 +27,18 @@ describe('Customization', function () {
|
||||
|
||||
it('should display custom name', function () {
|
||||
cy.visit('/')
|
||||
cy.get('nav').findByText('CUSTOM APP NAME')
|
||||
cy.findByRole('navigation', { name: 'Primary' }).findByText(
|
||||
'CUSTOM APP NAME'
|
||||
)
|
||||
})
|
||||
|
||||
it('should display custom left footer', function () {
|
||||
cy.visit('/')
|
||||
cy.get('footer').findByText('CUSTOM LEFT FOOTER')
|
||||
cy.findByRole('contentinfo').findByText('CUSTOM LEFT FOOTER')
|
||||
})
|
||||
it('should display custom right footer', function () {
|
||||
cy.visit('/')
|
||||
cy.get('footer').findByText('CUSTOM RIGHT FOOTER')
|
||||
cy.findByRole('contentinfo').findByText('CUSTOM RIGHT FOOTER')
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -24,7 +24,7 @@ describe('SAML', function () {
|
||||
|
||||
it('login', function () {
|
||||
cy.visit('/')
|
||||
cy.findByText('Log in with SAML Test Server').click()
|
||||
cy.findByRole('link', { name: 'Log in with SAML Test Server' }).click()
|
||||
|
||||
cy.origin(samlURL, () => {
|
||||
cy.get('input[name="username"]').type('sally')
|
||||
@@ -59,11 +59,11 @@ describe('LDAP', function () {
|
||||
|
||||
it('login', function () {
|
||||
cy.visit('/')
|
||||
cy.findByText('Log in LDAP')
|
||||
cy.findByRole('heading', { name: 'Log in LDAP' })
|
||||
|
||||
cy.get('input[name="login"]').type('fry')
|
||||
cy.get('input[name="password"]').type('fry')
|
||||
cy.get('button[type="submit"]').click()
|
||||
cy.findByLabelText('Username').type('fry')
|
||||
cy.findByLabelText('Password').type('fry')
|
||||
cy.findByRole('button', { name: 'Login' }).click()
|
||||
|
||||
cy.log('wait for login to finish')
|
||||
cy.url().should('contain', '/project')
|
||||
|
||||
@@ -72,11 +72,13 @@ describe('git-bridge', function () {
|
||||
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.findByRole('dialog').within(() => {
|
||||
cy.findByLabelText('Git authentication token')
|
||||
.contains(/olp_[a-zA-Z0-9]{16}/)
|
||||
.then(el => el.text())
|
||||
.as('newToken')
|
||||
cy.findByRole('button', { name: 'Close dialog' }).click()
|
||||
})
|
||||
cy.get('@newToken').then(token => {
|
||||
// There can be more than one token with the same prefix when retrying
|
||||
cy.findAllByText(
|
||||
@@ -258,7 +260,7 @@ describe('git-bridge', function () {
|
||||
const token = tokenEl.text()
|
||||
|
||||
// close Git modal
|
||||
cy.get('body').type('{esc}')
|
||||
cy.findByRole('button', { name: 'Close dialog' }).click()
|
||||
cy.findByTestId('git-bridge-modal').should('not.exist')
|
||||
// close the modal
|
||||
cy.get('body').type('{esc}')
|
||||
@@ -345,8 +347,16 @@ Hello world
|
||||
})
|
||||
.findByRole('button', { name: 'History' })
|
||||
.click()
|
||||
cy.findByText('(via Git)').should('not.exist')
|
||||
cy.findAllByText('Back to editor').last().click()
|
||||
cy.findByRole('complementary', {
|
||||
name: 'Project history and labels',
|
||||
}).within(() => {
|
||||
cy.findByText('(via Git)').should('not.exist')
|
||||
})
|
||||
cy.findByRole('navigation', {
|
||||
name: 'Project actions',
|
||||
})
|
||||
.findByRole('button', { name: 'Back to editor' })
|
||||
.click()
|
||||
cy.then(async () => {
|
||||
await git.push({
|
||||
...commonOptions,
|
||||
@@ -379,10 +389,10 @@ Hello world
|
||||
// Wait for history sync - trigger flush by toggling the UI
|
||||
cy.findByRole('navigation', {
|
||||
name: 'Project actions',
|
||||
}).within(() => {
|
||||
cy.findByRole('button', { name: 'History' }).click()
|
||||
cy.findByRole('button', { name: 'Back to editor' }).click()
|
||||
})
|
||||
.findByRole('button', { name: 'History' })
|
||||
.click()
|
||||
cy.findAllByText('Back to editor').last().click()
|
||||
|
||||
// check push in history
|
||||
cy.findByRole('navigation', {
|
||||
@@ -391,10 +401,18 @@ Hello world
|
||||
.findByRole('button', { name: 'History' })
|
||||
.click()
|
||||
cy.findByText(/Hello world/)
|
||||
cy.findByText('(via Git)').should('exist')
|
||||
cy.findByRole('complementary', {
|
||||
name: 'Project history and labels',
|
||||
}).within(() => {
|
||||
cy.findByText('(via Git)').should('exist')
|
||||
})
|
||||
|
||||
// Back to the editor
|
||||
cy.findAllByText('Back to editor').last().click()
|
||||
cy.findByRole('navigation', {
|
||||
name: 'Project actions',
|
||||
})
|
||||
.findByRole('button', { name: 'Back to editor' })
|
||||
.click()
|
||||
cy.findByText(/\\documentclass/)
|
||||
.parent()
|
||||
.parent()
|
||||
|
||||
@@ -39,14 +39,19 @@ describe('GracefulShutdown', function () {
|
||||
})
|
||||
|
||||
cy.log('add additional content')
|
||||
cy.findByText('\\maketitle').parent().click()
|
||||
cy.findByText('\\maketitle').parent().type(`\n\\section{{}New Section}`)
|
||||
cy.findByRole('region', { name: 'Editor' }).within(() => {
|
||||
cy.findByText('\\maketitle').parent().click()
|
||||
cy.findByText('\\maketitle').parent().type(`\n\\section{{}New Section}`)
|
||||
})
|
||||
recompile()
|
||||
|
||||
cy.log(
|
||||
'check flush from frontend to backend: should include new section in PDF'
|
||||
)
|
||||
cy.get('.pdf-viewer').should('contain.text', 'New Section')
|
||||
cy.findByRole('region', { name: 'PDF preview and logs' }).should(
|
||||
'contain.text',
|
||||
'New Section'
|
||||
)
|
||||
|
||||
cy.log('should have unflushed content in redis before shutdown')
|
||||
cy.then(async () => {
|
||||
@@ -62,8 +67,9 @@ describe('GracefulShutdown', function () {
|
||||
})
|
||||
|
||||
cy.log('wait for banner')
|
||||
cy.findByText(/performing maintenance/)
|
||||
cy.findByRole('dialog').findByText(/performing maintenance/)
|
||||
cy.log('wait for page reload')
|
||||
cy.findByRole('heading', { name: 'Maintenance' })
|
||||
cy.findByText(/is currently down for maintenance/)
|
||||
|
||||
cy.log('wait for shutdown to complete')
|
||||
@@ -85,13 +91,19 @@ describe('GracefulShutdown', function () {
|
||||
})
|
||||
|
||||
cy.log('check loading doc from mongo')
|
||||
cy.findByText('New Section')
|
||||
cy.findByRole('region', { name: 'Editor' }).findByText('New Section')
|
||||
|
||||
cy.log('check PDF')
|
||||
cy.get('.pdf-viewer').should('contain.text', 'New Section')
|
||||
|
||||
cy.findByRole('region', { name: 'PDF preview and logs' }).should(
|
||||
'contain.text',
|
||||
'New Section'
|
||||
)
|
||||
cy.log('check history')
|
||||
cy.findByText('History').click()
|
||||
cy.findByRole('navigation', {
|
||||
name: 'Project actions',
|
||||
})
|
||||
.findByRole('button', { name: 'History' })
|
||||
.click()
|
||||
cy.findByText(/\\section\{New Section}/)
|
||||
})
|
||||
})
|
||||
|
||||
@@ -26,22 +26,19 @@ describe('LearnWiki', function () {
|
||||
it('should add a documentation entry to the nav bar', function () {
|
||||
login(REGULAR_USER)
|
||||
cy.visit('/project')
|
||||
cy.findByRole('menuitem', { name: 'Documentation' }).should(
|
||||
'have.attr',
|
||||
'href',
|
||||
'/learn'
|
||||
)
|
||||
cy.findByRole('navigation', { name: 'Primary' }).findByRole('menuitem', {
|
||||
name: 'Documentation',
|
||||
})
|
||||
})
|
||||
|
||||
it('should display a tutorial link in the welcome page', function () {
|
||||
login(WITHOUT_PROJECTS_USER)
|
||||
cy.visit('/project')
|
||||
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')
|
||||
})
|
||||
cy.findByRole('link', { name: LABEL_LEARN_LATEX }).should(
|
||||
'have.attr',
|
||||
'href',
|
||||
'/learn/latex/Learn_LaTeX_in_30_minutes'
|
||||
)
|
||||
})
|
||||
|
||||
it('should render wiki page', function () {
|
||||
@@ -102,7 +99,11 @@ describe('LearnWiki', function () {
|
||||
it('should not add a documentation entry to the nav bar', function () {
|
||||
login(REGULAR_USER)
|
||||
cy.visit('/project')
|
||||
cy.findByText('Documentation').should('not.exist')
|
||||
cy.findByRole('navigation', { name: 'Primary' })
|
||||
.findByRole('menuitem', {
|
||||
name: 'Documentation',
|
||||
})
|
||||
.should('not.exist')
|
||||
})
|
||||
|
||||
it('should not render wiki page', function () {
|
||||
@@ -110,7 +111,7 @@ describe('LearnWiki', function () {
|
||||
cy.visit(COPYING_A_PROJECT_URL, {
|
||||
failOnStatusCode: false,
|
||||
})
|
||||
cy.findByText('Not found')
|
||||
cy.findByRole('heading', { name: 'Not found' })
|
||||
})
|
||||
|
||||
it('should not display a tutorial link in the welcome page', function () {
|
||||
|
||||
@@ -50,10 +50,12 @@ describe('Project Sharing', function () {
|
||||
// Add chat message
|
||||
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(
|
||||
'textarea[placeholder="Send a message to your collaborators…"]'
|
||||
).type('New Chat Message{enter}')
|
||||
cy.findByRole('complementary', { name: 'Chat' }).findByText(
|
||||
'Send your first message to your collaborators'
|
||||
)
|
||||
cy.findByLabelText('Send a message to your collaborators…').type(
|
||||
'New Chat Message{enter}'
|
||||
)
|
||||
|
||||
// Get link sharing links
|
||||
enableLinkSharing().then(
|
||||
@@ -130,7 +132,9 @@ describe('Project Sharing', function () {
|
||||
|
||||
function expectChatAccess() {
|
||||
cy.findByRole('button', { name: 'Chat' }).click()
|
||||
cy.findByText('New Chat Message')
|
||||
cy.findByRole('complementary', { name: 'Chat' }).findByText(
|
||||
'New Chat Message'
|
||||
)
|
||||
}
|
||||
|
||||
function expectHistoryAccess() {
|
||||
@@ -451,8 +455,14 @@ describe('Project Sharing', function () {
|
||||
it('should not display link sharing in the sharing modal', function () {
|
||||
login('user@example.com')
|
||||
openProjectByName(projectName)
|
||||
cy.findByText('Share').click()
|
||||
cy.findByText('Turn on link sharing').should('not.exist')
|
||||
cy.findByRole('navigation', {
|
||||
name: 'Project actions',
|
||||
})
|
||||
.findByRole('button', { name: 'Share' })
|
||||
.click()
|
||||
cy.findByRole('button', { name: 'Turn on link sharing' }).should(
|
||||
'not.exist'
|
||||
)
|
||||
})
|
||||
|
||||
it('should block new access to read-only link shared projects', function () {
|
||||
|
||||
@@ -38,7 +38,9 @@ describe('SandboxedCompiles', function () {
|
||||
|
||||
cy.log('Check which compiler version was used, expect 2023')
|
||||
cy.findByRole('button', { name: 'View logs' }).click()
|
||||
cy.findByText(/This is pdfTeX, Version .+ \(TeX Live 2023\) /)
|
||||
cy.findByLabelText('Raw logs from the LaTeX compiler').findByText(
|
||||
/This is pdfTeX, Version .+ \(TeX Live 2023\) /
|
||||
)
|
||||
|
||||
cy.log('Switch TeXLive version from 2023 to 2022')
|
||||
cy.findByRole('navigation', {
|
||||
@@ -59,7 +61,9 @@ describe('SandboxedCompiles', function () {
|
||||
|
||||
cy.log('Check which compiler version was used, expect 2022')
|
||||
cy.findByRole('button', { name: 'View logs' }).click()
|
||||
cy.findByText(/This is pdfTeX, Version .+ \(TeX Live 2022\) /)
|
||||
cy.findByLabelText('Raw logs from the LaTeX compiler').findByText(
|
||||
/This is pdfTeX, Version .+ \(TeX Live 2022\) /
|
||||
)
|
||||
})
|
||||
|
||||
checkSyncTeX()
|
||||
@@ -85,10 +89,10 @@ describe('SandboxedCompiles', function () {
|
||||
waitForCompileRateLimitCoolOff()
|
||||
cy.log('Start compile')
|
||||
// We need to start the compile manually because we do not want to wait for it to finish
|
||||
cy.findByText('Recompile').click()
|
||||
cy.findByRole('button', { name: 'Recompile' }).click()
|
||||
// Now stop the compile and kill the latex process
|
||||
stopCompile({ delay: 1000 })
|
||||
cy.get('.logs-pane')
|
||||
cy.findByRole('region', { name: 'PDF preview and logs' })
|
||||
.invoke('text')
|
||||
.should('match', /PDF Rendering Error|Compilation cancelled/)
|
||||
// Check that the previous compile is not running in the background by
|
||||
@@ -96,11 +100,9 @@ describe('SandboxedCompiles', function () {
|
||||
cy.findByText('\\def').parent().click()
|
||||
cy.findByText('\\def').parent().type('{home}disabled loop% ')
|
||||
recompile()
|
||||
cy.get('.pdf-viewer').should('contain.text', 'disabled loop')
|
||||
cy.get('.logs-pane').should(
|
||||
'not.contain.text',
|
||||
'A previous compile is still running'
|
||||
)
|
||||
cy.findByRole('region', { name: 'PDF preview and logs' })
|
||||
.should('contain.text', 'disabled loop')
|
||||
.should('not.contain.text', 'A previous compile is still running')
|
||||
})
|
||||
}
|
||||
|
||||
@@ -151,7 +153,10 @@ describe('SandboxedCompiles', function () {
|
||||
.findByText('Section B')
|
||||
.scrollIntoView()
|
||||
cy.get('@start').then((start: any) => {
|
||||
waitUntilScrollingFinished('.pdfjs-viewer-inner', start)
|
||||
waitUntilScrollingFinished(
|
||||
'[data-testid="pdfjs-viewer-inner"]',
|
||||
start
|
||||
)
|
||||
})
|
||||
// The sync button is swapped as the position in the PDF changes.
|
||||
// Cypress appears to click on a button that references a stale position.
|
||||
@@ -166,11 +171,13 @@ describe('SandboxedCompiles', function () {
|
||||
|
||||
it('should sync to pdf', function () {
|
||||
cy.log('zoom in')
|
||||
cy.findByRole('button', { name: /^\d+%$/ }).click() // TODO: ARIA label
|
||||
cy.findByRole('button', { name: 'PDF zoom level' }).click()
|
||||
cy.findByRole('menuitem', { name: '400%' }).click()
|
||||
cy.log('scroll to top')
|
||||
cy.findByTestId('pdfjs-viewer-inner').scrollTo('top')
|
||||
waitUntilScrollingFinished('.pdfjs-viewer-inner', -1).as('start')
|
||||
waitUntilScrollingFinished('[data-testid="pdfjs-viewer-inner"]', -1).as(
|
||||
'start'
|
||||
)
|
||||
|
||||
cy.log('navigate to title')
|
||||
cy.findByRole('textbox', { name: 'Source Editor editing' }).within(
|
||||
@@ -180,7 +187,10 @@ describe('SandboxedCompiles', function () {
|
||||
)
|
||||
cy.findByRole('button', { name: 'Go to code location in PDF' }).click()
|
||||
cy.get('@start').then((start: any) => {
|
||||
waitUntilScrollingFinished('.pdfjs-viewer-inner', start)
|
||||
waitUntilScrollingFinished(
|
||||
'[data-testid="pdfjs-viewer-inner"]',
|
||||
start
|
||||
)
|
||||
.as('title')
|
||||
.should('be.greaterThan', start)
|
||||
})
|
||||
@@ -191,7 +201,10 @@ describe('SandboxedCompiles', function () {
|
||||
)
|
||||
cy.findByRole('button', { name: 'Go to code location in PDF' }).click()
|
||||
cy.get('@title').then((title: any) => {
|
||||
waitUntilScrollingFinished('.pdfjs-viewer-inner', title)
|
||||
waitUntilScrollingFinished(
|
||||
'[data-testid="pdfjs-viewer-inner"]',
|
||||
title
|
||||
)
|
||||
.as('sectionA')
|
||||
.should('be.greaterThan', title)
|
||||
})
|
||||
@@ -202,7 +215,10 @@ describe('SandboxedCompiles', function () {
|
||||
)
|
||||
cy.findByRole('button', { name: 'Go to code location in PDF' }).click()
|
||||
cy.get('@sectionA').then((title: any) => {
|
||||
waitUntilScrollingFinished('.pdfjs-viewer-inner', title)
|
||||
waitUntilScrollingFinished(
|
||||
'[data-testid="pdfjs-viewer-inner"]',
|
||||
title
|
||||
)
|
||||
.as('sectionB')
|
||||
.should('be.greaterThan', title)
|
||||
})
|
||||
@@ -225,10 +241,9 @@ describe('SandboxedCompiles', function () {
|
||||
})
|
||||
recompile()
|
||||
recompile()
|
||||
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')
|
||||
cy.findByRole('region', { name: 'PDF preview and logs' })
|
||||
.findByText('Test Section')
|
||||
.should('not.contain.text', 'No PDF')
|
||||
})
|
||||
}
|
||||
|
||||
@@ -239,13 +254,14 @@ describe('SandboxedCompiles', function () {
|
||||
createProject('XeLaTeX')
|
||||
})
|
||||
cy.log('wait for compile')
|
||||
cy.findByRole('region', { name: 'PDF preview and logs' }).should(
|
||||
'contain.text',
|
||||
cy.findByRole('region', { name: 'PDF preview and logs' }).findByText(
|
||||
'XeLaTeX'
|
||||
)
|
||||
cy.log('Check which compiler was used, expect pdfLaTeX')
|
||||
cy.findByRole('button', { name: 'View logs' }).click()
|
||||
cy.findByText(/This is pdfTeX/)
|
||||
cy.findByLabelText('Raw logs from the LaTeX compiler').findByText(
|
||||
/This is pdfTeX/
|
||||
)
|
||||
|
||||
cy.log('Switch compiler to from pdfLaTeX to XeLaTeX')
|
||||
cy.findByRole('navigation', {
|
||||
@@ -265,7 +281,9 @@ describe('SandboxedCompiles', function () {
|
||||
|
||||
cy.log('Check which compiler was used, expect XeLaTeX')
|
||||
cy.findByRole('button', { name: 'View logs' }).click()
|
||||
cy.findByText(/This is XeTeX/)
|
||||
cy.findByLabelText('Raw logs from the LaTeX compiler').findByText(
|
||||
/This is XeTeX/
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -277,11 +295,15 @@ describe('SandboxedCompiles', function () {
|
||||
it('should not offer TexLive images and use default compiler', function () {
|
||||
createProject('sandboxed')
|
||||
cy.log('wait for compile')
|
||||
cy.get('.pdf-viewer').should('contain.text', 'sandboxed')
|
||||
cy.findByRole('region', { name: 'PDF preview and logs' }).findByText(
|
||||
'sandboxed'
|
||||
)
|
||||
|
||||
cy.log('Check which compiler version was used, expect 2025')
|
||||
cy.get('[aria-label="View logs"]').click()
|
||||
cy.findByText(/This is pdfTeX, Version .+ \(TeX Live 2025\) /)
|
||||
cy.findByRole('button', { name: 'View logs' }).click()
|
||||
cy.findByLabelText('Raw logs from the LaTeX compiler').findByText(
|
||||
/This is pdfTeX, Version .+ \(TeX Live 2025\) /
|
||||
)
|
||||
|
||||
cy.log('Check that there is no TeX Live version toggle')
|
||||
cy.findByRole('navigation', {
|
||||
@@ -289,8 +311,10 @@ describe('SandboxedCompiles', function () {
|
||||
})
|
||||
.findByRole('button', { name: 'Menu' })
|
||||
.click()
|
||||
cy.findByText('Word Count') // wait for lazy loading
|
||||
cy.findByText(LABEL_TEX_LIVE_VERSION).should('not.exist')
|
||||
cy.findByTestId('left-menu').within(() => {
|
||||
cy.findByRole('button', { name: 'Word Count' }) // wait for lazy loading
|
||||
cy.findByText(LABEL_TEX_LIVE_VERSION).should('not.exist')
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -43,9 +43,7 @@ describe('Templates', function () {
|
||||
it('should show templates link on welcome page', function () {
|
||||
login(WITHOUT_PROJECTS_USER)
|
||||
cy.visit('/')
|
||||
cy.findByRole('link', { name: LABEL_BROWSE_TEMPLATES })
|
||||
.should('have.attr', 'href', '/templates')
|
||||
.click()
|
||||
cy.findByRole('link', { name: LABEL_BROWSE_TEMPLATES }).click()
|
||||
cy.url().should('match', /\/templates$/)
|
||||
})
|
||||
|
||||
@@ -62,32 +60,31 @@ describe('Templates', function () {
|
||||
})
|
||||
.findByRole('button', { name: 'Menu' })
|
||||
.click()
|
||||
cy.findByText('Manage Template').click()
|
||||
cy.findByRole('button', { name: 'Manage Template' }).click()
|
||||
|
||||
cy.findByText('Template Description').as('description').click()
|
||||
cy.get('@description').parent().get('textarea').type(description)
|
||||
cy.findByText('Publish').click()
|
||||
cy.findByText('Publishing…').parent().should('be.disabled')
|
||||
cy.findByText('Publish').should('not.exist')
|
||||
cy.findByText('Unpublish', { timeout: 60_000 })
|
||||
cy.findByText('Republish')
|
||||
cy.findByLabelText('Template Description').type(description)
|
||||
cy.findByRole('button', { name: 'Publish' }).click()
|
||||
cy.findByRole('button', { name: 'Publishing…' }).should('be.disabled')
|
||||
cy.findByRole('button', { name: 'Publish' }).should('not.exist')
|
||||
cy.findByRole('button', { name: 'Unpublish', timeout: 60_000 })
|
||||
cy.findByRole('button', { name: 'Republish' })
|
||||
|
||||
cy.findByText('View it in the template gallery').click()
|
||||
cy.findByRole('link', { name: 'View it in the template gallery' }).click()
|
||||
cy.url()
|
||||
.should('match', /\/templates\/[a-f0-9]{24}$/)
|
||||
.as('templateURL')
|
||||
|
||||
cy.findAllByText(name).first().should('exist')
|
||||
cy.findByRole('heading', { level: 2 }).findByText(name)
|
||||
cy.findByText(description)
|
||||
cy.findByText('Open as Template')
|
||||
cy.findByText('Unpublish')
|
||||
cy.findByText('Republish')
|
||||
cy.findByRole('link', { name: 'Open as Template' })
|
||||
cy.findByRole('button', { name: 'Unpublish' })
|
||||
cy.findByRole('button', { name: 'Republish' })
|
||||
cy.get('img')
|
||||
.should('have.attr', 'src')
|
||||
.and('match', /\/v\/0\//)
|
||||
cy.findByText('Republish').click()
|
||||
cy.findByText('Publishing…').parent().should('be.disabled')
|
||||
cy.findByText('Republish', { timeout: 60_000 })
|
||||
cy.findByRole('button', { name: 'Republish' }).click()
|
||||
cy.findByRole('button', { name: 'Publishing…' }).should('be.disabled')
|
||||
cy.findByRole('button', { name: 'Republish', timeout: 60_000 })
|
||||
cy.get('img', { timeout: 60_000 })
|
||||
.should('have.attr', 'src')
|
||||
.and('match', /\/v\/1\//)
|
||||
@@ -95,43 +92,38 @@ describe('Templates', function () {
|
||||
// custom tag
|
||||
const tagName = `${Date.now()}`
|
||||
cy.visit('/')
|
||||
cy.findByText(name)
|
||||
.parent()
|
||||
.parent()
|
||||
.within(() => cy.get('input[type="checkbox"]').first().check())
|
||||
cy.get('.project-list-sidebar-scroll').within(() => {
|
||||
cy.findAllByText('New tag').first().click()
|
||||
})
|
||||
cy.findByRole('checkbox', { name: `Select ${name}` }).check()
|
||||
cy.findByRole('navigation', { name: 'Project categories and tags' })
|
||||
.findByRole('button', { name: 'New tag' })
|
||||
.click()
|
||||
cy.focused().type(tagName)
|
||||
cy.findByText('Create').click()
|
||||
cy.get('.project-list-sidebar-scroll').within(() => {
|
||||
cy.findByText(tagName)
|
||||
.parent()
|
||||
.within(() => cy.get('.name').should('have.text', `${tagName} (1)`))
|
||||
})
|
||||
cy.findByRole('button', { name: 'Create' }).click()
|
||||
cy.findByRole('navigation', {
|
||||
name: 'Project categories and tags',
|
||||
}).should('contain', `${tagName} (1)`)
|
||||
|
||||
// Check listing
|
||||
cy.visit('/templates')
|
||||
cy.findByText(tagName)
|
||||
cy.findByRole('link', { name: tagName })
|
||||
cy.visit('/templates/all')
|
||||
cy.findByText(name)
|
||||
cy.findByRole('heading', { name })
|
||||
cy.visit(`/templates/${tagName}`)
|
||||
cy.findByText(name)
|
||||
cy.findByRole('heading', { name })
|
||||
|
||||
// Unpublish via template page
|
||||
cy.get('@templateURL').then(url => cy.visit(`${url}`))
|
||||
cy.findByText('Unpublish').click()
|
||||
cy.findByRole('button', { name: 'Unpublish' }).click()
|
||||
cy.url().should('match', /\/templates$/)
|
||||
cy.get('@templateURL').then(url =>
|
||||
cy.visit(`${url}`, {
|
||||
failOnStatusCode: false,
|
||||
})
|
||||
)
|
||||
cy.findByText('Not found')
|
||||
cy.findByRole('heading', { name: 'Not found' })
|
||||
cy.visit('/templates/all')
|
||||
cy.findByText(name).should('not.exist')
|
||||
cy.findByRole('heading', { name }).should('not.exist')
|
||||
cy.visit(`/templates/${tagName}`)
|
||||
cy.findByText(name).should('not.exist')
|
||||
cy.findByRole('heading', { name }).should('not.exist')
|
||||
|
||||
// Publish again
|
||||
cy.get('@templateProjectId').then(projectId =>
|
||||
@@ -142,12 +134,12 @@ describe('Templates', function () {
|
||||
})
|
||||
.findByRole('button', { name: 'Menu' })
|
||||
.click()
|
||||
cy.findByText('Manage Template').click()
|
||||
cy.findByText('Publish').click()
|
||||
cy.findByText('Unpublish', { timeout: 60_000 })
|
||||
cy.findByRole('button', { name: 'Manage Template' }).click()
|
||||
cy.findByRole('button', { name: 'Publish' }).click()
|
||||
cy.findByRole('button', { name: 'Unpublish', timeout: 60_000 })
|
||||
|
||||
// Should assign a new template id
|
||||
cy.findByText('View it in the template gallery').click()
|
||||
cy.findByRole('link', { name: 'View it in the template gallery' }).click()
|
||||
cy.url()
|
||||
.should('match', /\/templates\/[a-f0-9]{24}$/)
|
||||
.as('newTemplateURL')
|
||||
@@ -161,31 +153,32 @@ describe('Templates', function () {
|
||||
// Open project from template
|
||||
login(REGULAR_USER)
|
||||
cy.visit('/templates')
|
||||
cy.findByText(tagName).click()
|
||||
cy.findByText(name).click()
|
||||
cy.findByText('Open as Template').click()
|
||||
cy.url().should('match', /\/project\/[a-f0-9]{24}$/)
|
||||
cy.get('.project-name').should('contain.text', 'Your Paper') // might have (1) suffix
|
||||
cy.findByRole('link', { name: tagName }).click()
|
||||
cy.findByRole('link', { name }).click()
|
||||
cy.findByRole('link', { name: 'Open as Template' }).click()
|
||||
cy.findByRole('navigation', { name: 'Project actions' }).findByText(
|
||||
/Your Paper/i
|
||||
) // might have (1) suffix
|
||||
cy.findByRole('navigation', {
|
||||
name: 'Project actions',
|
||||
})
|
||||
.findByRole('button', { name: 'Menu' })
|
||||
.click()
|
||||
cy.findByText('Word Count') // wait for lazy loading
|
||||
cy.findByText('Manage Template').should('not.exist')
|
||||
cy.findByRole('button', { name: 'Word Count' }).click() // wait for lazy loading
|
||||
cy.findByRole('button', { name: 'Manage Template' }).should('not.exist')
|
||||
|
||||
// Check management as regular user
|
||||
cy.get('@newTemplateURL').then(url => cy.visit(`${url}`))
|
||||
cy.findByText('Open as Template')
|
||||
cy.findByText('Unpublish').should('not.exist')
|
||||
cy.findByText('Republish').should('not.exist')
|
||||
cy.findByRole('link', { name: 'Open as Template' })
|
||||
cy.findByRole('button', { name: 'Unpublish' }).should('not.exist')
|
||||
cy.findByRole('button', { name: 'Republish' }).should('not.exist')
|
||||
|
||||
// Check management as admin user
|
||||
login(ADMIN_USER)
|
||||
cy.get('@newTemplateURL').then(url => cy.visit(`${url}`))
|
||||
cy.findByText('Open as Template')
|
||||
cy.findByText('Unpublish')
|
||||
cy.findByText('Republish')
|
||||
cy.findByRole('link', { name: 'Open as Template' })
|
||||
cy.findByRole('button', { name: 'Unpublish' })
|
||||
cy.findByRole('button', { name: 'Republish' })
|
||||
cy.get('@templateProjectId').then(projectId =>
|
||||
cy.visit(`/project/${projectId}`)
|
||||
)
|
||||
@@ -194,8 +187,8 @@ describe('Templates', function () {
|
||||
})
|
||||
.findByRole('button', { name: 'Menu' })
|
||||
.click()
|
||||
cy.findByText('Manage Template').click()
|
||||
cy.findByText('Unpublish')
|
||||
cy.findByRole('button', { name: 'Manage Template' }).click()
|
||||
cy.findByRole('button', { name: 'Unpublish' })
|
||||
|
||||
// Back to templates user
|
||||
login(TEMPLATES_USER)
|
||||
@@ -209,19 +202,20 @@ describe('Templates', function () {
|
||||
})
|
||||
.findByRole('button', { name: 'Menu' })
|
||||
.click()
|
||||
cy.findByText('Manage Template').click()
|
||||
cy.findByText('Unpublish').click()
|
||||
cy.findByText('Publish')
|
||||
cy.findByRole('button', { name: 'Manage Template' }).click()
|
||||
cy.findByRole('button', { name: 'Unpublish' }).click()
|
||||
cy.findByRole('button', { name: 'Publish' })
|
||||
cy.visit('/templates/all')
|
||||
cy.findByText(name).should('not.exist')
|
||||
cy.findByRole('link', { name }).should('not.exist')
|
||||
|
||||
// check for template links, after creating the first project
|
||||
cy.visit('/')
|
||||
cy.findAllByRole('button', { name: NEW_PROJECT_BUTTON_MATCHER }).click()
|
||||
cy.findAllByText('All Templates')
|
||||
.first()
|
||||
.parent()
|
||||
.should('have.attr', 'href', '/templates/all')
|
||||
cy.findByRole('menuitem', { name: /All Templates/ }).should(
|
||||
'have.attr',
|
||||
'href',
|
||||
'/templates/all'
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
@@ -237,25 +231,27 @@ describe('Templates', function () {
|
||||
})
|
||||
.findByRole('button', { name: 'Menu' })
|
||||
.click()
|
||||
cy.findByText('Word Count') // wait for lazy loading
|
||||
cy.findByText('Manage Template').should('not.exist')
|
||||
cy.findByRole('button', { name: 'Word Count' }) // wait for lazy loading
|
||||
cy.findByRole('button', { name: 'Manage Template' }).should('not.exist')
|
||||
|
||||
cy.visit('/templates', { failOnStatusCode: false })
|
||||
cy.findByText('Not found')
|
||||
cy.findByRole('heading', { name: 'Not found' })
|
||||
cy.visit('/templates/all', { failOnStatusCode: false })
|
||||
cy.findByText('Not found')
|
||||
cy.findByRole('heading', { name: 'Not found' })
|
||||
|
||||
// check for template links, after creating the first project
|
||||
cy.visit('/')
|
||||
cy.findAllByRole('button', { name: NEW_PROJECT_BUTTON_MATCHER }).click()
|
||||
cy.findAllByText('All Templates').should('not.exist')
|
||||
cy.findByRole('menuitem', { name: /All Templates/ }).should('not.exist')
|
||||
})
|
||||
|
||||
it('should not show templates link on welcome page', function () {
|
||||
login(WITHOUT_PROJECTS_USER)
|
||||
cy.visit('/')
|
||||
cy.findByText(NEW_PROJECT_BUTTON_MATCHER) // wait for lazy loading
|
||||
cy.findByText(LABEL_BROWSE_TEMPLATES).should('not.exist')
|
||||
cy.findByRole('button', { name: NEW_PROJECT_BUTTON_MATCHER }) // wait for lazy loading
|
||||
cy.findByRole('link', { name: LABEL_BROWSE_TEMPLATES }).should(
|
||||
'not.exist'
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -49,7 +49,7 @@ describe('Upgrading', function () {
|
||||
})
|
||||
|
||||
cy.log('Wait for successful compile')
|
||||
cy.get('.pdf-viewer').should('contain.text', PROJECT_NAME)
|
||||
cy.findByLabelText(/Page.*1/i).findByText(PROJECT_NAME)
|
||||
|
||||
cy.log('Increment the doc version three times')
|
||||
for (let i = 0; i < 3; i++) {
|
||||
@@ -66,15 +66,15 @@ describe('Upgrading', function () {
|
||||
})
|
||||
.findByRole('button', { name: 'Menu' })
|
||||
.click()
|
||||
cy.findByText('Source').click()
|
||||
cy.get('.left-menu-modal-backdrop').click({ force: true })
|
||||
cy.findByRole('link', { name: 'Source' }).click()
|
||||
cy.get('body').type('{esc}')
|
||||
}
|
||||
|
||||
cy.log('Check compile and history')
|
||||
for (let i = 0; i < 3; i++) {
|
||||
cy.get('.pdf-viewer').should('contain.text', `Old Section ${i}`)
|
||||
cy.findByLabelText(/Page.*1/i).findByText(`Old Section ${i}`)
|
||||
}
|
||||
cy.findByText('History').click()
|
||||
cy.findByRole('button', { name: 'History' }).click()
|
||||
for (let i = 0; i < 3; i++) {
|
||||
cy.findByText(new RegExp(`\\\\section{Old Section ${i}}`))
|
||||
}
|
||||
@@ -119,7 +119,7 @@ describe('Upgrading', function () {
|
||||
|
||||
it('should list the old project', function () {
|
||||
cy.visit('/project')
|
||||
cy.findByText(PROJECT_NAME)
|
||||
cy.findByRole('link', { name: PROJECT_NAME })
|
||||
})
|
||||
|
||||
it('should open the old project', function () {
|
||||
@@ -135,8 +135,8 @@ describe('Upgrading', function () {
|
||||
})
|
||||
|
||||
cy.log('wait for successful compile')
|
||||
cy.get('.pdf-viewer').should('contain.text', PROJECT_NAME)
|
||||
cy.get('.pdf-viewer').should('contain.text', 'Old Section 2')
|
||||
cy.findByLabelText(/Page.*1/i).findByText(PROJECT_NAME)
|
||||
cy.findByLabelText(/Page.*1/i).findByText('Old Section 2')
|
||||
|
||||
cy.log('Add more content')
|
||||
const newSection = `New Section ${uuid()}`
|
||||
@@ -145,8 +145,8 @@ describe('Upgrading', function () {
|
||||
|
||||
cy.log('Check compile and history')
|
||||
recompile()
|
||||
cy.get('.pdf-viewer').should('contain.text', newSection)
|
||||
cy.findByText('History').click()
|
||||
cy.findByLabelText(/Page.*1/i).findByText(newSection)
|
||||
cy.findByRole('button', { name: 'History' }).click()
|
||||
cy.findByText(/\\section\{Old Section 2}/)
|
||||
cy.findByText(new RegExp(`\\\\section\\{${newSection}}`))
|
||||
})
|
||||
@@ -208,10 +208,10 @@ describe('Upgrading', function () {
|
||||
|
||||
cy.log('Trigger flush')
|
||||
recompile()
|
||||
cy.get('.pdf-viewer').should('contain.text', 'FiveOOne Section')
|
||||
cy.findByLabelText(/Page.*1/i).findByText('FiveOOne Section')
|
||||
|
||||
cy.log('Check for broken history, i.e. not synced with latest edit')
|
||||
cy.findByText('History').click()
|
||||
cy.findByRole('button', { name: 'History' }).click()
|
||||
cy.findByText(/\\section\{Old Section 2}/) // wait for lazy loading
|
||||
cy.findByText(/\\section\{FiveOOne Section}/).should('not.exist')
|
||||
})
|
||||
@@ -246,7 +246,7 @@ describe('Upgrading', function () {
|
||||
cy.log(
|
||||
'The edit that was made while the history was broken should be there now.'
|
||||
)
|
||||
cy.findByText('History').click()
|
||||
cy.findByRole('button', { name: 'History' }).click()
|
||||
cy.findByText(/\\section\{FiveOOne Section}/)
|
||||
|
||||
// TODO(das7pad): restore after https://github.com/overleaf/internal/issues/19588 is fixed.
|
||||
|
||||
@@ -5,7 +5,7 @@ block content
|
||||
.container
|
||||
.error-container
|
||||
.error-details
|
||||
p.error-status Not found
|
||||
h1.error-status #{translate("not_found")}
|
||||
p.error-description #{translate("cant_find_page")}
|
||||
p.error-actions
|
||||
a.error-btn(href='/') Home
|
||||
|
||||
@@ -280,6 +280,7 @@
|
||||
"clicking_delete_will_remove_sso_config_and_clear_saml_data": "",
|
||||
"clone_with_git": "",
|
||||
"close": "",
|
||||
"close_dialog": "",
|
||||
"clsi_maintenance": "",
|
||||
"clsi_unavailable": "",
|
||||
"code_check_failed": "",
|
||||
@@ -1272,6 +1273,7 @@
|
||||
"pdf_unavailable_for_download": "",
|
||||
"pdf_viewer": "",
|
||||
"pdf_viewer_error": "",
|
||||
"pdf_zoom_level": "",
|
||||
"pending_additional_licenses": "",
|
||||
"pending_addon_cancellation": "",
|
||||
"pending_invite": "",
|
||||
|
||||
@@ -75,6 +75,7 @@ function PdfZoomDropdown({
|
||||
id="pdf-zoom-dropdown"
|
||||
variant="link"
|
||||
className="pdf-toolbar-btn pdfjs-zoom-dropdown-button small"
|
||||
aria-label={t('pdf_zoom_level')}
|
||||
>
|
||||
{rawScaleToPercentage(rawScale)}
|
||||
</DropdownToggle>
|
||||
|
||||
@@ -8,6 +8,7 @@ import {
|
||||
} from 'react-bootstrap'
|
||||
import { ModalBodyProps } from 'react-bootstrap/ModalBody'
|
||||
import type { Options as FocusTrapOptions } from 'focus-trap'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
|
||||
type OLModalProps = ModalProps & {
|
||||
size?: 'sm' | 'lg'
|
||||
@@ -52,8 +53,13 @@ export function OLModalHeader({
|
||||
closeButton = true,
|
||||
...props
|
||||
}: OLModalHeaderProps) {
|
||||
const { t } = useTranslation()
|
||||
return (
|
||||
<Modal.Header closeButton={closeButton} {...props}>
|
||||
<Modal.Header
|
||||
closeButton={closeButton}
|
||||
closeLabel={t('close_dialog')}
|
||||
{...props}
|
||||
>
|
||||
{children}
|
||||
</Modal.Header>
|
||||
)
|
||||
|
||||
@@ -357,6 +357,7 @@
|
||||
"clicking_delete_will_remove_sso_config_and_clear_saml_data": "Clicking <0>Delete</0> will remove your SSO configuration and unlink all users. You can only do this when SSO is disabled in your group settings.",
|
||||
"clone_with_git": "Clone with Git",
|
||||
"close": "Close",
|
||||
"close_dialog": "Close dialog",
|
||||
"clsi_maintenance": "The compile servers are down for maintenance, and will be back shortly.",
|
||||
"clsi_unavailable": "Sorry, the compile server for your project was temporarily unavailable. Please try again in a few moments.",
|
||||
"cn": "Chinese (Simplified)",
|
||||
@@ -1506,6 +1507,7 @@
|
||||
"normally_x_price_per_month": "Normally __price__ per month",
|
||||
"normally_x_price_per_year": "Normally __price__ per year",
|
||||
"not_a_student": "Not a student?",
|
||||
"not_found": "Not found",
|
||||
"not_found_error_from_the_supplied_url": "The link to open this content on Overleaf pointed to a file that could not be found. If this keeps happening for links on a particular site, please report this to them.",
|
||||
"not_managed": "Not managed",
|
||||
"not_now": "Not now",
|
||||
@@ -1659,6 +1661,7 @@
|
||||
"pdf_unavailable_for_download": "PDF unavailable for download",
|
||||
"pdf_viewer": "PDF Viewer",
|
||||
"pdf_viewer_error": "There was a problem displaying the PDF for this project.",
|
||||
"pdf_zoom_level": "PDF zoom level",
|
||||
"pending": "Pending",
|
||||
"pending_additional_licenses": "Your subscription is changing to include <0>__pendingAdditionalLicenses__</0> additional license(s) for a total of <1>__pendingTotalLicenses__</1> licenses.",
|
||||
"pending_addon_cancellation": "Your subscription will change to remove the <strong>__addOnName__</strong> add-on at the end of the current billing period.",
|
||||
|
||||
@@ -163,7 +163,7 @@ describe('<EditorLeftMenu />', function () {
|
||||
cy.findByRole('heading', { name: 'Copy project' })
|
||||
|
||||
// try closing & re-opening the modal with different methods
|
||||
cy.findByRole('button', { name: 'Close' }).click()
|
||||
cy.findByRole('button', { name: 'Close dialog' }).click()
|
||||
cy.findByRole('button', { name: 'Copy project' }).click()
|
||||
cy.findByRole('button', { name: 'Cancel' }).click()
|
||||
cy.findByRole('button', { name: 'Copy project' }).click()
|
||||
|
||||
@@ -43,7 +43,7 @@ describe('<OLModal />', function () {
|
||||
cy.findByRole('button', { name: 'Open modal' }).click()
|
||||
cy.findByRole('dialog').should('be.visible')
|
||||
cy.findByLabelText(/enter text/i).should('be.visible')
|
||||
cy.get('body').type('{esc}')
|
||||
cy.findByRole('button', { name: 'Close dialog' }).click()
|
||||
// Modal should hide with single escape (escapeDeactivates: false means FocusTrap doesn't handle it)
|
||||
cy.findByRole('dialog').should('not.exist')
|
||||
cy.findByRole('button', { name: 'Open modal' }).should('be.visible')
|
||||
@@ -70,13 +70,13 @@ describe('<OLModal />', function () {
|
||||
cy.findByRole('button', { name: 'Open modal' }).click()
|
||||
cy.findByRole('dialog').should('be.visible')
|
||||
|
||||
cy.findByRole('button', { name: 'Close' }).should('be.focused')
|
||||
cy.findByRole('button', { name: 'Close dialog' }).should('be.focused')
|
||||
cy.focused().tab()
|
||||
cy.findByLabelText(/enter text/i).should('be.focused')
|
||||
cy.focused().tab()
|
||||
cy.findByRole('button', { name: 'Close the modal' }).should('be.focused')
|
||||
cy.focused().tab()
|
||||
cy.findByRole('button', { name: 'Close' }).should('be.focused')
|
||||
cy.findByRole('button', { name: 'Close dialog' }).should('be.focused')
|
||||
cy.focused().tab({ shift: true })
|
||||
cy.findByRole('button', { name: 'Close the modal' }).should('be.focused')
|
||||
})
|
||||
@@ -95,7 +95,7 @@ describe('<OLModal />', function () {
|
||||
cy.mount(<Modal />)
|
||||
cy.findByRole('button', { name: 'Open modal' }).click()
|
||||
cy.findByRole('dialog').should('be.visible')
|
||||
cy.findByRole('button', { name: 'Close' }).click()
|
||||
cy.findByRole('button', { name: 'Close dialog' }).click()
|
||||
cy.findByRole('dialog').should('not.exist')
|
||||
})
|
||||
|
||||
@@ -103,7 +103,7 @@ describe('<OLModal />', function () {
|
||||
cy.mount(<Modal backdrop="static" />)
|
||||
cy.findByRole('button', { name: 'Open modal' }).click()
|
||||
cy.findByRole('dialog').should('be.visible')
|
||||
cy.get('body').type('{esc}')
|
||||
cy.findByRole('button', { name: 'Close dialog' }).click()
|
||||
cy.findByRole('dialog').should('not.exist')
|
||||
})
|
||||
})
|
||||
|
||||
@@ -24,8 +24,8 @@ describe('<SettingsDictionary />', function () {
|
||||
within(modal).getByRole('heading', { name: 'Edit Dictionary' })
|
||||
within(modal).getByText('Your custom dictionary is empty.')
|
||||
|
||||
const [, closeButton] = within(modal).getAllByRole('button', {
|
||||
name: 'Close',
|
||||
const closeButton = within(modal).getByRole('button', {
|
||||
name: 'Close dialog',
|
||||
})
|
||||
fireEvent.click(closeButton)
|
||||
expect(screen.getByTestId('dictionary-modal')).to.not.be.null
|
||||
|
||||
@@ -62,7 +62,7 @@ describe('<NewProjectButton />', function () {
|
||||
|
||||
it('close the new project modal when clicking at the top right "x" button', function () {
|
||||
fireEvent.click(screen.getByRole('menuitem', { name: 'Blank project' }))
|
||||
fireEvent.click(screen.getByRole('button', { name: 'Close' }))
|
||||
fireEvent.click(screen.getByRole('button', { name: 'Close dialog' }))
|
||||
|
||||
expect(screen.queryByRole('dialog')).to.be.null
|
||||
})
|
||||
|
||||
@@ -26,8 +26,8 @@ describe('<DictionarySetting />', function () {
|
||||
within(modal).getByRole('heading', { name: 'Edit Dictionary' })
|
||||
within(modal).getByText('Your custom dictionary is empty.')
|
||||
|
||||
const [, closeButton] = within(modal).getAllByRole('button', {
|
||||
name: 'Close',
|
||||
const closeButton = within(modal).getByRole('button', {
|
||||
name: 'Close dialog',
|
||||
})
|
||||
fireEvent.click(closeButton)
|
||||
expect(screen.getByTestId('dictionary-modal')).to.not.be.null
|
||||
|
||||
@@ -35,7 +35,7 @@ describe('<LeaveSection />', function () {
|
||||
)
|
||||
|
||||
const cancelButton = screen.getByRole('button', {
|
||||
name: 'Close',
|
||||
name: 'Cancel',
|
||||
})
|
||||
|
||||
fireEvent.click(cancelButton)
|
||||
|
||||
@@ -141,15 +141,10 @@ describe('<ShareProjectModal/>', function () {
|
||||
createContextProps()
|
||||
)
|
||||
|
||||
const [headerCloseButton, footerCloseButton] = await screen.findAllByRole(
|
||||
'button',
|
||||
{ name: 'Close' }
|
||||
)
|
||||
const closeButton = screen.getByRole('button', { name: 'Close dialog' })
|
||||
await userEvent.click(closeButton)
|
||||
|
||||
await userEvent.click(headerCloseButton)
|
||||
await userEvent.click(footerCloseButton)
|
||||
|
||||
expect(handleHide.callCount).to.equal(2)
|
||||
expect(handleHide.callCount).to.equal(1)
|
||||
})
|
||||
|
||||
it('handles access level "private"', async function () {
|
||||
@@ -410,7 +405,7 @@ describe('<ShareProjectModal/>', function () {
|
||||
createContextProps({ publicAccessLevel: 'tokenBased', invites })
|
||||
)
|
||||
|
||||
const [, closeButton] = screen.getAllByRole('button', {
|
||||
const closeButton = screen.getByRole('button', {
|
||||
name: 'Close',
|
||||
})
|
||||
|
||||
@@ -446,7 +441,7 @@ describe('<ShareProjectModal/>', function () {
|
||||
createContextProps({ publicAccessLevel: 'tokenBased', invites })
|
||||
)
|
||||
|
||||
const [, closeButton] = screen.getAllByRole('button', {
|
||||
const closeButton = screen.getByRole('button', {
|
||||
name: 'Close',
|
||||
})
|
||||
|
||||
@@ -481,7 +476,7 @@ describe('<ShareProjectModal/>', function () {
|
||||
createContextProps({ publicAccessLevel: 'tokenBased', members })
|
||||
)
|
||||
|
||||
const [, closeButton] = screen.getAllByRole('button', {
|
||||
const closeButton = screen.getByRole('button', {
|
||||
name: 'Close',
|
||||
})
|
||||
|
||||
|
||||
Reference in New Issue
Block a user