| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317 |
- // Disable prop type checks for test harnesses
- /* eslint-disable react/prop-types */
- import sinon from 'sinon'
- import { get, merge } from 'lodash'
- import { SplitTestProvider } from '@/shared/context/split-test-context'
- import { UserProvider } from '@/shared/context/user-context'
- import { ProjectProvider } from '@/shared/context/project-context'
- import { FileTreeDataProvider } from '@/shared/context/file-tree-data-context'
- import { EditorProvider } from '@/shared/context/editor-context'
- import { DetachProvider } from '@/shared/context/detach-context'
- import { LayoutProvider } from '@/shared/context/layout-context'
- import { LocalCompileProvider } from '@/shared/context/local-compile-context'
- import { DetachCompileProvider } from '@/shared/context/detach-compile-context'
- import { ProjectSettingsProvider } from '@/features/editor-left-menu/context/project-settings-context'
- import { FileTreePathProvider } from '@/features/file-tree/contexts/file-tree-path'
- import { UserSettingsProvider } from '@/shared/context/user-settings-context'
- import { OutlineProvider } from '@/features/ide-react/context/outline-context'
- import { SocketIOMock } from '@/ide/connection/SocketIoShim'
- import { IdeContext } from '@/shared/context/ide-context'
- import React, { useEffect, useState } from 'react'
- import {
- createReactScopeValueStore,
- IdeReactContext,
- } from '@/features/ide-react/context/ide-react-context'
- import { IdeEventEmitter } from '@/features/ide-react/create-ide-event-emitter'
- import { ReactScopeEventEmitter } from '@/features/ide-react/scope-event-emitter/react-scope-event-emitter'
- import { ConnectionContext } from '@/features/ide-react/context/connection-context'
- import { EventLog } from '@/features/ide-react/editor/event-log'
- import { ChatProvider } from '@/features/chat/context/chat-context'
- import { EditorManagerProvider } from '@/features/ide-react/context/editor-manager-context'
- import { FileTreeOpenProvider } from '@/features/ide-react/context/file-tree-open-context'
- import { MetadataProvider } from '@/features/ide-react/context/metadata-context'
- import { ModalsContextProvider } from '@/features/ide-react/context/modals-context'
- import { OnlineUsersProvider } from '@/features/ide-react/context/online-users-context'
- import { PermissionsProvider } from '@/features/ide-react/context/permissions-context'
- import { ReferencesProvider } from '@/features/ide-react/context/references-context'
- import { SnapshotProvider } from '@/features/ide-react/context/snapshot-context'
- import { EditorLeftMenuProvider } from '@/features/editor-left-menu/components/editor-left-menu-context'
- // these constants can be imported in tests instead of
- // using magic strings
- export const PROJECT_ID = 'project123'
- export const PROJECT_NAME = 'project-name'
- export const USER_ID = '123abd'
- export const USER_EMAIL = 'testuser@example.com'
- const defaultUserSettings = {
- pdfViewer: 'pdfjs',
- fontSize: 12,
- fontFamily: 'monaco',
- lineHeight: 'normal',
- editorTheme: 'textmate',
- overallTheme: '',
- mode: 'default',
- autoComplete: true,
- autoPairDelimiters: true,
- trackChanges: true,
- syntaxValidation: false,
- mathPreview: true,
- }
- export function EditorProviders({
- user = { id: USER_ID, email: USER_EMAIL },
- projectId = PROJECT_ID,
- projectOwner = {
- _id: '124abd',
- email: 'owner@example.com',
- },
- rootDocId = '_root_doc_id',
- socket = new SocketIOMock(),
- isRestrictedTokenMember = false,
- clsiServerId = '1234',
- scope = {},
- features = {
- referencesSearch: true,
- },
- permissionsLevel = 'owner',
- children,
- rootFolder = [
- {
- _id: 'root-folder-id',
- name: 'rootFolder',
- docs: [],
- folders: [],
- fileRefs: [],
- },
- ],
- ui = { view: 'editor', pdfLayout: 'sideBySide', chatOpen: true },
- fileTreeManager = {
- findEntityById: () => null,
- findEntityByPath: () => null,
- getEntityPath: () => '',
- getRootDocDirname: () => '',
- getPreviewByPath: path => ({ url: path, extension: 'png' }),
- },
- editorManager = {
- getCurrentDocId: () => 'foo',
- getCurrentDocValue: () => {},
- openDoc: sinon.stub(),
- },
- userSettings = {},
- providers = {},
- }) {
- window.metaAttributesCache.set(
- 'ol-gitBridgePublicBaseUrl',
- 'https://git.overleaf.test'
- )
- window.metaAttributesCache.set(
- 'ol-isRestrictedTokenMember',
- isRestrictedTokenMember
- )
- window.metaAttributesCache.set(
- 'ol-userSettings',
- merge({}, defaultUserSettings, userSettings)
- )
- const $scope = merge(
- {
- user,
- editor: {
- sharejs_doc: {
- doc_id: 'test-doc',
- getSnapshot: () => 'some doc content',
- },
- },
- project: {
- _id: projectId,
- name: PROJECT_NAME,
- owner: projectOwner,
- features,
- rootDoc_id: rootDocId,
- rootFolder,
- },
- ui,
- $watch: (path, callback) => {
- callback(get($scope, path))
- return () => null
- },
- $on: sinon.stub(),
- $applyAsync: sinon.stub(),
- permissionsLevel,
- },
- scope
- )
- window._ide = {
- $scope,
- socket,
- clsiServerId,
- editorManager,
- fileTreeManager,
- }
- // Add details for useUserContext
- window.metaAttributesCache.set('ol-user', { ...user, features })
- window.metaAttributesCache.set('ol-project_id', projectId)
- const Providers = {
- ChatProvider,
- ConnectionProvider,
- DetachCompileProvider,
- DetachProvider,
- EditorProvider,
- EditorLeftMenuProvider,
- EditorManagerProvider,
- SnapshotProvider,
- FileTreeDataProvider,
- FileTreeOpenProvider,
- FileTreePathProvider,
- IdeReactProvider,
- LayoutProvider,
- LocalCompileProvider,
- MetadataProvider,
- ModalsContextProvider,
- OnlineUsersProvider,
- OutlineProvider,
- PermissionsProvider,
- ProjectProvider,
- ProjectSettingsProvider,
- ReferencesProvider,
- SplitTestProvider,
- UserProvider,
- UserSettingsProvider,
- ...providers,
- }
- return (
- <Providers.SplitTestProvider>
- <Providers.ModalsContextProvider>
- <Providers.ConnectionProvider>
- <Providers.IdeReactProvider>
- <Providers.UserProvider>
- <Providers.UserSettingsProvider>
- <Providers.ProjectProvider>
- <Providers.SnapshotProvider>
- <Providers.FileTreeDataProvider>
- <Providers.FileTreePathProvider>
- <Providers.ReferencesProvider>
- <Providers.DetachProvider>
- <Providers.EditorProvider>
- <Providers.PermissionsProvider>
- <Providers.ProjectSettingsProvider>
- <Providers.LayoutProvider>
- <Providers.EditorManagerProvider>
- <Providers.LocalCompileProvider>
- <Providers.DetachCompileProvider>
- <Providers.ChatProvider>
- <Providers.FileTreeOpenProvider>
- <Providers.OnlineUsersProvider>
- <Providers.MetadataProvider>
- <Providers.OutlineProvider>
- <Providers.EditorLeftMenuProvider>
- {children}
- </Providers.EditorLeftMenuProvider>
- </Providers.OutlineProvider>
- </Providers.MetadataProvider>
- </Providers.OnlineUsersProvider>
- </Providers.FileTreeOpenProvider>
- </Providers.ChatProvider>
- </Providers.DetachCompileProvider>
- </Providers.LocalCompileProvider>
- </Providers.EditorManagerProvider>
- </Providers.LayoutProvider>
- </Providers.ProjectSettingsProvider>
- </Providers.PermissionsProvider>
- </Providers.EditorProvider>
- </Providers.DetachProvider>
- </Providers.ReferencesProvider>
- </Providers.FileTreePathProvider>
- </Providers.FileTreeDataProvider>
- </Providers.SnapshotProvider>
- </Providers.ProjectProvider>
- </Providers.UserSettingsProvider>
- </Providers.UserProvider>
- </Providers.IdeReactProvider>
- </Providers.ConnectionProvider>
- </Providers.ModalsContextProvider>
- </Providers.SplitTestProvider>
- )
- }
- const ConnectionProvider = ({ children }) => {
- const [value] = useState(() => ({
- socket: window._ide.socket,
- connectionState: {
- readyState: WebSocket.OPEN,
- forceDisconnected: false,
- inactiveDisconnect: false,
- reconnectAt: null,
- forcedDisconnectDelay: 0,
- lastConnectionAttempt: 0,
- error: '',
- },
- isConnected: true,
- isStillReconnecting: false,
- secondsUntilReconnect: () => 0,
- tryReconnectNow: () => {},
- registerUserActivity: () => {},
- disconnect: () => {},
- }))
- return (
- <ConnectionContext.Provider value={value}>
- {children}
- </ConnectionContext.Provider>
- )
- }
- const IdeReactProvider = ({ children }) => {
- const [startedFreeTrial, setStartedFreeTrial] = useState(false)
- const [ideReactContextValue] = useState(() => ({
- projectId: PROJECT_ID,
- eventEmitter: new IdeEventEmitter(),
- eventLog: new EventLog(),
- startedFreeTrial,
- setStartedFreeTrial,
- reportError: () => {},
- projectJoined: true,
- }))
- const [ideContextValue] = useState(() => {
- const ide = window._ide
- const scopeStore = createReactScopeValueStore(PROJECT_ID)
- for (const [key, value] of Object.entries(ide.$scope)) {
- // TODO: path for nested entries
- scopeStore.set(key, value)
- }
- scopeStore.set('editor.sharejs_doc', ide.$scope.editor.sharejs_doc)
- scopeStore.set('ui.chatOpen', ide.$scope.ui.chatOpen)
- const scopeEventEmitter = new ReactScopeEventEmitter(new IdeEventEmitter())
- return {
- ...ide,
- scopeStore,
- scopeEventEmitter,
- }
- })
- useEffect(() => {
- window.overleaf = {
- ...window.overleaf,
- unstable: {
- ...window.overleaf?.unstable,
- store: ideContextValue.scopeStore,
- },
- }
- }, [ideContextValue.scopeStore])
- return (
- <IdeReactContext.Provider value={ideReactContextValue}>
- <IdeContext.Provider value={ideContextValue}>
- {children}
- </IdeContext.Provider>
- </IdeReactContext.Provider>
- )
- }
|