Improve compile request mocking in Cypress tests (#12095)

GitOrigin-RevId: fdbc53148e5437e451dab4889232923c823d649e
This commit is contained in:
Alf Eaton 2023-03-06 12:50:17 +00:00 committed by Copybot
parent cff49bd9c1
commit 488c6ff919
9 changed files with 378 additions and 248 deletions

View file

@ -43,26 +43,111 @@ const outputFiles = () => {
]
}
export const interceptCompile = (prefix = 'compile') => {
cy.intercept('POST', '/project/*/compile*', {
body: {
status: 'success',
clsiServerId: 'foo',
compileGroup: 'priority',
pdfDownloadDomain: 'https://clsi.test-overleaf.com',
outputFiles: outputFiles(),
},
}).as(`${prefix}`)
export const interceptCompile = (prefix = 'compile', times = 1) => {
cy.intercept(
{ method: 'POST', url: '/project/*/compile*', times },
{
body: {
status: 'success',
clsiServerId: 'foo',
compileGroup: 'priority',
pdfDownloadDomain: 'https://clsi.test-overleaf.com',
outputFiles: outputFiles(),
},
}
).as(`${prefix}`)
cy.intercept('/build/*/output.pdf*', {
fixture: 'build/output.pdf,null',
}).as(`${prefix}-pdf`)
cy.intercept(
{ url: '/build/*/output.pdf*', times },
{ fixture: 'build/output.pdf,null' }
).as(`${prefix}-pdf`)
cy.intercept('/build/*/output.log*', {
fixture: 'build/output.log',
}).as(`${prefix}-log`)
cy.intercept(
{ url: '/build/*/output.log*', times },
{ fixture: 'build/output.log' }
).as(`${prefix}-log`)
cy.intercept('/build/*/output.blg*', {
fixture: 'build/output.blg',
}).as(`${prefix}-blg`)
cy.intercept(
{ url: '/build/*/output.blg*', times },
{ fixture: 'build/output.blg' }
).as(`${prefix}-blg`)
}
export const waitForCompile = ({ prefix = 'compile', pdf = false } = {}) => {
cy.wait(`@${prefix}`)
cy.wait(`@${prefix}-log`)
cy.wait(`@${prefix}-blg`)
if (pdf) {
cy.wait(`@${prefix}-pdf`)
}
return cy.wrap(null)
}
export const interceptDeferredCompile = (beforeResponse?: () => void) => {
let resolveDeferredCompile: (value?: unknown) => void
const promise = new Promise(resolve => {
resolveDeferredCompile = resolve
})
cy.intercept(
{ method: 'POST', url: '/project/*/compile*', times: 1 },
req => {
if (beforeResponse) {
beforeResponse()
}
// only reply once the Promise is resolved
promise.then(() => {
req.reply({
body: {
status: 'success',
clsiServerId: 'foo',
compileGroup: 'priority',
pdfDownloadDomain: 'https://clsi.test-overleaf.com',
outputFiles: [
{
path: 'output.pdf',
build: '123',
url: '/build/123/output.pdf',
type: 'pdf',
},
{
path: 'output.log',
build: '123',
url: '/build/123/output.log',
type: 'log',
},
{
path: 'output.blg',
build: '123',
url: '/build/123/output.blg',
type: 'log',
},
],
},
})
})
return promise
}
).as('compile')
cy.intercept(
{ url: '/build/*/output.pdf*', times: 1 },
{ fixture: 'build/output.pdf,null' }
).as(`compile-pdf`)
cy.intercept(
{ url: '/build/*/output.log*', times: 1 },
{ fixture: 'build/output.log' }
).as(`compile-log`)
cy.intercept(
{ url: '/build/*/output.blg*', times: 1 },
{ fixture: 'build/output.blg' }
).as(`compile-blg`)
// @ts-ignore
return cy.wrap(resolveDeferredCompile)
}

View file

@ -1,5 +1,9 @@
import '@testing-library/cypress/add-commands'
import { interceptCompile } from './compile'
import {
interceptCompile,
waitForCompile,
interceptDeferredCompile,
} from './compile'
import { interceptEvents } from './events'
import { interceptSpelling } from './spelling'
@ -12,6 +16,8 @@ declare global {
interceptCompile: typeof interceptCompile
interceptEvents: typeof interceptEvents
interceptSpelling: typeof interceptSpelling
waitForCompile: typeof waitForCompile
interceptDeferredCompile: typeof interceptDeferredCompile
index: () => Chainable<number>
}
}
@ -20,6 +26,8 @@ declare global {
Cypress.Commands.add('interceptCompile', interceptCompile)
Cypress.Commands.add('interceptEvents', interceptEvents)
Cypress.Commands.add('interceptSpelling', interceptSpelling)
Cypress.Commands.add('waitForCompile', waitForCompile)
Cypress.Commands.add('interceptDeferredCompile', interceptDeferredCompile)
Cypress.Commands.add('index', { prevSubject: true }, subject => {
return cy.wrap(subject).invoke('index')
})

View file

@ -5,7 +5,7 @@ import { testDetachChannel } from '../../helpers/detach-channel'
describe('<DetachCompileButtonWrapper />', function () {
beforeEach(function () {
cy.interceptCompile()
window.metaAttributesCache = new Map()
cy.interceptEvents()
})
@ -14,6 +14,8 @@ describe('<DetachCompileButtonWrapper />', function () {
})
it('detacher mode and not linked: does not show button ', function () {
cy.interceptCompile()
cy.window().then(win => {
win.metaAttributesCache = new Map([['ol-detachRole', 'detacher']])
})
@ -26,10 +28,14 @@ describe('<DetachCompileButtonWrapper />', function () {
</EditorProviders>
)
cy.waitForCompile()
cy.findByRole('button', { name: 'Recompile' }).should('not.exist')
})
it('detacher mode and linked: show button', function () {
cy.interceptCompile()
cy.window().then(win => {
win.metaAttributesCache = new Map([['ol-detachRole', 'detacher']])
})
@ -42,6 +48,8 @@ describe('<DetachCompileButtonWrapper />', function () {
</EditorProviders>
)
cy.waitForCompile()
cy.wrap(null).then(() => {
testDetachChannel.postMessage({
role: 'detached',
@ -53,6 +61,8 @@ describe('<DetachCompileButtonWrapper />', function () {
})
it('not detacher mode and linked: does not show button ', function () {
cy.interceptCompile()
cy.window().then(win => {
win.metaAttributesCache = new Map([['ol-detachRole', 'detached']])
})
@ -65,6 +75,8 @@ describe('<DetachCompileButtonWrapper />', function () {
</EditorProviders>
)
cy.waitForCompile()
cy.wrap(null).then(() => {
testDetachChannel.postMessage({
role: 'detacher',

View file

@ -6,11 +6,12 @@ import { unmountComponentAtNode } from 'react-dom'
describe('<PdfJSViewer/>', function () {
beforeEach(function () {
cy.interceptCompile()
cy.interceptEvents()
})
it('loads all PDF pages', function () {
cy.interceptCompile()
const scope = mockScope()
cy.mount(
@ -21,6 +22,8 @@ describe('<PdfJSViewer/>', function () {
</EditorProviders>
)
cy.waitForCompile()
cy.findByLabelText('Page 1')
cy.findByLabelText('Page 2')
cy.findByLabelText('Page 3')
@ -30,6 +33,8 @@ describe('<PdfJSViewer/>', function () {
})
it('renders pages in a "loading" state', function () {
cy.interceptCompile()
const scope = mockScope()
cy.mount(
@ -40,10 +45,14 @@ describe('<PdfJSViewer/>', function () {
</EditorProviders>
)
cy.waitForCompile()
cy.findByLabelText('Loading…')
})
it('can be unmounted while loading a document', function () {
cy.interceptCompile()
const scope = mockScope()
cy.mount(
@ -54,10 +63,14 @@ describe('<PdfJSViewer/>', function () {
</EditorProviders>
)
cy.waitForCompile()
cy.then(() => unmountComponentAtNode(getContainerEl()))
})
it('can be unmounted after loading a document', function () {
cy.interceptCompile()
const scope = mockScope()
cy.mount(
@ -68,6 +81,8 @@ describe('<PdfJSViewer/>', function () {
</EditorProviders>
)
cy.waitForCompile()
cy.findByLabelText('Page 1')
cy.then(() => unmountComponentAtNode(getContainerEl()))

View file

@ -11,9 +11,9 @@ describe('<PdfPreviewDetachedRoot/>', function () {
['ol-project_id', 'project1'],
['ol-detachRole', 'detached'],
['ol-projectName', 'Project Name'],
['ol-preventCompileOnLoad', true],
])
cy.interceptCompile()
cy.interceptEvents()
})
@ -22,6 +22,8 @@ describe('<PdfPreviewDetachedRoot/>', function () {
})
it('syncs compiling state', function () {
cy.interceptCompile()
cy.mount(<PdfPreviewDetachedRoot />)
cy.wrap(null).then(() => {
@ -51,6 +53,8 @@ describe('<PdfPreviewDetachedRoot/>', function () {
})
it('sends a clear cache request when the button is pressed', function () {
cy.interceptCompile()
cy.mount(<PdfPreviewDetachedRoot />)
cy.wrap(null).then(() => {

View file

@ -4,7 +4,8 @@ import { testDetachChannel } from '../../helpers/detach-channel'
describe('<PdfPreviewHybridToolbar/>', function () {
beforeEach(function () {
cy.interceptCompile()
window.metaAttributesCache = new Map()
window.metaAttributesCache.set('ol-preventCompileOnLoad', true)
cy.interceptEvents()
})

View file

@ -22,11 +22,18 @@ const Layout: FC<{ layout: string; view?: string }> = ({ layout, view }) => {
describe('<PdfPreview/>', function () {
beforeEach(function () {
cy.interceptCompile()
window.metaAttributesCache.set('ol-preventCompileOnLoad', true)
cy.interceptEvents()
})
afterEach(function () {
window.metaAttributesCache = new Map()
})
it('renders the PDF preview', function () {
window.metaAttributesCache.set('ol-preventCompileOnLoad', false)
cy.interceptCompile('compile')
const scope = mockScope()
cy.mount(
@ -38,13 +45,14 @@ describe('<PdfPreview/>', function () {
)
// wait for "compile on load" to finish
cy.findByRole('button', { name: 'Compiling…' })
cy.wait('@compile')
cy.waitForCompile({ pdf: true })
cy.findByRole('button', { name: 'Recompile' })
cy.wait('@compile-pdf')
})
it('runs a compile when the Recompile button is pressed', function () {
cy.interceptCompile()
const scope = mockScope()
cy.mount(
@ -55,28 +63,18 @@ describe('<PdfPreview/>', function () {
</EditorProviders>
)
// wait for "compile on load" to finish
cy.findByRole('button', { name: 'Compiling…' })
cy.wait('@compile')
cy.wait('@compile-pdf')
cy.interceptCompile('recompile')
// press the Recompile button => compile
cy.findByRole('button', { name: 'Recompile' }).click()
// wait for "recompile" to finish
// cy.findByRole('button', { name: 'Compiling…' })
cy.wait('@recompile-pdf')
cy.wait('@recompile-log')
cy.wait('@recompile-blg')
cy.findByRole('button', { name: 'Recompile' })
// wait for compile to finish
cy.waitForCompile({ pdf: true })
cy.contains('Your Paper')
})
it('runs a compile on `pdf:recompile` event', function () {
cy.interceptCompile()
const scope = mockScope()
cy.mount(
@ -87,111 +85,79 @@ describe('<PdfPreview/>', function () {
</EditorProviders>
)
// wait for "compile on load" to finish
cy.findByRole('button', { name: 'Compiling…' })
cy.wait('@compile')
cy.wait('@compile-pdf')
cy.interceptCompile('recompile')
cy.window().then(win => {
win.dispatchEvent(new CustomEvent('pdf:recompile'))
})
// wait for "recompile" to finish
// cy.findByRole('button', { name: 'Compiling…' })
cy.wait('@recompile')
// wait for compile to finish
cy.waitForCompile({ pdf: true })
cy.findByRole('button', { name: 'Recompile' })
cy.wait('@recompile-pdf')
cy.contains('Your Paper')
})
it('does not compile while compiling', function () {
let compileResolve: (value?: unknown) => void
let counter = 0
cy.interceptDeferredCompile(() => counter++).then(
resolveDeferredCompile => {
const scope = mockScope()
const promise = new Promise(resolve => {
compileResolve = resolve
})
cy.mount(
<EditorProviders scope={scope}>
<div className="pdf-viewer">
<PdfPreview />
</div>
</EditorProviders>
)
cy.intercept(
'POST',
'/project/project123/compile?auto_compile=true',
req => {
counter++
// start compiling
cy.findByRole('button', { name: 'Recompile' })
.click()
.then(() => {
cy.findByRole('button', { name: 'Compiling…' })
promise.then(() => {
req.reply({
body: {
status: 'success',
clsiServerId: 'foo',
compileGroup: 'priority',
pdfDownloadDomain: 'https://clsi.test-overleaf.com',
outputFiles: [
{
path: 'output.pdf',
build: '123',
url: '/build/123/output.pdf',
type: 'pdf',
},
{
path: 'output.log',
build: '123',
url: '/build/123/output.log',
type: 'log',
},
],
},
// trigger a recompile
cy.window().then(win => {
win.dispatchEvent(new CustomEvent('pdf:recompile'))
})
// finish the original compile
resolveDeferredCompile()
// wait for the original compile to finish
cy.waitForCompile({ pdf: true })
// NOTE: difficult to assert that a second request won't be sent, at some point
expect(counter).to.equal(1)
})
})
return promise
}
).as('compile')
const scope = mockScope()
cy.mount(
<EditorProviders scope={scope}>
<div className="pdf-viewer">
<PdfPreview />
</div>
</EditorProviders>
).then(() => {
cy.findByRole('button', { name: 'Compiling…' })
cy.window().then(win => {
win.dispatchEvent(new CustomEvent('pdf:recompile'))
})
compileResolve()
cy.findByRole('button', { name: 'Recompile' })
cy.contains('Your Paper').should(() => {
expect(counter).to.equal(1)
})
})
)
})
it('disables compile button while compile is running', function () {
const scope = mockScope()
cy.interceptDeferredCompile().then(resolveDeferredCompile => {
const scope = mockScope()
cy.mount(
<EditorProviders scope={scope}>
<div className="pdf-viewer">
<PdfPreview />
</div>
</EditorProviders>
)
cy.mount(
<EditorProviders scope={scope}>
<div className="pdf-viewer">
<PdfPreview />
</div>
</EditorProviders>
)
cy.findByRole('button', { name: 'Compiling…' }).should('be.disabled')
cy.findByRole('button', { name: 'Recompile' }).should('not.be.disabled')
cy.findByRole('button', { name: 'Recompile' }).click()
cy.findByRole('button', { name: 'Compiling…' })
.should('be.disabled')
.then(resolveDeferredCompile)
cy.waitForCompile()
cy.findByRole('button', { name: 'Recompile' }).should('not.be.disabled')
})
})
it('runs a compile on doc change if autocompile is enabled', function () {
cy.interceptCompile()
const scope = mockScope()
cy.mount(
@ -202,11 +168,6 @@ describe('<PdfPreview/>', function () {
</EditorProviders>
)
// wait for "compile on load" to finish
cy.findByRole('button', { name: 'Compiling…' })
cy.wait('@compile')
cy.findByRole('button', { name: 'Recompile' })
cy.window().then(win => {
cy.clock()
@ -216,16 +177,21 @@ describe('<PdfPreview/>', function () {
// fire a doc:changed event => compile
win.dispatchEvent(new CustomEvent('doc:changed'))
// wait enough time for the compile to start
cy.tick(6000) // > AUTO_COMPILE_DEBOUNCE
cy.clock().invoke('restore')
})
cy.findByRole('button', { name: 'Compiling…' })
// wait for compile to finish
cy.waitForCompile({ pdf: true })
cy.findByRole('button', { name: 'Recompile' })
})
it('does not run a compile on doc change if autocompile is disabled', function () {
cy.interceptCompile()
const scope = mockScope()
cy.mount(
@ -236,10 +202,6 @@ describe('<PdfPreview/>', function () {
</EditorProviders>
)
// wait for "compile on load" to finish
cy.findByRole('button', { name: 'Compiling…' })
cy.findByRole('button', { name: 'Recompile' })
cy.window().then(win => {
cy.clock()
@ -249,15 +211,19 @@ describe('<PdfPreview/>', function () {
// fire a doc:changed event => no compile
win.dispatchEvent(new CustomEvent('doc:changed'))
cy.tick(5000) // AUTO_COMPILE_DEBOUNCE
// wait enough time for the compile to start
cy.tick(6000) // AUTO_COMPILE_DEBOUNCE
cy.clock().invoke('restore')
})
// NOTE: difficult to assert that a request hasn't been sent
cy.findByRole('button', { name: 'Recompile' })
})
it('does not run a compile on doc change if autocompile is blocked by syntax check', function () {
cy.interceptCompile()
const scope = mockScope()
// enable linting in the editor
scope.settings.syntaxValidation = true
@ -272,10 +238,6 @@ describe('<PdfPreview/>', function () {
</EditorProviders>
)
// wait for "compile on load" to finish
cy.findByRole('button', { name: 'Compiling…' })
cy.findByRole('button', { name: 'Recompile' })
cy.window().then(win => {
cy.clock()
@ -288,16 +250,21 @@ describe('<PdfPreview/>', function () {
// fire a doc:changed event => no compile
win.dispatchEvent(new CustomEvent('doc:changed'))
cy.tick(5000) // AUTO_COMPILE_DEBOUNCE
// wait enough time for the compile to start
cy.tick(6000) // AUTO_COMPILE_DEBOUNCE
cy.clock().invoke('restore')
})
// NOTE: difficult to assert that a request hasn't been sent
cy.findByRole('button', { name: 'Recompile' })
cy.findByText('Code check failed')
})
it('does not run a compile on doc change if the PDF preview is not open', function () {
cy.interceptCompile()
const scope = mockScope()
cy.mount(
@ -309,11 +276,6 @@ describe('<PdfPreview/>', function () {
</EditorProviders>
)
// wait for "compile on load" to finish
cy.findByRole('button', { name: 'Compiling…' })
cy.wait('@compile')
cy.findByRole('button', { name: 'Recompile' })
cy.window().then(win => {
cy.clock()
@ -323,15 +285,17 @@ describe('<PdfPreview/>', function () {
// fire a doc:changed event => compile
win.dispatchEvent(new CustomEvent('doc:changed'))
// wait enough time for the compile to start
cy.tick(6000) // > AUTO_COMPILE_DEBOUNCE
cy.clock().invoke('restore')
})
// NOTE: difficult to assert that a request hasn't been sent
cy.findByRole('button', { name: 'Recompile' })
})
describe('displays error messages', function () {
describe('error messages', function () {
const compileErrorStatuses = {
'clear-cache':
'Sorry, something went wrong and your project could not be compiled. Please try again in a few moments.',
@ -355,7 +319,7 @@ describe('<PdfPreview/>', function () {
for (const [status, message] of Object.entries(compileErrorStatuses)) {
it(`displays error message for '${status}' status`, function () {
cy.intercept('POST', '/project/*/compile?*', {
cy.intercept('POST', '/project/*/compile*', {
body: {
status,
clsiServerId: 'foo',
@ -373,86 +337,86 @@ describe('<PdfPreview/>', function () {
</EditorProviders>
)
// wait for "compile on load" to finish
cy.findByRole('button', { name: 'Compiling…' })
cy.findByRole('button', { name: 'Recompile' })
cy.findByRole('button', { name: 'Recompile' }).click()
cy.wait('@compile')
cy.findByText(message)
})
}
})
it('displays expandable raw logs', function () {
const scope = mockScope()
it('displays expandable raw logs', function () {
cy.interceptCompile()
cy.mount(
<EditorProviders scope={scope}>
<div className="pdf-viewer">
<PdfPreview />
</div>
</EditorProviders>
)
const scope = mockScope()
// wait for "compile on load" to finish
cy.findByRole('button', { name: 'Compiling…' })
cy.findByRole('button', { name: 'Recompile' })
cy.mount(
<EditorProviders scope={scope}>
<div className="pdf-viewer">
<PdfPreview />
</div>
</EditorProviders>
)
cy.findByRole('button', { name: 'View logs' }).click()
cy.findByRole('button', { name: 'View PDF' })
cy.findByRole('button', { name: 'Recompile' }).click()
cy.waitForCompile({ pdf: true })
cy.findByRole('button', { name: 'Expand' }).click()
cy.findByRole('button', { name: 'Collapse' }).click()
})
cy.findByRole('button', { name: 'View logs' }).click()
cy.findByRole('button', { name: 'View PDF' })
it('displays error messages if there were validation problems', function () {
const validationProblems = {
sizeCheck: {
resources: [
{ path: 'foo/bar', kbSize: 76221 },
{ path: 'bar/baz', kbSize: 2342 },
],
},
mainFile: true,
conflictedPaths: [
{
path: 'foo/bar',
},
{
path: 'foo/baz',
},
cy.findByRole('button', { name: 'Expand' }).click()
cy.findByRole('button', { name: 'Collapse' }).click()
})
it('displays error messages if there were validation problems', function () {
const validationProblems = {
sizeCheck: {
resources: [
{ path: 'foo/bar', kbSize: 76221 },
{ path: 'bar/baz', kbSize: 2342 },
],
}
cy.intercept('POST', '/project/*/compile?*', {
body: {
status: 'validation-problems',
validationProblems,
clsiServerId: 'foo',
compileGroup: 'priority',
},
mainFile: true,
conflictedPaths: [
{
path: 'foo/bar',
},
}).as('compile')
{
path: 'foo/baz',
},
],
}
const scope = mockScope()
cy.intercept('POST', '/project/*/compile*', {
body: {
status: 'validation-problems',
validationProblems,
clsiServerId: 'foo',
compileGroup: 'priority',
},
}).as('compile')
cy.mount(
<EditorProviders scope={scope}>
<div className="pdf-viewer">
<PdfPreview />
</div>
</EditorProviders>
)
const scope = mockScope()
// wait for "compile on load" to finish
cy.findByRole('button', { name: 'Compiling…' })
cy.findByRole('button', { name: 'Recompile' })
cy.mount(
<EditorProviders scope={scope}>
<div className="pdf-viewer">
<PdfPreview />
</div>
</EditorProviders>
)
cy.wait('@compile')
cy.findByRole('button', { name: 'Recompile' }).click()
cy.wait('@compile')
cy.findByText('Project too large')
cy.findByText('Unknown main document')
cy.findByText('Conflicting Paths Found')
})
cy.findByText('Project too large')
cy.findByText('Unknown main document')
cy.findByText('Conflicting Paths Found')
})
describe('clear cache', function () {
it('sends a clear cache request when the button is pressed', function () {
cy.interceptCompile()
const scope = mockScope()
cy.mount(
@ -463,16 +427,15 @@ describe('<PdfPreview/>', function () {
</EditorProviders>
)
// wait for "compile on load" to finish
cy.findByRole('button', { name: 'Compiling…' })
cy.findByRole('button', { name: 'Recompile' })
cy.findByRole('button', { name: 'Recompile' }).click()
cy.waitForCompile({ pdf: true })
cy.findByRole('button', { name: 'View logs' }).click()
cy.findByRole('button', { name: 'Clear cached files' }).should(
'not.be.disabled'
)
cy.intercept('DELETE', 'project/*/output?*', {
cy.intercept('DELETE', '/project/*/output*', {
statusCode: 204,
delay: 100,
}).as('clear-cache')
@ -489,6 +452,8 @@ describe('<PdfPreview/>', function () {
})
it('handle "recompile from scratch"', function () {
cy.interceptCompile()
const scope = mockScope()
cy.mount(
@ -499,10 +464,13 @@ describe('<PdfPreview/>', function () {
</EditorProviders>
)
// wait for "compile on load" to finish
cy.findByRole('button', { name: 'Compiling…' })
cy.wait('@compile')
cy.findByRole('button', { name: 'Recompile' })
cy.findByRole('button', { name: 'Recompile' }).click()
cy.waitForCompile({ pdf: true })
cy.interceptCompile('recompile')
cy.intercept('DELETE', '/project/*/output*', {
statusCode: 204,
delay: 100,
}).as('clear-cache')
// show the logs UI
cy.findByRole('button', { name: 'View logs' }).click()
@ -511,13 +479,6 @@ describe('<PdfPreview/>', function () {
'not.be.disabled'
)
cy.interceptCompile()
cy.intercept('DELETE', 'project/*/output?*', {
statusCode: 204,
delay: 100,
}).as('clear-cache')
// TODO: open the menu?
cy.findByRole('menuitem', {
name: 'Recompile from scratch',
@ -530,14 +491,19 @@ describe('<PdfPreview/>', function () {
cy.findByRole('button', { name: 'Compiling…' })
cy.wait('@clear-cache')
// wait for recompile from scratch to finish
cy.waitForCompile({ pdf: true, prefix: 'recompile' })
cy.findByRole('button', { name: 'Recompile' })
cy.wait('@compile')
cy.wait('@compile-pdf')
})
})
describe('invalid URLs and broken PDFs', function () {
it('shows an error for an invalid URL', function () {
cy.intercept('/build/*/output.pdf?*', {
cy.interceptCompile()
cy.intercept('/build/*/output.pdf*', {
statusCode: 500,
body: {
message: 'something awful happened',
@ -555,6 +521,8 @@ describe('<PdfPreview/>', function () {
</EditorProviders>
)
cy.findByRole('button', { name: 'Recompile' }).click()
cy.waitForCompile()
cy.wait('@compile-pdf-error')
cy.contains('Something went wrong while rendering this PDF.')
@ -565,7 +533,9 @@ describe('<PdfPreview/>', function () {
})
it('shows an error for a corrupt PDF', function () {
cy.intercept('/build/*/output.pdf?*', {
cy.interceptCompile()
cy.intercept('/build/*/output.pdf*', {
fixture: 'build/output-corrupt.pdf,null',
}).as('compile-pdf-corrupt')
@ -579,6 +549,8 @@ describe('<PdfPreview/>', function () {
</EditorProviders>
)
cy.findByRole('button', { name: 'Recompile' }).click()
cy.waitForCompile()
cy.wait('@compile-pdf-corrupt')
cy.contains('Something went wrong while rendering this PDF.')
@ -591,9 +563,11 @@ describe('<PdfPreview/>', function () {
describe('human readable logs', function () {
it('shows human readable hint for undefined reference errors', function () {
cy.intercept('/build/*/output.log?*', {
cy.interceptCompile()
cy.intercept('/build/*/output.log*', {
fixture: 'build/output-human-readable.log',
}).as('log')
}).as('compile-log')
const scope = mockScope()
@ -605,7 +579,8 @@ describe('<PdfPreview/>', function () {
</EditorProviders>
)
cy.wait('@log')
cy.findByRole('button', { name: 'Recompile' }).click()
cy.waitForCompile()
cy.findByRole('button', { name: 'View logs' }).click()
cy.findByText(
@ -622,9 +597,10 @@ describe('<PdfPreview/>', function () {
})
it('does not show human readable hint when no undefined reference errors', function () {
cy.interceptCompile()
cy.intercept('/build/*/output.log?*', {
fixture: 'build/output-undefined-references.log',
}).as('log')
}).as('compile-log')
const scope = mockScope()
@ -636,7 +612,8 @@ describe('<PdfPreview/>', function () {
</EditorProviders>
)
cy.wait('@log')
cy.findByRole('button', { name: 'Recompile' }).click()
cy.waitForCompile()
cy.findByRole('button', { name: 'View logs' }).click()
cy.findByText(

View file

@ -77,7 +77,7 @@ const WithSelectedEntities = ({
}
const interceptSyncCodeAsync = () => {
const output: { resolve: () => void } = {
const deferred: { resolve: () => void } = {
resolve: () => {
// do nothing
},
@ -85,7 +85,7 @@ const interceptSyncCodeAsync = () => {
cy.intercept('/project/*/sync/code?*', req => {
return new Promise(resolve => {
output.resolve = () => {
deferred.resolve = () => {
req.reply({
body: { pdf: cloneDeep(mockHighlights) },
})
@ -94,7 +94,7 @@ const interceptSyncCodeAsync = () => {
})
}).as('sync-code')
return output
return deferred
}
const interceptSyncPdfAsync = () => {
@ -127,12 +127,10 @@ const interceptSyncPdf = () => {
}).as('sync-pdf')
}
// eslint-disable-next-line mocha/no-skipped-tests
describe.skip('<PdfSynctexControls/>', function () {
describe('<PdfSynctexControls/>', function () {
beforeEach(function () {
window.metaAttributesCache = new Map()
cy.interceptCompile()
window.metaAttributesCache.set('ol-preventCompileOnLoad', false)
cy.interceptEvents()
})
@ -141,6 +139,8 @@ describe.skip('<PdfSynctexControls/>', function () {
})
it('handles clicks on sync buttons', function () {
cy.interceptCompile()
const scope = mockScope()
cy.mount(
@ -151,6 +151,8 @@ describe.skip('<PdfSynctexControls/>', function () {
</EditorProviders>
)
cy.waitForCompile()
cy.get('.synctex-control-icon').should('have.length', 2)
// mock editor cursor position update
@ -162,7 +164,7 @@ describe.skip('<PdfSynctexControls/>', function () {
)
})
cy.wait('@compile').then(() => {
cy.wrap(null).then(() => {
setDetachedPosition(mockPosition)
})
@ -190,6 +192,8 @@ describe.skip('<PdfSynctexControls/>', function () {
})
it('disables button when multiple entities are selected', function () {
cy.interceptCompile()
const scope = mockScope()
cy.mount(
@ -202,12 +206,16 @@ describe.skip('<PdfSynctexControls/>', function () {
</EditorProviders>
)
cy.waitForCompile()
cy.findByRole('button', { name: 'Go to code location in PDF' }).should(
'be.disabled'
)
})
it('disables button when a file is selected', function () {
cy.interceptCompile()
const scope = mockScope()
cy.mount(
@ -218,6 +226,8 @@ describe.skip('<PdfSynctexControls/>', function () {
</EditorProviders>
)
cy.waitForCompile()
cy.findByRole('button', { name: 'Go to code location in PDF' }).should(
'be.disabled'
)
@ -229,6 +239,8 @@ describe.skip('<PdfSynctexControls/>', function () {
})
it('does not have go to PDF location button nor arrow icon', function () {
cy.interceptCompile()
const scope = mockScope()
cy.mount(
@ -239,6 +251,8 @@ describe.skip('<PdfSynctexControls/>', function () {
</EditorProviders>
)
cy.waitForCompile()
cy.findByRole('button', { name: /^Go to PDF location in code/ }).should(
'not.exist'
)
@ -247,6 +261,8 @@ describe.skip('<PdfSynctexControls/>', function () {
})
it('send set highlights action', function () {
cy.interceptCompile()
const scope = mockScope()
cy.mount(
@ -257,7 +273,7 @@ describe.skip('<PdfSynctexControls/>', function () {
</EditorProviders>
)
cy.wait('@compile')
cy.waitForCompile()
// mock editor cursor position update
cy.window().then(win => {
@ -302,6 +318,7 @@ describe.skip('<PdfSynctexControls/>', function () {
})
it('reacts to sync to code action', function () {
cy.interceptCompile()
interceptSyncPdf()
const scope = mockScope()
@ -312,7 +329,9 @@ describe.skip('<PdfSynctexControls/>', function () {
<WithSelectedEntities mockSelectedEntities={mockSelectedEntities} />
<PdfSynctexControls />
</EditorProviders>
).then(() => {
)
cy.waitForCompile().then(() => {
testDetachChannel.postMessage({
role: 'detached',
event: 'action-sync-to-code',
@ -332,6 +351,8 @@ describe.skip('<PdfSynctexControls/>', function () {
})
it('does not have go to code location button nor arrow icon', function () {
cy.interceptCompile()
const scope = mockScope()
cy.mount(
@ -341,6 +362,8 @@ describe.skip('<PdfSynctexControls/>', function () {
</EditorProviders>
)
cy.waitForCompile()
cy.findByRole('button', {
name: 'Go to code location in PDF',
}).should('not.exist')
@ -349,6 +372,8 @@ describe.skip('<PdfSynctexControls/>', function () {
})
it('send go to code line action', function () {
cy.interceptCompile()
const scope = mockScope()
cy.mount(
@ -357,7 +382,7 @@ describe.skip('<PdfSynctexControls/>', function () {
</EditorProviders>
)
cy.wait('@compile').then(() => {
cy.waitForCompile().then(() => {
testDetachChannel.postMessage({
role: 'detacher',
event: `state-position`,
@ -394,6 +419,8 @@ describe.skip('<PdfSynctexControls/>', function () {
})
it('update inflight state', function () {
cy.interceptCompile()
const scope = mockScope()
cy.mount(
@ -403,7 +430,7 @@ describe.skip('<PdfSynctexControls/>', function () {
</EditorProviders>
)
cy.wrap(null).then(() => {
cy.waitForCompile().then(() => {
testDetachChannel.postMessage({
role: 'detacher',
event: `state-position`,

View file

@ -34,12 +34,13 @@ const DetachLayoutTest = () => {
)
}
// eslint-disable-next-line mocha/no-skipped-tests
describe.skip('useDetachLayout', function () {
describe('useDetachLayout', function () {
beforeEach(function () {
window.metaAttributesCache = new Map()
window.metaAttributesCache.set('ol-preventCompileOnLoad', true)
cy.stub(window, 'open').as('openWindow')
cy.stub(window, 'close').as('closeWindow')
cy.interceptEvents()
})
afterEach(function () {