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.
|
||||
|
||||
Reference in New Issue
Block a user