[web] Move scopes permissionsLevel, permissions and hasLintingError to React context (#26607)

* Move `hasLintingError` from scope to react state

* Move `permissionsLevel` to IdeReactContext states

* Get `permissionsLevel` from `useIdeReactContext()`

* Set `permissionsLevel` in mocked `IdeReactProvider`

* Replace `permissions` scope by React state

* Fixup `permission` changes

* Remove redundant type

GitOrigin-RevId: 6203c61f9ac429789624196bf67e508310f4577f
This commit is contained in:
Antoine Clausse
2025-07-04 12:31:58 +02:00
committed by Copybot
parent 53168d7673
commit 779e346cb1
24 changed files with 93 additions and 75 deletions
@@ -4,7 +4,7 @@ import getMeta from '../../../../utils/meta'
import { useProjectSettingsContext } from '../../context/project-settings-context'
import SettingsMenuSelect from './settings-menu-select'
import type { Optgroup } from './settings-menu-select'
import { useEditorContext } from '@/shared/context/editor-context'
import { useIdeReactContext } from '@/features/ide-react/context/ide-react-context'
import { supportsWebAssembly } from '@/utils/wasm'
export default function SettingsSpellCheckLanguage() {
@@ -12,7 +12,7 @@ export default function SettingsSpellCheckLanguage() {
const { spellCheckLanguage, setSpellCheckLanguage } =
useProjectSettingsContext()
const { permissionsLevel } = useEditorContext()
const { permissionsLevel } = useIdeReactContext()
const optgroup: Optgroup = useMemo(() => {
const options = (getMeta('ol-languages') ?? [])
@@ -1,5 +1,5 @@
import { useCallback } from 'react'
import { useEditorContext } from '../../../shared/context/editor-context'
import { useIdeReactContext } from '@/features/ide-react/context/ide-react-context'
import useScopeValue from '../../../shared/hooks/use-scope-value'
import type { ProjectSettings } from '../utils/api'
import useSaveProjectSettings from './use-save-project-settings'
@@ -7,7 +7,7 @@ import useSaveProjectSettings from './use-save-project-settings'
export default function useRootDocId() {
const [rootDocId] =
useScopeValue<ProjectSettings['rootDocId']>('project.rootDocId')
const { permissionsLevel } = useEditorContext()
const { permissionsLevel } = useIdeReactContext()
const saveProjectSettings = useSaveProjectSettings()
const setRootDocIdFunc = useCallback(
@@ -1,6 +1,7 @@
import React, { useState, useCallback } from 'react'
import ToolbarHeader from './toolbar-header'
import { useEditorContext } from '../../../shared/context/editor-context'
import { useIdeReactContext } from '@/features/ide-react/context/ide-react-context'
import { useChatContext } from '../../chat/context/chat-context'
import { useLayoutContext } from '../../../shared/context/layout-context'
import { useProjectContext } from '../../../shared/context/project-context'
@@ -27,12 +28,10 @@ const EditorNavigationToolbarRoot = React.memo(
features: { trackChangesVisible },
} = useProjectContext()
const {
cobranding,
isRestrictedTokenMember,
renameProject,
permissionsLevel,
} = useEditorContext()
const { cobranding, isRestrictedTokenMember, renameProject } =
useEditorContext()
const { permissionsLevel } = useIdeReactContext()
const {
chatIsOpen,
@@ -1,5 +1,5 @@
import { useEditorManagerContext } from '@/features/ide-react/context/editor-manager-context'
import { useEditorContext } from '@/shared/context/editor-context'
import { useIdeReactContext } from '@/features/ide-react/context/ide-react-context'
import { FC, useCallback, useEffect, useRef, useState } from 'react'
import { PermissionsLevel } from '@/features/ide-react/types/permissions'
import { UnsavedDocsLockedAlert } from '@/features/ide-react/components/unsaved-docs/unsaved-docs-locked-alert'
@@ -12,7 +12,7 @@ const MAX_UNSAVED_SECONDS = 30 // lock the editor after this time if unsaved
export const UnsavedDocs: FC = () => {
const { openDocs, debugTimers } = useEditorManagerContext()
const { permissionsLevel, setPermissionsLevel } = useEditorContext()
const { permissionsLevel, setPermissionsLevel } = useIdeReactContext()
const [isLocked, setIsLocked] = useState(false)
const [unsavedDocs, setUnsavedDocs] = useState(new Map<string, number>())
const globalAlertsContainer = useGlobalAlertsContainer()
@@ -35,7 +35,6 @@ import { EditorType } from '@/features/ide-react/editor/types/editor-type'
import { DocId } from '../../../../../types/project-settings'
import { Update } from '@/features/history/services/types/update'
import { useDebugDiffTracker } from '../hooks/use-debug-diff-tracker'
import { useEditorContext } from '@/shared/context/editor-context'
import { convertFileRefToBinaryFile } from '@/features/ide-react/util/file-view'
import { useEditorOpenDocContext } from '@/features/ide-react/context/editor-open-doc-context'
@@ -89,8 +88,8 @@ export const EditorManagerProvider: FC<React.PropsWithChildren> = ({
}) => {
const { t } = useTranslation()
const { scopeStore } = useIdeContext()
const { reportError, eventEmitter, projectId } = useIdeReactContext()
const { setOutOfSync } = useEditorContext()
const { reportError, eventEmitter, projectId, setOutOfSync } =
useIdeReactContext()
const { socket, closeConnection, connectionState } = useConnectionContext()
const { view, setView, setOpenFile } = useLayoutContext()
const { showGenericMessageModal, genericModalVisible, showOutOfSyncModal } =
@@ -19,6 +19,7 @@ import { populateEditorScope } from '@/features/ide-react/scope-adapters/editor-
import { postJSON } from '@/infrastructure/fetch-json'
import { ReactScopeEventEmitter } from '@/features/ide-react/scope-event-emitter/react-scope-event-emitter'
import getMeta from '@/utils/meta'
import { type PermissionsLevel } from '@/features/ide-react/types/permissions'
const LOADED_AT = new Date()
@@ -31,6 +32,9 @@ type IdeReactContextValue = {
>
reportError: (error: any, meta?: Record<string, any>) => void
projectJoined: boolean
permissionsLevel: PermissionsLevel
setPermissionsLevel: (permissionsLevel: PermissionsLevel) => void
setOutOfSync: (value: boolean) => void
}
export const IdeReactContext = createContext<IdeReactContextValue | undefined>(
@@ -43,13 +47,6 @@ function populateIdeReactScope(store: ReactScopeValueStore) {
function populateProjectScope(store: ReactScopeValueStore) {
store.allowNonExistentPath('project', true)
store.set('permissionsLevel', 'readOnly')
store.set('permissions', {
read: true,
write: false,
admin: false,
comment: true,
})
}
function populatePdfScope(store: ReactScopeValueStore) {
@@ -78,6 +75,9 @@ export const IdeReactProvider: FC<React.PropsWithChildren> = ({ children }) => {
const projectId = getMeta('ol-project_id')
const [scopeStore] = useState(() => createReactScopeValueStore(projectId))
const [eventEmitter] = useState(createIdeEventEmitter)
const [permissionsLevel, setPermissionsLevel] =
useState<PermissionsLevel>('readOnly')
const [outOfSync, setOutOfSync] = useState(false)
const [scopeEventEmitter] = useState(
() => new ReactScopeEventEmitter(eventEmitter)
)
@@ -137,7 +137,7 @@ export const IdeReactProvider: FC<React.PropsWithChildren> = ({ children }) => {
}: JoinProjectPayload) {
const project = { ..._project, rootDocId }
scopeStore.set('project', project)
scopeStore.set('permissionsLevel', permissionsLevel)
setPermissionsLevel(permissionsLevel)
// Make watchers update immediately
scopeStore.flushUpdates()
eventEmitter.emit('project:joined', { project, permissionsLevel })
@@ -173,11 +173,22 @@ export const IdeReactProvider: FC<React.PropsWithChildren> = ({ children }) => {
eventEmitter,
startedFreeTrial,
setStartedFreeTrial,
permissionsLevel: outOfSync ? 'readOnly' : permissionsLevel,
setPermissionsLevel,
setOutOfSync,
projectId,
reportError,
projectJoined,
}),
[eventEmitter, projectId, projectJoined, reportError, startedFreeTrial]
[
eventEmitter,
outOfSync,
permissionsLevel,
projectId,
projectJoined,
reportError,
startedFreeTrial,
]
)
return (
@@ -13,7 +13,6 @@ import { useConnectionContext } from '@/features/ide-react/context/connection-co
import { useEditorOpenDocContext } from '@/features/ide-react/context/editor-open-doc-context'
import { getJSON, postJSON } from '@/infrastructure/fetch-json'
import { useOnlineUsersContext } from '@/features/ide-react/context/online-users-context'
import { useEditorContext } from '@/shared/context/editor-context'
import useSocketListener from '@/features/ide-react/hooks/use-socket-listener'
import useEventListener from '@/shared/hooks/use-event-listener'
import { useModalsContext } from '@/features/ide-react/context/modals-context'
@@ -49,10 +48,9 @@ export const MetadataContext = createContext<
export const MetadataProvider: FC<React.PropsWithChildren> = ({ children }) => {
const { t } = useTranslation()
const { eventEmitter, projectId } = useIdeReactContext()
const { eventEmitter, permissionsLevel, projectId } = useIdeReactContext()
const { socket } = useConnectionContext()
const { onlineUsersCount } = useOnlineUsersContext()
const { permissionsLevel } = useEditorContext()
const permissions = usePermissionsContext()
const { currentDocument } = useEditorOpenDocContext()
const { showGenericMessageModal } = useModalsContext()
@@ -1,12 +1,11 @@
import { createContext, useContext, useEffect } from 'react'
import { createContext, useContext, useEffect, useState } from 'react'
import { useConnectionContext } from '@/features/ide-react/context/connection-context'
import { useEditorContext } from '@/shared/context/editor-context'
import { useIdeReactContext } from '@/features/ide-react/context/ide-react-context'
import getMeta from '@/utils/meta'
import {
Permissions,
PermissionsLevel,
} from '@/features/ide-react/types/permissions'
import useScopeValue from '@/shared/hooks/use-scope-value'
import { DeepReadonly } from '../../../../../types/utils'
import useViewerPermissions from '@/shared/hooks/use-viewer-permissions'
import { useProjectContext } from '@/shared/context/project-context'
@@ -79,15 +78,24 @@ const noTrackChangesPermissionsMap: typeof permissionsMap = {
owner: permissionsMap.owner,
}
const defaultPermissions: Permissions = {
read: true,
write: true,
admin: false,
comment: true,
resolveOwnComments: false,
resolveAllComments: false,
trackedWrite: true,
labelVersion: false,
}
export const PermissionsProvider: React.FC<React.PropsWithChildren> = ({
children,
}) => {
const [permissions, setPermissions] =
useScopeValue<Readonly<Permissions>>('permissions')
useState<Permissions>(defaultPermissions)
const { connectionState } = useConnectionContext()
const { permissionsLevel } = useEditorContext() as {
permissionsLevel: PermissionsLevel
}
const { permissionsLevel } = useIdeReactContext()
const hasViewerPermissions = useViewerPermissions()
const anonymous = getMeta('ol-anonymous')
const project = useProjectContext()
@@ -12,14 +12,12 @@ import { debugConsole } from '@/utils/debugging'
import { useCallback } from 'react'
import { PublicAccessLevel } from '../../../../../types/public-access-level'
import { useLocation } from '@/shared/hooks/use-location'
import { useEditorContext } from '@/shared/context/editor-context'
function useSocketListeners() {
const { t } = useTranslation()
const { socket } = useConnectionContext()
const { projectId } = useIdeReactContext()
const { permissionsLevel, projectId } = useIdeReactContext()
const { showGenericMessageModal } = useModalsContext()
const { permissionsLevel } = useEditorContext()
const [, setPublicAccessLevel] = useScopeValue('project.publicAccesLevel')
const [, setProjectMembers] = useScopeValue('project.members')
const [, setProjectInvites] = useScopeValue('project.invites')
@@ -9,6 +9,7 @@ import { useProjectContext } from '@/shared/context/project-context'
import { useTranslation } from 'react-i18next'
import importOverleafModules from '../../../../../macros/import-overleaf-module.macro'
import { useEditorContext } from '@/shared/context/editor-context'
import { useIdeReactContext } from '@/features/ide-react/context/ide-react-context'
import { DownloadProjectPDF, DownloadProjectZip } from './download-project'
import { useCallback, useState } from 'react'
import OLDropdownMenuItem from '@/features/ui/components/ol/ol-dropdown-menu-item'
@@ -21,7 +22,8 @@ const SubmitProjectButton = publishModalModules?.import.NewPublishDropdownButton
export const ToolbarProjectTitle = () => {
const { cobranding } = useEditorContext()
const { t } = useTranslation()
const { permissionsLevel, renameProject } = useEditorContext()
const { renameProject } = useEditorContext()
const { permissionsLevel } = useIdeReactContext()
const { name } = useProjectContext()
const shouldDisplaySubmitButton =
(permissionsLevel === 'owner' || permissionsLevel === 'readAndWrite') &&
@@ -14,13 +14,15 @@ import { useEditorContext } from '@/shared/context/editor-context'
import importOverleafModules from '../../../../../macros/import-overleaf-module.macro'
import UpgradeButton from './upgrade-button'
import getMeta from '@/utils/meta'
import { useIdeReactContext } from '@/features/ide-react/context/ide-react-context'
const [publishModalModules] = importOverleafModules('publishModal')
const SubmitProjectButton = publishModalModules?.import.NewPublishToolbarButton
export const Toolbar = () => {
const { view, setView } = useLayoutContext()
const { cobranding, permissionsLevel } = useEditorContext()
const { cobranding } = useEditorContext()
const { permissionsLevel } = useIdeReactContext()
const shouldDisplaySubmitButton =
(permissionsLevel === 'owner' || permissionsLevel === 'readAndWrite') &&
SubmitProjectButton
@@ -17,6 +17,7 @@ import { usePermissionsContext } from '@/features/ide-react/context/permissions-
import usePersistedState from '@/shared/hooks/use-persisted-state'
import { sendMB } from '@/infrastructure/event-tracking'
import { useEditorContext } from '@/shared/context/editor-context'
import { useIdeReactContext } from '@/features/ide-react/context/ide-react-context'
import { useProjectContext } from '@/shared/context/project-context'
import UpgradeTrackChangesModal from './upgrade-track-changes-modal'
import { ReviewModePromo } from '@/features/review-panel-new/components/review-mode-promo'
@@ -33,7 +34,7 @@ const useCurrentMode = (): Mode => {
trackChanges?.onForEveryone ||
(user?.id && trackChanges?.onForMembers[user.id]) ||
(!user?.id && trackChanges?.onForGuests)
const { permissionsLevel } = useEditorContext()
const { permissionsLevel } = useIdeReactContext()
if (permissionsLevel === 'readOnly') {
return 'view'
@@ -52,7 +53,7 @@ function ReviewModeSwitcher() {
const { saveTrackChangesForCurrentUser, saveTrackChanges } =
useTrackChangesStateActionsContext()
const mode = useCurrentMode()
const { permissionsLevel } = useEditorContext()
const { permissionsLevel } = useIdeReactContext()
const { write, trackedWrite } = usePermissionsContext()
const project = useProjectContext()
const [showUpgradeModal, setShowUpgradeModal] = useState(false)
@@ -3,13 +3,15 @@ import EditorOverLimitModalContent from './editor-over-limit-modal-content'
import customLocalStorage from '@/infrastructure/local-storage'
import { useProjectContext } from '@/shared/context/project-context'
import { useEditorContext } from '@/shared/context/editor-context'
import { useIdeReactContext } from '@/features/ide-react/context/ide-react-context'
import { sendMB } from '@/infrastructure/event-tracking'
import OLModal from '@/features/ui/components/ol/ol-modal'
const EditorOverLimitModal = () => {
const [show, setShow] = useState(false)
const { isProjectOwner, permissionsLevel } = useEditorContext()
const { isProjectOwner } = useEditorContext()
const { permissionsLevel } = useIdeReactContext()
const { members, features, _id: projectId } = useProjectContext()
const handleHide = () => {
@@ -3,14 +3,15 @@ import ViewOnlyAccessModalContent from './view-only-access-modal-content'
import customLocalStorage from '@/infrastructure/local-storage'
import { useProjectContext } from '@/shared/context/project-context'
import { useEditorContext } from '@/shared/context/editor-context'
import { useIdeReactContext } from '@/features/ide-react/context/ide-react-context'
import { sendMB } from '@/infrastructure/event-tracking'
import OLModal from '@/features/ui/components/ol/ol-modal'
const ViewOnlyAccessModal = () => {
const [show, setShow] = useState(false)
const { isProjectOwner, isPendingEditor, permissionsLevel } =
useEditorContext()
const { isProjectOwner, isPendingEditor } = useEditorContext()
const { permissionsLevel } = useIdeReactContext()
const { members, features, _id: projectId } = useProjectContext()
const handleHide = () => {
@@ -58,11 +58,12 @@ import {
import { GotoLineOptions } from '@/features/ide-react/types/goto-line-options'
import { useOnlineUsersContext } from '@/features/ide-react/context/online-users-context'
import { useEditorOpenDocContext } from '@/features/ide-react/context/editor-open-doc-context'
import { usePermissionsContext } from '@/features/ide-react/context/permissions-context'
function useCodeMirrorScope(view: EditorView) {
const { fileTreeData } = useFileTreeData()
const [permissions] = useScopeValue<Permissions>('permissions')
const permissions: Permissions = usePermissionsContext()
// set up scope listeners
@@ -17,7 +17,6 @@ import { useDetachContext } from './detach-context'
import getMeta from '../../utils/meta'
import { useUserContext } from './user-context'
import { saveProjectSettings } from '@/features/editor-left-menu/utils/api'
import { PermissionsLevel } from '@/features/ide-react/types/permissions'
import { useModalsContext } from '@/features/ide-react/context/modals-context'
import { WritefullAPI } from './types/writefull-instance'
import { Cobranding } from '../../../../types/cobranding'
@@ -28,19 +27,16 @@ export const EditorContext = createContext<
cobranding?: Cobranding
hasPremiumCompile?: boolean
renameProject: (newName: string) => void
setPermissionsLevel: (permissionsLevel: PermissionsLevel) => void
showSymbolPalette?: boolean
toggleSymbolPalette?: () => void
insertSymbol?: (symbol: SymbolWithCharacter) => void
isProjectOwner: boolean
isRestrictedTokenMember?: boolean
isPendingEditor: boolean
permissionsLevel: PermissionsLevel
deactivateTutorial: (tutorial: string) => void
inactiveTutorials: string[]
currentPopup: string | null
setCurrentPopup: Dispatch<SetStateAction<string | null>>
setOutOfSync: (value: boolean) => void
hasPremiumSuggestion: boolean
setHasPremiumSuggestion: (value: boolean) => void
setPremiumSuggestionResetDate: (date: Date) => void
@@ -78,9 +74,6 @@ export const EditorProvider: FC<React.PropsWithChildren> = ({ children }) => {
}, [])
const [projectName, setProjectName] = useScopeValue('project.name')
const [permissionsLevel, setPermissionsLevel] =
useScopeValue('permissionsLevel')
const [outOfSync, setOutOfSync] = useState(false)
const [showSymbolPalette] = useScopeValue('editor.showSymbolPalette')
const [toggleSymbolPalette] = useScopeValue('editor.toggleSymbolPalette')
@@ -187,8 +180,6 @@ export const EditorProvider: FC<React.PropsWithChildren> = ({ children }) => {
cobranding,
hasPremiumCompile: features?.compileGroup === 'priority',
renameProject,
permissionsLevel: outOfSync ? 'readOnly' : permissionsLevel,
setPermissionsLevel,
isProjectOwner: owner?._id === userId,
isRestrictedTokenMember: getMeta('ol-isRestrictedTokenMember'),
isPendingEditor,
@@ -199,7 +190,6 @@ export const EditorProvider: FC<React.PropsWithChildren> = ({ children }) => {
deactivateTutorial,
currentPopup,
setCurrentPopup,
setOutOfSync,
hasPremiumSuggestion,
setHasPremiumSuggestion,
premiumSuggestionResetDate,
@@ -213,8 +203,6 @@ export const EditorProvider: FC<React.PropsWithChildren> = ({ children }) => {
owner,
userId,
renameProject,
permissionsLevel,
setPermissionsLevel,
isPendingEditor,
showSymbolPalette,
toggleSymbolPalette,
@@ -223,8 +211,6 @@ export const EditorProvider: FC<React.PropsWithChildren> = ({ children }) => {
deactivateTutorial,
currentPopup,
setCurrentPopup,
outOfSync,
setOutOfSync,
hasPremiumSuggestion,
setHasPremiumSuggestion,
premiumSuggestionResetDate,
@@ -238,6 +224,7 @@ export const EditorProvider: FC<React.PropsWithChildren> = ({ children }) => {
<EditorContext.Provider value={value}>{children}</EditorContext.Provider>
)
}
export function useEditorContext() {
const context = useContext(EditorContext)
@@ -28,6 +28,8 @@ import {
useSnapshotContext,
} from '@/features/ide-react/context/snapshot-context'
import importOverleafModules from '../../../macros/import-overleaf-module.macro'
import { useIdeReactContext } from '@/features/ide-react/context/ide-react-context'
const { buildFileTree, createFolder } =
(importOverleafModules('snapshotUtils')[0]
?.import as typeof StubSnapshotUtils) || StubSnapshotUtils
@@ -61,6 +63,7 @@ enum ACTION_TYPES {
MOVE = 'MOVE',
CREATE = 'CREATE',
}
/* eslint-enable no-unused-vars */
type Action =
@@ -181,7 +184,7 @@ export const FileTreeDataProvider: FC<React.PropsWithChildren> = ({
}) => {
const [project] = useScopeValue<Project>('project')
const { currentDocumentId, setOpenDocName } = useEditorOpenDocContext()
const [permissionsLevel] = useScopeValue('permissionsLevel')
const { permissionsLevel } = useIdeReactContext()
const { fileTreeFromHistory, snapshot, snapshotVersion } =
useSnapshotContext()
const fileTreeReadOnly =
@@ -10,7 +10,6 @@ import {
Dispatch,
SetStateAction,
} from 'react'
import useScopeValue from '../hooks/use-scope-value'
import usePersistedState from '../hooks/use-persisted-state'
import useAbortController from '../hooks/use-abort-controller'
import DocumentCompiler from '../../features/pdf-preview/util/compiler'
@@ -85,7 +84,7 @@ export type CompileContext = {
setAutoCompile: (value: boolean) => void
setDraft: (value: any) => void
setError: (value: any) => void
setHasLintingError: (value: any) => void // only for storybook
setHasLintingError: (value: boolean) => void // only for storybook
setHighlights: (value: any) => void
setPosition: Dispatch<SetStateAction<PdfScrollPosition>>
setShowCompileTimeWarning: (value: any) => void
@@ -273,7 +272,7 @@ export const LocalCompileProvider: FC<React.PropsWithChildren> = ({
)
// whether the editor linter found errors
const [hasLintingError, setHasLintingError] = useScopeValue('hasLintingError')
const [hasLintingError, setHasLintingError] = useState(false)
// the timestamp that a doc was last changed
const [changedAt, setChangedAt] = useState(0)
@@ -1,7 +1,7 @@
import { useEditorContext } from '../context/editor-context'
import { useIdeReactContext } from '@/features/ide-react/context/ide-react-context'
function useViewerPermissions() {
const { permissionsLevel } = useEditorContext()
const { permissionsLevel } = useIdeReactContext()
return permissionsLevel === 'readOnly'
}
@@ -75,7 +75,6 @@ const initialScope = {
},
open_doc_name: 'testfile.tex',
},
hasLintingError: false,
permissionsLevel: 'owner',
}
@@ -190,6 +189,9 @@ const IdeReactProvider: FC<React.PropsWithChildren> = ({ children }) => {
setStartedFreeTrial,
reportError: () => {},
projectJoined: true,
permissionsLevel: 'owner' as const,
setPermissionsLevel: () => {},
setOutOfSync: () => {},
}))
const [ideContextValue] = useState(() => {
@@ -12,7 +12,6 @@ type Scope = {
getSnapshot?: () => string
}
}
hasLintingError?: boolean
ui?: {
view?: 'editor' | 'history' | 'file' | 'pdf'
pdfLayout?: 'flat' | 'sideBySide' | 'split'
@@ -46,6 +45,5 @@ export const mockScope = (scope?: Scope) => ({
getSnapshot: () => 'some doc content',
},
},
hasLintingError: false,
...scope,
})
@@ -7,7 +7,8 @@ import {
IdeView,
useLayoutContext,
} from '../../../../frontend/js/shared/context/layout-context'
import { FC, useEffect } from 'react'
import { FC, PropsWithChildren, useEffect } from 'react'
import { useLocalCompileContext } from '@/shared/context/local-compile-context'
const storeAndFireEvent = (win: typeof window, key: string, value: unknown) => {
localStorage.setItem(key, value)
@@ -462,14 +463,20 @@ describe('<PdfPreview/>', function () {
const scope = mockScope()
// enable linting in the editor
const userSettings = { syntaxValidation: true }
// mock a linting error
scope.hasLintingError = true
const WithLintingErrors: FC<PropsWithChildren> = ({ children }) => {
const { setHasLintingError } = useLocalCompileContext()
useEffect(() => setHasLintingError(true), [setHasLintingError])
return children
}
cy.mount(
<EditorProviders scope={scope} userSettings={userSettings}>
<div className="pdf-viewer">
<PdfPreview />
</div>
<WithLintingErrors>
<div className="pdf-viewer">
<PdfPreview />
</div>
</WithLintingErrors>
</EditorProviders>
)
@@ -15,5 +15,4 @@ export const mockScope = () => ({
doc: '\\documentclass{article}',
}),
},
hasLintingError: false,
})
@@ -204,6 +204,7 @@ const makeIdeReactProvider = (scope, socket) => {
setStartedFreeTrial,
reportError: () => {},
projectJoined: true,
permissionsLevel: scope.permissionsLevel,
}))
const [ideContextValue] = useState(() => {