From 55829a3382a789b5525b39534dde20940921a5fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timoth=C3=A9e=20Alby?= Date: Mon, 10 Jan 2022 16:46:05 +0100 Subject: [PATCH] Merge pull request #6199 from overleaf/ta-pdf-detach-sync-to-entry Make syncToEntry a Detach Action GitOrigin-RevId: 92e92b770c4e2be5b001c083d2d490231a7fddfb --- .../components/pdf-logs-entries.js | 10 +- .../components/pdf-logs-entries.test.js | 114 ++++++++++++++++++ .../frontend/helpers/render-with-context.js | 24 ++-- 3 files changed, 134 insertions(+), 14 deletions(-) create mode 100644 services/web/test/frontend/features/pdf-preview/components/pdf-logs-entries.test.js diff --git a/services/web/frontend/js/features/pdf-preview/components/pdf-logs-entries.js b/services/web/frontend/js/features/pdf-preview/components/pdf-logs-entries.js index 1675243397..04a92e3532 100644 --- a/services/web/frontend/js/features/pdf-preview/components/pdf-logs-entries.js +++ b/services/web/frontend/js/features/pdf-preview/components/pdf-logs-entries.js @@ -4,6 +4,7 @@ import { useTranslation } from 'react-i18next' import PreviewLogsPaneMaxEntries from '../../preview/components/preview-logs-pane-max-entries' import PdfLogEntry from './pdf-log-entry' import { useIdeContext } from '../../../shared/context/ide-context' +import useDetachAction from '../../../shared/hooks/use-detach-action' const LOG_PREVIEW_LIMIT = 100 @@ -12,7 +13,7 @@ function PdfLogsEntries({ entries, hasErrors }) { const ide = useIdeContext() - const syncToEntry = useCallback( + const _syncToEntry = useCallback( entry => { const entity = ide.fileTreeManager.findEntityByPath(entry.file) @@ -26,6 +27,13 @@ function PdfLogsEntries({ entries, hasErrors }) { [ide] ) + const syncToEntry = useDetachAction( + 'sync-to-entry', + _syncToEntry, + 'detached', + 'detacher' + ) + const logEntries = entries.slice(0, LOG_PREVIEW_LIMIT) return ( diff --git a/services/web/test/frontend/features/pdf-preview/components/pdf-logs-entries.test.js b/services/web/test/frontend/features/pdf-preview/components/pdf-logs-entries.test.js new file mode 100644 index 0000000000..3995c994e5 --- /dev/null +++ b/services/web/test/frontend/features/pdf-preview/components/pdf-logs-entries.test.js @@ -0,0 +1,114 @@ +import PdfLogsEntries from '../../../../../frontend/js/features/pdf-preview/components/pdf-logs-entries' +import { renderWithEditorContext } from '../../../helpers/render-with-context' +import { screen, fireEvent } from '@testing-library/react' +import sysendTestHelper from '../../../helpers/sysend' +import { expect } from 'chai' +import sinon from 'sinon' + +describe('', function () { + const fileTreeManager = {} + const editorManager = {} + const logEntries = [ + { + file: 'main.tex', + line: 9, + column: 8, + level: 'error', + message: 'LaTeX Error', + content: 'See the LaTeX manual', + raw: '', + ruleId: 'latex_error', + humanReadableHint: '', + humanReadableHintComponent: <>, + key: '', + }, + ] + const fakeEntity = { type: 'doc' } + + beforeEach(function () { + fileTreeManager.findEntityByPath = sinon.stub().returns(fakeEntity) + editorManager.openDoc = sinon.stub() + }) + + afterEach(function () { + window.metaAttributesCache = new Map() + sysendTestHelper.resetHistory() + fileTreeManager.findEntityByPath.resetHistory() + }) + + it('opens doc on click', async function () { + renderWithEditorContext(, { + fileTreeManager, + editorManager, + }) + + const button = await screen.getByRole('button', { + name: 'Navigate to log position in source code: main.tex, 9', + }) + fireEvent.click(button) + sinon.assert.calledOnce(fileTreeManager.findEntityByPath) + sinon.assert.calledOnce(editorManager.openDoc) + sinon.assert.calledWith(editorManager.openDoc, fakeEntity, { + gotoLine: 9, + gotoColumn: 8, + }) + }) + + it('opens doc via detached action', async function () { + window.metaAttributesCache.set('ol-detachRole', 'detacher') + + renderWithEditorContext(, { + fileTreeManager, + editorManager, + }) + + sysendTestHelper.receiveMessage({ + role: 'detached', + event: 'action-sync-to-entry', + data: { + args: [ + { + file: 'main.tex', + line: 7, + column: 6, + }, + ], + }, + }) + + sinon.assert.calledOnce(fileTreeManager.findEntityByPath) + sinon.assert.calledOnce(editorManager.openDoc) + sinon.assert.calledWith(editorManager.openDoc, fakeEntity, { + gotoLine: 7, + gotoColumn: 6, + }) + }) + + it('sends open doc clicks via detached action', async function () { + window.metaAttributesCache.set('ol-detachRole', 'detached') + renderWithEditorContext(, { + fileTreeManager, + editorManager, + }) + + const button = await screen.getByRole('button', { + name: 'Navigate to log position in source code: main.tex, 9', + }) + fireEvent.click(button) + sinon.assert.notCalled(fileTreeManager.findEntityByPath) + sinon.assert.notCalled(editorManager.openDoc) + expect(sysendTestHelper.getLastBroacastMessage()).to.deep.equal({ + role: 'detached', + event: 'action-sync-to-entry', + data: { + args: [ + { + file: 'main.tex', + line: 9, + column: 8, + }, + ], + }, + }) + }) +}) diff --git a/services/web/test/frontend/helpers/render-with-context.js b/services/web/test/frontend/helpers/render-with-context.js index baab046538..9cd792532c 100644 --- a/services/web/test/frontend/helpers/render-with-context.js +++ b/services/web/test/frontend/helpers/render-with-context.js @@ -33,6 +33,17 @@ export function EditorProviders({ children, rootFolder, ui = { view: null, pdfLayout: 'flat', chatOpen: true }, + fileTreeManager = { + findEntityById: () => null, + findEntityByPath: () => null, + getEntityPath: () => '', + getRootDocDirname: () => '', + }, + editorManager = { + getCurrentDocId: () => 'foo', + getCurrentDocValue: () => {}, + openDoc: sinon.stub(), + }, }) { window.user = user || window.user window.gitBridgePublicBaseUrl = 'git.overleaf.test' @@ -66,19 +77,6 @@ export function EditorProviders({ ...scope, } - const fileTreeManager = { - findEntityById: () => null, - findEntityByPath: () => null, - getEntityPath: () => '', - getRootDocDirname: () => '', - } - - const editorManager = { - getCurrentDocId: () => 'foo', - getCurrentDocValue: () => {}, - openDoc: sinon.stub(), - } - const metadataManager = { metadata: { state: {