diff --git a/services/web/test/frontend/components/pdf-preview/pdf-synctex-controls.spec.tsx b/services/web/test/frontend/components/pdf-preview/pdf-synctex-controls.spec.tsx
index 552357104b..d8fcacb7d0 100644
--- a/services/web/test/frontend/components/pdf-preview/pdf-synctex-controls.spec.tsx
+++ b/services/web/test/frontend/components/pdf-preview/pdf-synctex-controls.spec.tsx
@@ -4,7 +4,6 @@ import { cloneDeep } from 'lodash'
import { useDetachCompileContext as useCompileContext } from '../../../../frontend/js/shared/context/detach-compile-context'
import { useFileTreeData } from '../../../../frontend/js/shared/context/file-tree-data-context'
import { useEffect } from 'react'
-
import { EditorProviders } from '../../helpers/editor-providers'
import { mockScope } from './scope'
@@ -54,6 +53,15 @@ const WithPosition = ({ mockPosition }: { mockPosition: Position }) => {
return null
}
+// mock PDF scroll position update
+const setDetachedPosition = (mockPosition: Position) => {
+ sysendTestHelper.receiveMessage({
+ role: 'detacher',
+ event: 'state-position',
+ data: { value: mockPosition },
+ })
+}
+
const WithSelectedEntities = ({
mockSelectedEntities = [],
}: {
@@ -67,22 +75,64 @@ const WithSelectedEntities = ({
return null
}
+
+const interceptSyncCodeAsync = () => {
+ const output: { resolve: () => void } = {
+ resolve: () => {
+ // do nothing
+ },
+ }
+
+ cy.intercept('/project/*/sync/code?*', req => {
+ return new Promise(resolve => {
+ output.resolve = () => {
+ req.reply({
+ body: { pdf: cloneDeep(mockHighlights) },
+ })
+ resolve()
+ }
+ })
+ }).as('sync-code')
+
+ return output
+}
+
+const interceptSyncPdfAsync = () => {
+ const output: { resolve: () => void } = {
+ resolve: () => {
+ // do nothing
+ },
+ }
+
+ cy.intercept('/project/*/sync/pdf?*', req => {
+ return new Promise(resolve => {
+ output.resolve = () => {
+ req.reply({
+ body: { code: [{ file: 'main.tex', line: 100 }] },
+ delay: 1,
+ })
+ resolve()
+ }
+ })
+ }).as('sync-pdf')
+
+ return output
+}
+
+const interceptSyncPdf = () => {
+ cy.intercept('/project/*/sync/pdf?*', req => {
+ req.reply({
+ body: { code: [{ file: 'main.tex', line: 100 }] },
+ })
+ }).as('sync-pdf')
+}
+
describe('', function () {
beforeEach(function () {
window.metaAttributesCache = new Map()
cy.interceptCompile()
cy.interceptEvents()
-
- cy.intercept('/project/*/sync/code?*', {
- body: { pdf: cloneDeep(mockHighlights) },
- delay: 100,
- }).as('sync-code')
-
- cy.intercept('/project/*/sync/pdf?*', {
- body: { code: [{ file: 'main.tex', line: 100 }] },
- delay: 100,
- }).as('sync-pdf')
})
afterEach(function () {
@@ -111,21 +161,29 @@ describe('', function () {
)
})
- cy.get('body')
- .findByRole('button', { name: 'Go to code location in PDF' })
- .click()
- cy.get('body')
- .findByRole('button', { name: 'Go to code location in PDF' })
+ cy.wait('@compile').then(() => {
+ setDetachedPosition(mockPosition)
+ })
+
+ const syncCode = interceptSyncCodeAsync()
+
+ cy.findByRole('button', { name: 'Go to code location in PDF' }).click()
+ cy.findByRole('button', { name: 'Go to code location in PDF' })
.should('be.disabled')
+ .then(() => {
+ syncCode.resolve()
+ })
cy.wait('@sync-code')
- cy.get('body')
- .findByRole('button', { name: /^Go to PDF location in code/ })
- .click()
- cy.get('body')
- .findByRole('button', { name: /^Go to PDF location in code/ })
+ const syncPdf = interceptSyncPdfAsync()
+
+ cy.findByRole('button', { name: /^Go to PDF location in code/ }).click()
+ cy.findByRole('button', { name: /^Go to PDF location in code/ })
.should('be.disabled')
+ .then(() => {
+ syncPdf.resolve()
+ })
cy.wait('@sync-pdf')
})
@@ -143,9 +201,9 @@ describe('', function () {
)
- cy.get('body')
- .findByRole('button', { name: 'Go to code location in PDF' })
- .should('be.disabled')
+ cy.findByRole('button', { name: 'Go to code location in PDF' }).should(
+ 'be.disabled'
+ )
})
it('disables button when a file is selected', function () {
@@ -159,9 +217,9 @@ describe('', function () {
)
- cy.get('body')
- .findByRole('button', { name: 'Go to code location in PDF' })
- .should('be.disabled')
+ cy.findByRole('button', { name: 'Go to code location in PDF' }).should(
+ 'be.disabled'
+ )
})
describe('with detacher role', function () {
@@ -180,15 +238,14 @@ describe('', function () {
)
- cy.get('body')
- .findByRole('button', { name: /^Go to PDF location in code/ })
- .should('not.exist')
+ cy.findByRole('button', { name: /^Go to PDF location in code/ }).should(
+ 'not.exist'
+ )
cy.get('.synctex-control-icon').should('not.exist')
})
- // eslint-disable-next-line mocha/no-skipped-tests
- it.skip('send set highlights action', function () {
+ it('send set highlights action', function () {
const scope = mockScope()
cy.mount(
@@ -212,6 +269,8 @@ describe('', function () {
)
})
+ const syncing = interceptSyncCodeAsync()
+
cy.findByRole('button', {
name: 'Go to code location in PDF',
})
@@ -220,15 +279,19 @@ describe('', function () {
cy.findByRole('button', {
name: 'Go to code location in PDF',
- }).should('be.disabled')
+ })
+ .should('be.disabled')
+ .then(() => {
+ syncing.resolve()
+ })
- cy.wait('@sync-code').should(() => {
- const messages = sysendTestHelper
- .getAllBroacastMessages()
- .map((item: any) => item.args[1])
+ cy.wait('@sync-code')
- const message = messages.find(
- (message: any) => message.event === 'action-setHighlights'
+ cy.findByRole('button', {
+ name: 'Go to code location in PDF',
+ }).should(() => {
+ const message = sysendTestHelper.getMessageWithEvent(
+ 'action-setHighlights'
)
// synctex is called locally and the result are broadcast for the detached tab
@@ -242,6 +305,8 @@ describe('', function () {
})
it('reacts to sync to code action', function () {
+ interceptSyncPdf()
+
const scope = mockScope()
cy.mount(
@@ -250,9 +315,7 @@ describe('', function () {
- )
-
- cy.wait('@compile').then(() => {
+ ).then(() => {
sysendTestHelper.receiveMessage({
role: 'detached',
event: 'action-sync-to-code',
@@ -288,54 +351,60 @@ describe('', function () {
cy.get('.synctex-control-icon').should('not.exist')
})
- // eslint-disable-next-line mocha/no-skipped-tests
- it.skip('send go to code line action', function () {
+ it('send go to code line action', function () {
const scope = mockScope()
cy.mount(
-
)
- cy.wait('@compile')
+ cy.wait('@compile').then(() => {
+ sysendTestHelper.receiveMessage({
+ role: 'detacher',
+ event: `state-position`,
+ data: { value: mockPosition },
+ })
+ })
- cy.get('body').findByRole('button', {
+ cy.findByRole('button', {
name: /^Go to PDF location in code/,
})
- cy.get('body')
- .findByRole('button', { name: /^Go to PDF location in code/ })
+ cy.findByRole('button', { name: /^Go to PDF location in code/ })
.should('not.be.disabled')
.then(() => {
sysendTestHelper.resetHistory()
})
- cy.get('body')
- .findByRole('button', { name: /^Go to PDF location in code/ })
- .click()
+ cy.findByRole('button', { name: /^Go to PDF location in code/ }).click()
// the button is only disabled when the state is updated via sysend
- cy.get('body')
- .findByRole('button', { name: /^Go to PDF location in code/ })
- .should('not.be.disabled')
+ cy.findByRole('button', { name: /^Go to PDF location in code/ }).should(
+ 'not.be.disabled'
+ )
- cy.get('.synctex-spin-icon')
- .should('not.exist')
- .then(() => {
- expect(sysendTestHelper.getLastBroacastMessage()).to.deep.equal({
+ cy.get('.synctex-spin-icon').should('not.exist')
+
+ cy.findByRole('button', { name: /^Go to PDF location in code/ }).should(
+ () => {
+ const message = sysendTestHelper.getMessageWithEvent(
+ 'action-sync-to-code'
+ )
+
+ expect(message).to.deep.equal({
role: 'detached',
event: 'action-sync-to-code',
data: {
args: [mockPosition, 72],
},
})
- })
+ }
+ )
})
- // eslint-disable-next-line mocha/no-skipped-tests
- it.skip('update inflight state', function () {
+ it('update inflight state', function () {
const scope = mockScope()
cy.mount(
@@ -345,15 +414,15 @@ describe('', function () {
).then(() => {
sysendTestHelper.receiveMessage({
- role: 'detached',
- event: 'state-has-single-selected-doc',
- data: { value: true },
+ role: 'detacher',
+ event: `state-position`,
+ data: { value: mockPosition },
})
})
- cy.get('body')
- .findByRole('button', { name: /^Go to PDF location in code/ })
- .should('be.disabled')
+ cy.findByRole('button', { name: /^Go to PDF location in code/ }).should(
+ 'not.be.disabled'
+ )
cy.get('.synctex-spin-icon')
.should('not.exist')
@@ -365,9 +434,9 @@ describe('', function () {
})
})
- cy.get('body')
- .findByRole('button', { name: /^Go to PDF location in code/ })
- .should('be.disabled')
+ cy.findByRole('button', { name: /^Go to PDF location in code/ }).should(
+ 'be.disabled'
+ )
cy.get('.synctex-spin-icon')
.should('have.length', 1)
@@ -379,9 +448,9 @@ describe('', function () {
})
})
- cy.get('body')
- .findByRole('button', { name: /^Go to PDF location in code/ })
- .should('not.be.disabled')
+ cy.findByRole('button', { name: /^Go to PDF location in code/ }).should(
+ 'not.be.disabled'
+ )
cy.get('.synctex-spin-icon').should('not.exist')
})
diff --git a/services/web/test/frontend/helpers/sysend.js b/services/web/test/frontend/helpers/sysend.js
index 59a1997f96..cffa687f21 100644
--- a/services/web/test/frontend/helpers/sysend.js
+++ b/services/web/test/frontend/helpers/sysend.js
@@ -32,7 +32,13 @@ function getAllBroacastMessages() {
// this fakes receiving a message by calling the handler add to `on`. A bit
// funky, but works for now
function receiveMessage(message) {
- getLastDetachCall('on')?.args[1](message)
+ getLastDetachCall('on').args[1](message)
+}
+
+function getMessageWithEvent(eventName) {
+ return getAllBroacastMessages()
+ .map(item => item.args[1])
+ .find(item => item.event === eventName)
}
export default {
@@ -42,5 +48,6 @@ export default {
getLastDetachCall,
getLastBroacastMessage,
getAllBroacastMessages,
+ getMessageWithEvent,
receiveMessage,
}