Ver Fonte

Allow context providers to be overridden in ReactContextRoot (#22631)

* Allow providers to be overridden in ReactContextRoot
* Use ReactContextRoot in EditorProviders
* Use ReactContextRoot in ScopeDecorator

GitOrigin-RevId: bb6dab91f3fca843d7563ed812c4ea6f56fb28bb
Alf Eaton há 1 ano atrás
pai
commit
3ac1b48d10
19 ficheiros alterados com 296 adições e 302 exclusões
  1. 95 64
      services/web/frontend/js/features/ide-react/context/react-context-root.tsx
  2. 10 99
      services/web/frontend/stories/decorators/scope.tsx
  3. 10 2
      services/web/test/frontend/features/editor-left-menu/components/settings/settings-auto-close-brackets.test.tsx
  4. 10 2
      services/web/test/frontend/features/editor-left-menu/components/settings/settings-auto-complete.test.tsx
  5. 10 2
      services/web/test/frontend/features/editor-left-menu/components/settings/settings-compiler.test.tsx
  6. 10 2
      services/web/test/frontend/features/editor-left-menu/components/settings/settings-dictionary.test.tsx
  7. 10 4
      services/web/test/frontend/features/editor-left-menu/components/settings/settings-document.test.tsx
  8. 10 2
      services/web/test/frontend/features/editor-left-menu/components/settings/settings-editor-theme.test.tsx
  9. 10 2
      services/web/test/frontend/features/editor-left-menu/components/settings/settings-font-family.test.tsx
  10. 10 2
      services/web/test/frontend/features/editor-left-menu/components/settings/settings-font-size.test.tsx
  11. 10 2
      services/web/test/frontend/features/editor-left-menu/components/settings/settings-image-name.test.tsx
  12. 10 2
      services/web/test/frontend/features/editor-left-menu/components/settings/settings-keybindings.test.tsx
  13. 10 2
      services/web/test/frontend/features/editor-left-menu/components/settings/settings-line-height.test.tsx
  14. 10 2
      services/web/test/frontend/features/editor-left-menu/components/settings/settings-math-preview.test.tsx
  15. 31 5
      services/web/test/frontend/features/editor-left-menu/components/settings/settings-overall-theme.test.tsx
  16. 10 2
      services/web/test/frontend/features/editor-left-menu/components/settings/settings-pdf-viewer.test.tsx
  17. 10 2
      services/web/test/frontend/features/editor-left-menu/components/settings/settings-spell-check-language.test.tsx
  18. 10 2
      services/web/test/frontend/features/editor-left-menu/components/settings/settings-syntax-validation.test.tsx
  19. 10 102
      services/web/test/frontend/helpers/editor-providers.jsx

+ 95 - 64
services/web/frontend/js/features/ide-react/context/react-context-root.tsx

@@ -1,79 +1,110 @@
 import { FC } from 'react'
+import { ChatProvider } from '@/features/chat/context/chat-context'
 import { ConnectionProvider } from './connection-context'
-import { IdeReactProvider } from '@/features/ide-react/context/ide-react-context'
-import { LayoutProvider } from '@/shared/context/layout-context'
+import { DetachCompileProvider } from '@/shared/context/detach-compile-context'
 import { DetachProvider } from '@/shared/context/detach-context'
-import { ProjectProvider } from '@/shared/context/project-context'
-import { ProjectSettingsProvider } from '@/features/editor-left-menu/context/project-settings-context'
-import { EditorProvider } from '@/shared/context/editor-context'
-import { UserProvider } from '@/shared/context/user-context'
 import { EditorManagerProvider } from '@/features/ide-react/context/editor-manager-context'
+import { EditorProvider } from '@/shared/context/editor-context'
 import { FileTreeDataProvider } from '@/shared/context/file-tree-data-context'
-import { DetachCompileProvider } from '@/shared/context/detach-compile-context'
-import { ChatProvider } from '@/features/chat/context/chat-context'
+import { FileTreeOpenProvider } from '@/features/ide-react/context/file-tree-open-context'
+import { FileTreePathProvider } from '@/features/file-tree/contexts/file-tree-path'
+import { IdeReactProvider } from '@/features/ide-react/context/ide-react-context'
+import { LayoutProvider } from '@/shared/context/layout-context'
 import { LocalCompileProvider } from '@/shared/context/local-compile-context'
-import { OnlineUsersProvider } from '@/features/ide-react/context/online-users-context'
 import { MetadataProvider } from '@/features/ide-react/context/metadata-context'
-import { ReferencesProvider } from '@/features/ide-react/context/references-context'
-import { SplitTestProvider } from '@/shared/context/split-test-context'
 import { ModalsContextProvider } from '@/features/ide-react/context/modals-context'
-import { FileTreePathProvider } from '@/features/file-tree/contexts/file-tree-path'
-import { UserSettingsProvider } from '@/shared/context/user-settings-context'
-import { PermissionsProvider } from '@/features/ide-react/context/permissions-context'
-import { FileTreeOpenProvider } from '@/features/ide-react/context/file-tree-open-context'
+import { OnlineUsersProvider } from '@/features/ide-react/context/online-users-context'
 import { OutlineProvider } from '@/features/ide-react/context/outline-context'
+import { PermissionsProvider } from '@/features/ide-react/context/permissions-context'
+import { ProjectProvider } from '@/shared/context/project-context'
+import { ProjectSettingsProvider } from '@/features/editor-left-menu/context/project-settings-context'
+import { ReferencesProvider } from '@/features/ide-react/context/references-context'
 import { SnapshotProvider } from '@/features/ide-react/context/snapshot-context'
+import { SplitTestProvider } from '@/shared/context/split-test-context'
+import { UserProvider } from '@/shared/context/user-context'
+import { UserSettingsProvider } from '@/shared/context/user-settings-context'
+
+export const ReactContextRoot: FC<{ providers?: Record<string, FC> }> = ({
+  children,
+  providers = {},
+}) => {
+  const Providers = {
+    ChatProvider,
+    ConnectionProvider,
+    DetachCompileProvider,
+    DetachProvider,
+    EditorManagerProvider,
+    EditorProvider,
+    FileTreeDataProvider,
+    FileTreeOpenProvider,
+    FileTreePathProvider,
+    IdeReactProvider,
+    LayoutProvider,
+    LocalCompileProvider,
+    MetadataProvider,
+    ModalsContextProvider,
+    OnlineUsersProvider,
+    OutlineProvider,
+    PermissionsProvider,
+    ProjectProvider,
+    ProjectSettingsProvider,
+    ReferencesProvider,
+    SnapshotProvider,
+    SplitTestProvider,
+    UserProvider,
+    UserSettingsProvider,
+    ...providers,
+  }
 
-export const ReactContextRoot: FC = ({ children }) => {
   return (
-    <SplitTestProvider>
-      <ModalsContextProvider>
-        <ConnectionProvider>
-          <IdeReactProvider>
-            <UserProvider>
-              <UserSettingsProvider>
-                <ProjectProvider>
-                  <SnapshotProvider>
-                    <FileTreeDataProvider>
-                      <FileTreePathProvider>
-                        <ReferencesProvider>
-                          <DetachProvider>
-                            <EditorProvider>
-                              <PermissionsProvider>
-                                <ProjectSettingsProvider>
-                                  <LayoutProvider>
-                                    <EditorManagerProvider>
-                                      <LocalCompileProvider>
-                                        <DetachCompileProvider>
-                                          <ChatProvider>
-                                            <FileTreeOpenProvider>
-                                              <OnlineUsersProvider>
-                                                <MetadataProvider>
-                                                  <OutlineProvider>
+    <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>
                                                     {children}
-                                                  </OutlineProvider>
-                                                </MetadataProvider>
-                                              </OnlineUsersProvider>
-                                            </FileTreeOpenProvider>
-                                          </ChatProvider>
-                                        </DetachCompileProvider>
-                                      </LocalCompileProvider>
-                                    </EditorManagerProvider>
-                                  </LayoutProvider>
-                                </ProjectSettingsProvider>
-                              </PermissionsProvider>
-                            </EditorProvider>
-                          </DetachProvider>
-                        </ReferencesProvider>
-                      </FileTreePathProvider>
-                    </FileTreeDataProvider>
-                  </SnapshotProvider>
-                </ProjectProvider>
-              </UserSettingsProvider>
-            </UserProvider>
-          </IdeReactProvider>
-        </ConnectionProvider>
-      </ModalsContextProvider>
-    </SplitTestProvider>
+                                                  </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>
   )
 }

+ 10 - 99
services/web/frontend/stories/decorators/scope.tsx

@@ -9,20 +9,6 @@ import {
 } from '../fixtures/compile'
 import useFetchMock from '../hooks/use-fetch-mock'
 import { useMeta } from '../hooks/use-meta'
-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 { ChatProvider } from '@/features/chat/context/chat-context'
 import SocketIOShim, { SocketIOMock } from '@/ide/connection/SocketIoShim'
 import { IdeContext } from '@/shared/context/ide-context'
 import {
@@ -31,18 +17,11 @@ import {
 } 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 { ModalsContextProvider } from '@/features/ide-react/context/modals-context'
 import { ConnectionContext } from '@/features/ide-react/context/connection-context'
 import { EventLog } from '@/features/ide-react/editor/event-log'
-import { ReferencesProvider } from '@/features/ide-react/context/references-context'
-import { PermissionsProvider } from '@/features/ide-react/context/permissions-context'
 import { Socket } from '@/features/ide-react/connection/types/socket'
 import { ConnectionState } from '@/features/ide-react/connection/types/connection-state'
-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 { OnlineUsersProvider } from '@/features/ide-react/context/online-users-context'
-import { SnapshotProvider } from '@/features/ide-react/context/snapshot-context'
+import { ReactContextRoot } from '@/features/ide-react/context/react-context-root'
 
 const scopeWatchers: [string, (value: any) => void][] = []
 
@@ -173,84 +152,16 @@ export const ScopeDecorator = (
   // set values on window.metaAttributesCache (created in initialize, above)
   useMeta(meta)
 
-  const Providers = {
-    ChatProvider,
-    ConnectionProvider,
-    DetachCompileProvider,
-    DetachProvider,
-    EditorProvider,
-    EditorManagerProvider,
-    SnapshotProvider,
-    FileTreeDataProvider,
-    FileTreeOpenProvider,
-    FileTreePathProvider,
-    IdeReactProvider,
-    LayoutProvider,
-    LocalCompileProvider,
-    MetadataProvider,
-    ModalsContextProvider,
-    OnlineUsersProvider,
-    OutlineProvider,
-    PermissionsProvider,
-    ProjectProvider,
-    ProjectSettingsProvider,
-    ReferencesProvider,
-    SplitTestProvider,
-    UserProvider,
-    UserSettingsProvider,
-    ...opts.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>
-                                                    <Story />
-                                                  </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>
+    <ReactContextRoot
+      providers={{
+        ConnectionProvider,
+        IdeReactProvider,
+        ...opts.providers,
+      }}
+    >
+      <Story />
+    </ReactContextRoot>
   )
 }
 

+ 10 - 2
services/web/test/frontend/features/editor-left-menu/components/settings/settings-auto-close-brackets.test.tsx

@@ -2,7 +2,9 @@ import { screen, within } from '@testing-library/dom'
 import { expect } from 'chai'
 import fetchMock from 'fetch-mock'
 import SettingsAutoCloseBrackets from '../../../../../../frontend/js/features/editor-left-menu/components/settings/settings-auto-close-brackets'
-import { renderWithEditorContext } from '../../../../helpers/render-with-context'
+import { EditorLeftMenuProvider } from '@/features/editor-left-menu/components/editor-left-menu-context'
+import { render } from '@testing-library/react'
+import { EditorProviders } from '../../../../helpers/editor-providers'
 
 describe('<SettingsAutoCloseBrackets />', function () {
   afterEach(function () {
@@ -10,7 +12,13 @@ describe('<SettingsAutoCloseBrackets />', function () {
   })
 
   it('shows correct menu', async function () {
-    renderWithEditorContext(<SettingsAutoCloseBrackets />)
+    render(
+      <EditorProviders>
+        <EditorLeftMenuProvider>
+          <SettingsAutoCloseBrackets />
+        </EditorLeftMenuProvider>
+      </EditorProviders>
+    )
 
     const select = screen.getByLabelText('Auto-close Brackets')
 

+ 10 - 2
services/web/test/frontend/features/editor-left-menu/components/settings/settings-auto-complete.test.tsx

@@ -2,7 +2,9 @@ import { screen, within } from '@testing-library/dom'
 import { expect } from 'chai'
 import fetchMock from 'fetch-mock'
 import SettingsAutoComplete from '../../../../../../frontend/js/features/editor-left-menu/components/settings/settings-auto-complete'
-import { renderWithEditorContext } from '../../../../helpers/render-with-context'
+import { EditorLeftMenuProvider } from '@/features/editor-left-menu/components/editor-left-menu-context'
+import { render } from '@testing-library/react'
+import { EditorProviders } from '../../../../helpers/editor-providers'
 
 describe('<SettingsAutoComplete />', function () {
   afterEach(function () {
@@ -10,7 +12,13 @@ describe('<SettingsAutoComplete />', function () {
   })
 
   it('shows correct menu', async function () {
-    renderWithEditorContext(<SettingsAutoComplete />)
+    render(
+      <EditorProviders>
+        <EditorLeftMenuProvider>
+          <SettingsAutoComplete />
+        </EditorLeftMenuProvider>
+      </EditorProviders>
+    )
 
     const select = screen.getByLabelText('Auto-complete')
 

+ 10 - 2
services/web/test/frontend/features/editor-left-menu/components/settings/settings-compiler.test.tsx

@@ -2,7 +2,9 @@ import { screen, within } from '@testing-library/dom'
 import { expect } from 'chai'
 import fetchMock from 'fetch-mock'
 import SettingsCompiler from '../../../../../../frontend/js/features/editor-left-menu/components/settings/settings-compiler'
-import { renderWithEditorContext } from '../../../../helpers/render-with-context'
+import { EditorLeftMenuProvider } from '@/features/editor-left-menu/components/editor-left-menu-context'
+import { render } from '@testing-library/react'
+import { EditorProviders } from '../../../../helpers/editor-providers'
 
 describe('<SettingsCompiler />', function () {
   afterEach(function () {
@@ -10,7 +12,13 @@ describe('<SettingsCompiler />', function () {
   })
 
   it('shows correct menu', async function () {
-    renderWithEditorContext(<SettingsCompiler />)
+    render(
+      <EditorProviders>
+        <EditorLeftMenuProvider>
+          <SettingsCompiler />
+        </EditorLeftMenuProvider>
+      </EditorProviders>
+    )
 
     const select = screen.getByLabelText('Compiler')
 

+ 10 - 2
services/web/test/frontend/features/editor-left-menu/components/settings/settings-dictionary.test.tsx

@@ -1,11 +1,19 @@
 import { fireEvent, screen, within } from '@testing-library/dom'
 import { expect } from 'chai'
 import SettingsDictionary from '../../../../../../frontend/js/features/editor-left-menu/components/settings/settings-dictionary'
-import { renderWithEditorContext } from '../../../../helpers/render-with-context'
+import { EditorLeftMenuProvider } from '@/features/editor-left-menu/components/editor-left-menu-context'
+import { render } from '@testing-library/react'
+import { EditorProviders } from '../../../../helpers/editor-providers'
 
 describe('<SettingsDictionary />', function () {
   it('open dictionary modal', function () {
-    renderWithEditorContext(<SettingsDictionary />)
+    render(
+      <EditorProviders>
+        <EditorLeftMenuProvider>
+          <SettingsDictionary />
+        </EditorLeftMenuProvider>
+      </EditorProviders>
+    )
 
     screen.getByText('Dictionary')
 

+ 10 - 4
services/web/test/frontend/features/editor-left-menu/components/settings/settings-document.test.tsx

@@ -4,8 +4,10 @@ import sinon from 'sinon'
 import fetchMock from 'fetch-mock'
 import SettingsDocument from '../../../../../../frontend/js/features/editor-left-menu/components/settings/settings-document'
 import * as isValidTeXFileModule from '../../../../../../frontend/js/main/is-valid-tex-file'
-import { renderWithEditorContext } from '../../../../helpers/render-with-context'
 import { Folder } from '../../../../../../types/folder'
+import { EditorLeftMenuProvider } from '@/features/editor-left-menu/components/editor-left-menu-context'
+import { render } from '@testing-library/react'
+import { EditorProviders } from '../../../../helpers/editor-providers'
 
 describe('<SettingsDocument />', function () {
   let isValidTeXFileStub: sinon.SinonStub
@@ -35,9 +37,13 @@ describe('<SettingsDocument />', function () {
   })
 
   it('shows correct menu', async function () {
-    renderWithEditorContext(<SettingsDocument />, {
-      rootFolder: [rootFolder],
-    })
+    render(
+      <EditorProviders rootFolder={[rootFolder as any]}>
+        <EditorLeftMenuProvider>
+          <SettingsDocument />
+        </EditorLeftMenuProvider>
+      </EditorProviders>
+    )
 
     const select = screen.getByLabelText('Main document')
 

+ 10 - 2
services/web/test/frontend/features/editor-left-menu/components/settings/settings-editor-theme.test.tsx

@@ -2,7 +2,9 @@ import { screen, within } from '@testing-library/dom'
 import { expect } from 'chai'
 import fetchMock from 'fetch-mock'
 import SettingsEditorTheme from '../../../../../../frontend/js/features/editor-left-menu/components/settings/settings-editor-theme'
-import { renderWithEditorContext } from '../../../../helpers/render-with-context'
+import { EditorLeftMenuProvider } from '@/features/editor-left-menu/components/editor-left-menu-context'
+import { render } from '@testing-library/react'
+import { EditorProviders } from '../../../../helpers/editor-providers'
 
 describe('<SettingsEditorTheme />', function () {
   const editorThemes = ['editortheme-1', 'editortheme-2', 'editortheme-3']
@@ -19,7 +21,13 @@ describe('<SettingsEditorTheme />', function () {
   })
 
   it('shows correct menu', async function () {
-    renderWithEditorContext(<SettingsEditorTheme />)
+    render(
+      <EditorProviders>
+        <EditorLeftMenuProvider>
+          <SettingsEditorTheme />
+        </EditorLeftMenuProvider>
+      </EditorProviders>
+    )
 
     const select = screen.getByLabelText('Editor theme')
 

+ 10 - 2
services/web/test/frontend/features/editor-left-menu/components/settings/settings-font-family.test.tsx

@@ -2,7 +2,9 @@ import { screen, within } from '@testing-library/dom'
 import { expect } from 'chai'
 import fetchMock from 'fetch-mock'
 import SettingsFontFamily from '../../../../../../frontend/js/features/editor-left-menu/components/settings/settings-font-family'
-import { renderWithEditorContext } from '../../../../helpers/render-with-context'
+import { EditorLeftMenuProvider } from '@/features/editor-left-menu/components/editor-left-menu-context'
+import { render } from '@testing-library/react'
+import { EditorProviders } from '../../../../helpers/editor-providers'
 
 describe('<SettingsFontFamily />', function () {
   afterEach(function () {
@@ -10,7 +12,13 @@ describe('<SettingsFontFamily />', function () {
   })
 
   it('shows correct menu', async function () {
-    renderWithEditorContext(<SettingsFontFamily />)
+    render(
+      <EditorProviders>
+        <EditorLeftMenuProvider>
+          <SettingsFontFamily />
+        </EditorLeftMenuProvider>
+      </EditorProviders>
+    )
 
     const select = screen.getByLabelText('Font Family')
 

+ 10 - 2
services/web/test/frontend/features/editor-left-menu/components/settings/settings-font-size.test.tsx

@@ -2,7 +2,9 @@ import { screen, within } from '@testing-library/dom'
 import { expect } from 'chai'
 import fetchMock from 'fetch-mock'
 import SettingsFontSize from '../../../../../../frontend/js/features/editor-left-menu/components/settings/settings-font-size'
-import { renderWithEditorContext } from '../../../../helpers/render-with-context'
+import { EditorLeftMenuProvider } from '@/features/editor-left-menu/components/editor-left-menu-context'
+import { render } from '@testing-library/react'
+import { EditorProviders } from '../../../../helpers/editor-providers'
 
 describe('<SettingsFontSize />', function () {
   const sizes = ['10', '11', '12', '13', '14', '16', '18', '20', '22', '24']
@@ -12,7 +14,13 @@ describe('<SettingsFontSize />', function () {
   })
 
   it('shows correct menu', async function () {
-    renderWithEditorContext(<SettingsFontSize />)
+    render(
+      <EditorProviders>
+        <EditorLeftMenuProvider>
+          <SettingsFontSize />
+        </EditorLeftMenuProvider>
+      </EditorProviders>
+    )
 
     const select = screen.getByLabelText('Font Size')
 

+ 10 - 2
services/web/test/frontend/features/editor-left-menu/components/settings/settings-image-name.test.tsx

@@ -3,7 +3,9 @@ import { expect } from 'chai'
 import fetchMock from 'fetch-mock'
 import SettingsImageName from '../../../../../../frontend/js/features/editor-left-menu/components/settings/settings-image-name'
 import type { AllowedImageName } from '../../../../../../types/project-settings'
-import { renderWithEditorContext } from '../../../../helpers/render-with-context'
+import { EditorLeftMenuProvider } from '@/features/editor-left-menu/components/editor-left-menu-context'
+import { render } from '@testing-library/react'
+import { EditorProviders } from '../../../../helpers/editor-providers'
 
 describe('<SettingsImageName />', function () {
   const allowedImageNames: AllowedImageName[] = [
@@ -26,7 +28,13 @@ describe('<SettingsImageName />', function () {
   })
 
   it('shows correct menu', async function () {
-    renderWithEditorContext(<SettingsImageName />)
+    render(
+      <EditorProviders>
+        <EditorLeftMenuProvider>
+          <SettingsImageName />
+        </EditorLeftMenuProvider>
+      </EditorProviders>
+    )
 
     const select = screen.getByLabelText('TeX Live version')
 

+ 10 - 2
services/web/test/frontend/features/editor-left-menu/components/settings/settings-keybindings.test.tsx

@@ -2,7 +2,9 @@ import { screen, within } from '@testing-library/dom'
 import { expect } from 'chai'
 import fetchMock from 'fetch-mock'
 import SettingsKeybindings from '../../../../../../frontend/js/features/editor-left-menu/components/settings/settings-keybindings'
-import { renderWithEditorContext } from '../../../../helpers/render-with-context'
+import { render } from '@testing-library/react'
+import { EditorProviders } from '../../../../helpers/editor-providers'
+import { EditorLeftMenuProvider } from '@/features/editor-left-menu/components/editor-left-menu-context'
 
 describe('<SettingsKeybindings />', function () {
   afterEach(function () {
@@ -10,7 +12,13 @@ describe('<SettingsKeybindings />', function () {
   })
 
   it('shows correct menu', async function () {
-    renderWithEditorContext(<SettingsKeybindings />)
+    render(
+      <EditorProviders>
+        <EditorLeftMenuProvider>
+          <SettingsKeybindings />
+        </EditorLeftMenuProvider>
+      </EditorProviders>
+    )
 
     const select = screen.getByLabelText('Keybindings')
 

+ 10 - 2
services/web/test/frontend/features/editor-left-menu/components/settings/settings-line-height.test.tsx

@@ -2,7 +2,9 @@ import { screen, within } from '@testing-library/dom'
 import { expect } from 'chai'
 import fetchMock from 'fetch-mock'
 import SettingsLineHeight from '../../../../../../frontend/js/features/editor-left-menu/components/settings/settings-line-height'
-import { renderWithEditorContext } from '../../../../helpers/render-with-context'
+import { render } from '@testing-library/react'
+import { EditorProviders } from '../../../../helpers/editor-providers'
+import { EditorLeftMenuProvider } from '@/features/editor-left-menu/components/editor-left-menu-context'
 
 describe('<SettingsLineHeight />', function () {
   afterEach(function () {
@@ -10,7 +12,13 @@ describe('<SettingsLineHeight />', function () {
   })
 
   it('shows correct menu', async function () {
-    renderWithEditorContext(<SettingsLineHeight />)
+    render(
+      <EditorProviders>
+        <EditorLeftMenuProvider>
+          <SettingsLineHeight />
+        </EditorLeftMenuProvider>
+      </EditorProviders>
+    )
 
     const select = screen.getByLabelText('Line Height')
 

+ 10 - 2
services/web/test/frontend/features/editor-left-menu/components/settings/settings-math-preview.test.tsx

@@ -2,7 +2,9 @@ import { screen, within } from '@testing-library/dom'
 import { expect } from 'chai'
 import fetchMock from 'fetch-mock'
 import SettingsMathPreview from '@/features/editor-left-menu/components/settings/settings-math-preview'
-import { renderWithEditorContext } from '../../../../helpers/render-with-context'
+import { render } from '@testing-library/react'
+import { EditorProviders } from '../../../../helpers/editor-providers'
+import { EditorLeftMenuProvider } from '@/features/editor-left-menu/components/editor-left-menu-context'
 
 describe('<SettingsMathPreview />', function () {
   afterEach(function () {
@@ -10,7 +12,13 @@ describe('<SettingsMathPreview />', function () {
   })
 
   it('shows correct menu', async function () {
-    renderWithEditorContext(<SettingsMathPreview />)
+    render(
+      <EditorProviders>
+        <EditorLeftMenuProvider>
+          <SettingsMathPreview />
+        </EditorLeftMenuProvider>
+      </EditorProviders>
+    )
 
     const select = screen.getByLabelText('Equation preview')
 

+ 31 - 5
services/web/test/frontend/features/editor-left-menu/components/settings/settings-overall-theme.test.tsx

@@ -3,8 +3,10 @@ import { expect } from 'chai'
 import fetchMock from 'fetch-mock'
 import SettingsOverallTheme from '../../../../../../frontend/js/features/editor-left-menu/components/settings/settings-overall-theme'
 import type { OverallThemeMeta } from '../../../../../../types/project-settings'
-import { renderWithEditorContext } from '../../../../helpers/render-with-context'
 import getMeta from '@/utils/meta'
+import { render } from '@testing-library/react'
+import { EditorProviders } from '../../../../helpers/editor-providers'
+import { EditorLeftMenuProvider } from '@/features/editor-left-menu/components/editor-left-menu-context'
 
 const IEEE_BRAND_ID = 1234
 const OTHER_BRAND_ID = 2234
@@ -35,7 +37,13 @@ describe('<SettingsOverallTheme />', function () {
   })
 
   it('shows correct menu', async function () {
-    renderWithEditorContext(<SettingsOverallTheme />)
+    render(
+      <EditorProviders>
+        <EditorLeftMenuProvider>
+          <SettingsOverallTheme />
+        </EditorLeftMenuProvider>
+      </EditorProviders>
+    )
 
     const select = screen.getByLabelText('Overall theme')
 
@@ -49,7 +57,13 @@ describe('<SettingsOverallTheme />', function () {
       window.metaAttributesCache.set('ol-brandVariation', {
         brand_id: IEEE_BRAND_ID,
       })
-      renderWithEditorContext(<SettingsOverallTheme />)
+      render(
+        <EditorProviders>
+          <EditorLeftMenuProvider>
+            <SettingsOverallTheme />
+          </EditorLeftMenuProvider>
+        </EditorProviders>
+      )
       const select = screen.queryByText('Overall theme')
       expect(select).to.not.exist
     })
@@ -58,14 +72,26 @@ describe('<SettingsOverallTheme />', function () {
       window.metaAttributesCache.set('ol-brandVariation', {
         brand_id: OTHER_BRAND_ID,
       })
-      renderWithEditorContext(<SettingsOverallTheme />)
+      render(
+        <EditorProviders>
+          <EditorLeftMenuProvider>
+            <SettingsOverallTheme />
+          </EditorLeftMenuProvider>
+        </EditorProviders>
+      )
       const select = screen.getByLabelText('Overall theme')
       expect(select).to.exist
     })
 
     it('should show overall theme picker for non branded projects', function () {
       window.metaAttributesCache.set('ol-brandVariation', undefined)
-      renderWithEditorContext(<SettingsOverallTheme />)
+      render(
+        <EditorProviders>
+          <EditorLeftMenuProvider>
+            <SettingsOverallTheme />
+          </EditorLeftMenuProvider>
+        </EditorProviders>
+      )
       const select = screen.getByLabelText('Overall theme')
       expect(select).to.exist
     })

+ 10 - 2
services/web/test/frontend/features/editor-left-menu/components/settings/settings-pdf-viewer.test.tsx

@@ -2,7 +2,9 @@ import { screen, within } from '@testing-library/dom'
 import { expect } from 'chai'
 import fetchMock from 'fetch-mock'
 import SettingsPdfViewer from '../../../../../../frontend/js/features/editor-left-menu/components/settings/settings-pdf-viewer'
-import { renderWithEditorContext } from '../../../../helpers/render-with-context'
+import { render } from '@testing-library/react'
+import { EditorProviders } from '../../../../helpers/editor-providers'
+import { EditorLeftMenuProvider } from '@/features/editor-left-menu/components/editor-left-menu-context'
 
 describe('<SettingsPdfViewer />', function () {
   afterEach(function () {
@@ -10,7 +12,13 @@ describe('<SettingsPdfViewer />', function () {
   })
 
   it('shows correct menu', async function () {
-    renderWithEditorContext(<SettingsPdfViewer />)
+    render(
+      <EditorProviders>
+        <EditorLeftMenuProvider>
+          <SettingsPdfViewer />
+        </EditorLeftMenuProvider>
+      </EditorProviders>
+    )
 
     const select = screen.getByLabelText('PDF Viewer')
 

+ 10 - 2
services/web/test/frontend/features/editor-left-menu/components/settings/settings-spell-check-language.test.tsx

@@ -3,7 +3,9 @@ import { expect } from 'chai'
 import fetchMock from 'fetch-mock'
 import SettingsSpellCheckLanguage from '../../../../../../frontend/js/features/editor-left-menu/components/settings/settings-spell-check-language'
 import type { SpellCheckLanguage } from '../../../../../../types/project-settings'
-import { renderWithEditorContext } from '../../../../helpers/render-with-context'
+import { render } from '@testing-library/react'
+import { EditorProviders } from '../../../../helpers/editor-providers'
+import { EditorLeftMenuProvider } from '@/features/editor-left-menu/components/editor-left-menu-context'
 
 describe('<SettingsSpellCheckLanguage />', function () {
   const languages: SpellCheckLanguage[] = [
@@ -28,7 +30,13 @@ describe('<SettingsSpellCheckLanguage />', function () {
   })
 
   it('shows correct menu', async function () {
-    renderWithEditorContext(<SettingsSpellCheckLanguage />)
+    render(
+      <EditorProviders>
+        <EditorLeftMenuProvider>
+          <SettingsSpellCheckLanguage />
+        </EditorLeftMenuProvider>
+      </EditorProviders>
+    )
 
     const select = screen.getByLabelText('Spell check')
 

+ 10 - 2
services/web/test/frontend/features/editor-left-menu/components/settings/settings-syntax-validation.test.tsx

@@ -2,7 +2,9 @@ import { screen, within } from '@testing-library/dom'
 import { expect } from 'chai'
 import fetchMock from 'fetch-mock'
 import SettingsSyntaxValidation from '../../../../../../frontend/js/features/editor-left-menu/components/settings/settings-syntax-validation'
-import { renderWithEditorContext } from '../../../../helpers/render-with-context'
+import { render } from '@testing-library/react'
+import { EditorProviders } from '../../../../helpers/editor-providers'
+import { EditorLeftMenuProvider } from '@/features/editor-left-menu/components/editor-left-menu-context'
 
 describe('<SettingsSyntaxValidation />', function () {
   afterEach(function () {
@@ -10,7 +12,13 @@ describe('<SettingsSyntaxValidation />', function () {
   })
 
   it('shows correct menu', async function () {
-    renderWithEditorContext(<SettingsSyntaxValidation />)
+    render(
+      <EditorProviders>
+        <EditorLeftMenuProvider>
+          <SettingsSyntaxValidation />
+        </EditorLeftMenuProvider>
+      </EditorProviders>
+    )
 
     const select = screen.getByLabelText('Code check')
 

+ 10 - 102
services/web/test/frontend/helpers/editor-providers.jsx

@@ -2,19 +2,6 @@
 /* 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'
@@ -26,16 +13,7 @@ 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'
+import { ReactContextRoot } from '@/features/ide-react/context/react-context-root'
 
 // these constants can be imported in tests instead of
 // using magic strings
@@ -154,87 +132,17 @@ export function EditorProviders({
   // 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>
+    <ReactContextRoot
+      providers={{
+        ConnectionProvider,
+        IdeReactProvider,
+        ...providers,
+      }}
+    >
+      {children}
+    </ReactContextRoot>
   )
 }