mirror of
https://github.com/yu-i-i/overleaf-cep.git
synced 2026-05-23 17:19:37 +02:00
[web] Convert EditorProviders and some test files to Typescript (#26512)
* Rename files to tsx * Update types * Remove props that aren't typed * Add `LayoutContextOwnStates` * Use `LayoutContextOwnStates` * Ignore ts errors about `SocketIOMock` * Address comments: remove `satisfies`, update `BroadcastChannel` fixture * Add types to `makeEditorOpenDocProvider`. Update `openDocId`->`currentDocumentId` * misc. * Type sockets as `SocketIOMock & Socket` * Fix remaining typing errors * Fix type of `ideReactContextValue` GitOrigin-RevId: 2734ac707517d56c452b0bf06ea3438f947a64be
This commit is contained in:
@@ -39,6 +39,28 @@ const enableROMirrorOnClient =
|
||||
new URLSearchParams(window.location.search).get('ro-mirror-on-client') ===
|
||||
'enabled'
|
||||
|
||||
export type ToolbarHeaderProps = {
|
||||
cobranding: Cobranding | undefined
|
||||
onShowLeftMenuClick: () => void
|
||||
chatIsOpen: boolean
|
||||
toggleChatOpen: () => void
|
||||
reviewPanelOpen: boolean
|
||||
toggleReviewPanelOpen: (e: React.MouseEvent) => void
|
||||
historyIsOpen: boolean
|
||||
toggleHistoryOpen: () => void
|
||||
unreadMessageCount: number
|
||||
onlineUsers: OnlineUser[]
|
||||
goToUser: (user: OnlineUser) => void
|
||||
isRestrictedTokenMember: boolean | undefined
|
||||
hasPublishPermissions: boolean
|
||||
chatVisible: boolean
|
||||
projectName: string
|
||||
renameProject: (name: string) => void
|
||||
hasRenamePermissions: boolean
|
||||
openShareModal: () => void
|
||||
trackChangesVisible: boolean | undefined
|
||||
}
|
||||
|
||||
const ToolbarHeader = React.memo(function ToolbarHeader({
|
||||
cobranding,
|
||||
onShowLeftMenuClick,
|
||||
@@ -59,27 +81,7 @@ const ToolbarHeader = React.memo(function ToolbarHeader({
|
||||
hasRenamePermissions,
|
||||
openShareModal,
|
||||
trackChangesVisible,
|
||||
}: {
|
||||
cobranding: Cobranding | undefined
|
||||
onShowLeftMenuClick: () => void
|
||||
chatIsOpen: boolean
|
||||
toggleChatOpen: () => void
|
||||
reviewPanelOpen: boolean
|
||||
toggleReviewPanelOpen: (e: React.MouseEvent) => void
|
||||
historyIsOpen: boolean
|
||||
toggleHistoryOpen: () => void
|
||||
unreadMessageCount: number
|
||||
onlineUsers: OnlineUser[]
|
||||
goToUser: (user: OnlineUser) => void
|
||||
isRestrictedTokenMember: boolean | undefined
|
||||
hasPublishPermissions: boolean
|
||||
chatVisible: boolean
|
||||
projectName: string
|
||||
renameProject: (name: string) => void
|
||||
hasRenamePermissions: boolean
|
||||
openShareModal: () => void
|
||||
trackChangesVisible: boolean | undefined
|
||||
}) {
|
||||
}: ToolbarHeaderProps) {
|
||||
const chatEnabled = getMeta('ol-capabilities')?.includes('chat')
|
||||
|
||||
const { t } = useTranslation()
|
||||
|
||||
@@ -11,12 +11,15 @@ import { DocId } from '../../../../../types/project-settings'
|
||||
import useExposedState from '@/shared/hooks/use-exposed-state'
|
||||
import { DocumentContainer } from '@/features/ide-react/editor/document-container'
|
||||
|
||||
type EditorOpenDocContextValue = {
|
||||
export interface EditorOpenDocContextState {
|
||||
currentDocumentId: DocId | null
|
||||
setCurrentDocumentId: Dispatch<SetStateAction<DocId | null>>
|
||||
openDocName: string | null
|
||||
setOpenDocName: Dispatch<SetStateAction<string | null>>
|
||||
currentDocument: DocumentContainer | null
|
||||
}
|
||||
|
||||
interface EditorOpenDocContextValue extends EditorOpenDocContextState {
|
||||
setCurrentDocumentId: Dispatch<SetStateAction<DocId | null>>
|
||||
setOpenDocName: Dispatch<SetStateAction<string | null>>
|
||||
setCurrentDocument: Dispatch<SetStateAction<DocumentContainer | null>>
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { FC } from 'react'
|
||||
import React, { FC, PropsWithChildren } from 'react'
|
||||
import { ChatProvider } from '@/features/chat/context/chat-context'
|
||||
import { ConnectionProvider } from './connection-context'
|
||||
import { DetachCompileProvider } from '@/shared/context/detach-compile-context'
|
||||
@@ -32,7 +32,7 @@ import { CommandRegistryProvider } from './command-registry-context'
|
||||
|
||||
export const ReactContextRoot: FC<
|
||||
React.PropsWithChildren<{
|
||||
providers?: Record<string, FC>
|
||||
providers?: Record<string, FC<PropsWithChildren>>
|
||||
}>
|
||||
> = ({ children, providers = {} }) => {
|
||||
const Providers = {
|
||||
|
||||
@@ -25,37 +25,40 @@ import usePersistedState from '@/shared/hooks/use-persisted-state'
|
||||
export type IdeLayout = 'sideBySide' | 'flat'
|
||||
export type IdeView = 'editor' | 'file' | 'pdf' | 'history'
|
||||
|
||||
export type LayoutContextValue = {
|
||||
export type LayoutContextOwnStates = {
|
||||
view: IdeView | null
|
||||
chatIsOpen: boolean
|
||||
reviewPanelOpen: boolean
|
||||
miniReviewPanelVisible: boolean
|
||||
leftMenuShown: boolean
|
||||
loadingStyleSheet: boolean
|
||||
pdfLayout: IdeLayout
|
||||
projectSearchIsOpen: boolean
|
||||
openFile: BinaryFile | null
|
||||
}
|
||||
|
||||
export type LayoutContextValue = LayoutContextOwnStates & {
|
||||
reattach: () => void
|
||||
detach: () => void
|
||||
detachIsLinked: boolean
|
||||
detachRole: DetachRole
|
||||
changeLayout: (newLayout: IdeLayout, newView?: IdeView) => void
|
||||
view: IdeView | null
|
||||
setView: (view: IdeView | null) => void
|
||||
chatIsOpen: boolean
|
||||
setChatIsOpen: Dispatch<SetStateAction<LayoutContextValue['chatIsOpen']>>
|
||||
reviewPanelOpen: boolean
|
||||
setReviewPanelOpen: Dispatch<
|
||||
SetStateAction<LayoutContextValue['reviewPanelOpen']>
|
||||
>
|
||||
miniReviewPanelVisible: boolean
|
||||
setMiniReviewPanelVisible: Dispatch<
|
||||
SetStateAction<LayoutContextValue['miniReviewPanelVisible']>
|
||||
>
|
||||
leftMenuShown: boolean
|
||||
setLeftMenuShown: Dispatch<
|
||||
SetStateAction<LayoutContextValue['leftMenuShown']>
|
||||
>
|
||||
loadingStyleSheet: boolean
|
||||
setLoadingStyleSheet: Dispatch<
|
||||
SetStateAction<LayoutContextValue['loadingStyleSheet']>
|
||||
>
|
||||
pdfLayout: IdeLayout
|
||||
pdfPreviewOpen: boolean
|
||||
projectSearchIsOpen: boolean
|
||||
setProjectSearchIsOpen: Dispatch<SetStateAction<boolean>>
|
||||
openFile: BinaryFile | null
|
||||
setOpenFile: Dispatch<SetStateAction<BinaryFile | null>>
|
||||
}
|
||||
|
||||
|
||||
@@ -80,6 +80,7 @@ function mockProviders() {
|
||||
return {
|
||||
EditorOpenDocProvider: makeEditorOpenDocProvider({
|
||||
openDocName: 'main.tex',
|
||||
currentDocumentId: null,
|
||||
currentDocument: {
|
||||
doc_id: 'test-doc',
|
||||
getSnapshot: () => 'some doc content',
|
||||
@@ -87,7 +88,7 @@ function mockProviders() {
|
||||
on: () => {},
|
||||
off: () => {},
|
||||
leaveAndCleanUpPromise: () => Promise.resolve(),
|
||||
},
|
||||
} as any,
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,12 +5,13 @@ import { screen, waitFor } from '@testing-library/react'
|
||||
import LayoutDropdownButton from '../../../../../frontend/js/features/editor-navigation-toolbar/components/layout-dropdown-button'
|
||||
import { renderWithEditorContext } from '../../../helpers/render-with-context'
|
||||
import * as eventTracking from '@/infrastructure/event-tracking'
|
||||
import type { LayoutContextOwnStates } from '@/shared/context/layout-context'
|
||||
|
||||
describe('<LayoutDropdownButton />', function () {
|
||||
let openStub
|
||||
let sendMBSpy
|
||||
let openStub: sinon.SinonStub
|
||||
let sendMBSpy: sinon.SinonSpy
|
||||
|
||||
const defaultLayout = {
|
||||
const defaultLayout: Partial<LayoutContextOwnStates> = {
|
||||
pdfLayout: 'flat',
|
||||
view: 'pdf',
|
||||
chatIsOpen: false,
|
||||
@@ -161,9 +162,10 @@ describe('<LayoutDropdownButton />', function () {
|
||||
})
|
||||
|
||||
describe('on detach', async function () {
|
||||
let originalBroadcastChannel
|
||||
const originalBroadcastChannel = window.BroadcastChannel
|
||||
beforeEach(async function () {
|
||||
window.BroadcastChannel = originalBroadcastChannel || true // ensure that window.BroadcastChannel is truthy
|
||||
// @ts-expect-error
|
||||
window.BroadcastChannel = true // ensure that window.BroadcastChannel is truthy
|
||||
|
||||
renderWithEditorContext(<LayoutDropdownButton />, {
|
||||
layoutContext: { ...defaultLayout, view: 'editor' },
|
||||
@@ -8,12 +8,16 @@ describe('<OnlineUsersWidget />', function () {
|
||||
const defaultProps = {
|
||||
onlineUsers: [
|
||||
{
|
||||
id: 'test_user',
|
||||
user_id: 'test_user',
|
||||
name: 'test_user',
|
||||
email: 'test_email',
|
||||
},
|
||||
{
|
||||
id: 'another_test_user',
|
||||
user_id: 'another_test_user',
|
||||
name: 'another_test_user',
|
||||
email: 'another_test_email',
|
||||
},
|
||||
],
|
||||
goToUser: () => {},
|
||||
@@ -44,8 +48,10 @@ describe('<OnlineUsersWidget />', function () {
|
||||
fireEvent.click(icon)
|
||||
|
||||
expect(props.goToUser).to.be.calledWith({
|
||||
name: 'test_user',
|
||||
id: 'test_user',
|
||||
user_id: 'test_user',
|
||||
name: 'test_user',
|
||||
email: 'test_email',
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -55,12 +61,16 @@ describe('<OnlineUsersWidget />', function () {
|
||||
...defaultProps,
|
||||
onlineUsers: defaultProps.onlineUsers.concat([
|
||||
{
|
||||
id: 'user_3',
|
||||
user_id: 'user_3',
|
||||
name: 'user_3',
|
||||
email: 'user_3',
|
||||
},
|
||||
{
|
||||
id: 'user_4',
|
||||
user_id: 'user_4',
|
||||
name: 'user_4',
|
||||
email: 'user_4',
|
||||
},
|
||||
]),
|
||||
}
|
||||
@@ -96,8 +106,10 @@ describe('<OnlineUsersWidget />', function () {
|
||||
fireEvent.click(icon)
|
||||
|
||||
expect(testProps.goToUser).to.be.calledWith({
|
||||
name: 'user_3',
|
||||
id: 'user_3',
|
||||
user_id: 'user_3',
|
||||
name: 'user_3',
|
||||
email: 'user_3',
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -1,11 +1,13 @@
|
||||
import { expect } from 'chai'
|
||||
import { screen } from '@testing-library/react'
|
||||
|
||||
import ToolbarHeader from '../../../../../frontend/js/features/editor-navigation-toolbar/components/toolbar-header'
|
||||
import ToolbarHeader, {
|
||||
type ToolbarHeaderProps,
|
||||
} from '../../../../../frontend/js/features/editor-navigation-toolbar/components/toolbar-header'
|
||||
import { renderWithEditorContext } from '../../../helpers/render-with-context'
|
||||
|
||||
describe('<ToolbarHeader />', function () {
|
||||
const defaultProps = {
|
||||
const defaultProps: ToolbarHeaderProps = {
|
||||
onShowLeftMenuClick: () => {},
|
||||
toggleChatOpen: () => {},
|
||||
toggleReviewPanelOpen: () => {},
|
||||
@@ -19,11 +21,12 @@ describe('<ToolbarHeader />', function () {
|
||||
hasPublishPermissions: true,
|
||||
chatVisible: true,
|
||||
trackChangesVisible: true,
|
||||
handleChangeLayout: () => {},
|
||||
pdfLayout: 'sideBySide',
|
||||
view: 'editor',
|
||||
reattach: () => {},
|
||||
detach: () => {},
|
||||
cobranding: undefined,
|
||||
isRestrictedTokenMember: false,
|
||||
hasRenamePermissions: true,
|
||||
historyIsOpen: false,
|
||||
chatIsOpen: false,
|
||||
reviewPanelOpen: false,
|
||||
}
|
||||
|
||||
beforeEach(function () {
|
||||
@@ -40,6 +43,8 @@ describe('<ToolbarHeader />', function () {
|
||||
const props = {
|
||||
...defaultProps,
|
||||
cobranding: {
|
||||
brandId: 12,
|
||||
brandVariationId: 12,
|
||||
brandVariationHomeUrl: 'http://cobranding',
|
||||
brandVariationName: 'variation',
|
||||
logoImgUrl: 'http://cobranding/logo',
|
||||
@@ -1,6 +1,7 @@
|
||||
import FileTreeRoot from '../../../../../frontend/js/features/file-tree/components/file-tree-root'
|
||||
import { EditorProviders } from '../../../helpers/editor-providers'
|
||||
import { SocketIOMock } from '@/ide/connection/SocketIoShim'
|
||||
import type { Socket } from '@/features/ide-react/connection/types/socket'
|
||||
|
||||
describe('<FileTreeRoot/>', function () {
|
||||
beforeEach(function () {
|
||||
@@ -245,9 +246,9 @@ describe('<FileTreeRoot/>', function () {
|
||||
})
|
||||
|
||||
describe('when deselecting files', function () {
|
||||
let socket: SocketIOMock
|
||||
let socket: SocketIOMock & Socket
|
||||
beforeEach(function () {
|
||||
socket = new SocketIOMock()
|
||||
socket = new SocketIOMock() as any
|
||||
const rootFolder = [
|
||||
{
|
||||
_id: 'root-folder-id',
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
import FileTreeRoot from '../../../../../frontend/js/features/file-tree/components/file-tree-root'
|
||||
import { EditorProviders } from '../../../helpers/editor-providers'
|
||||
import { SocketIOMock } from '@/ide/connection/SocketIoShim'
|
||||
import type { Socket } from '@/features/ide-react/connection/types/socket'
|
||||
|
||||
describe('FileTree Create Folder Flow', function () {
|
||||
let socket: SocketIOMock
|
||||
let socket: SocketIOMock & Socket
|
||||
beforeEach(function () {
|
||||
socket = new SocketIOMock()
|
||||
socket = new SocketIOMock() as any
|
||||
cy.window().then(win => {
|
||||
win.metaAttributesCache.set('ol-user', { id: 'user1' })
|
||||
})
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import FileTreeRoot from '../../../../../frontend/js/features/file-tree/components/file-tree-root'
|
||||
import { EditorProviders } from '../../../helpers/editor-providers'
|
||||
import { SocketIOMock } from '@/ide/connection/SocketIoShim'
|
||||
import type { Socket } from '@/features/ide-react/connection/types/socket'
|
||||
|
||||
describe('FileTree Delete Entity Flow', function () {
|
||||
beforeEach(function () {
|
||||
@@ -10,9 +11,9 @@ describe('FileTree Delete Entity Flow', function () {
|
||||
})
|
||||
|
||||
describe('single entity', function () {
|
||||
let socket: SocketIOMock
|
||||
let socket: SocketIOMock & Socket
|
||||
beforeEach(function () {
|
||||
socket = new SocketIOMock()
|
||||
socket = new SocketIOMock() as any
|
||||
const rootFolder = [
|
||||
{
|
||||
_id: 'root-folder-id',
|
||||
@@ -136,9 +137,9 @@ describe('FileTree Delete Entity Flow', function () {
|
||||
})
|
||||
|
||||
describe('folders', function () {
|
||||
let socket: SocketIOMock
|
||||
let socket: SocketIOMock & Socket
|
||||
beforeEach(function () {
|
||||
socket = new SocketIOMock()
|
||||
socket = new SocketIOMock() as any
|
||||
const rootFolder = [
|
||||
{
|
||||
_id: 'root-folder-id',
|
||||
@@ -207,9 +208,9 @@ describe('FileTree Delete Entity Flow', function () {
|
||||
})
|
||||
|
||||
describe('multiple entities', function () {
|
||||
let socket: SocketIOMock
|
||||
let socket: SocketIOMock & Socket
|
||||
beforeEach(function () {
|
||||
socket = new SocketIOMock()
|
||||
socket = new SocketIOMock() as any
|
||||
const rootFolder = [
|
||||
{
|
||||
_id: 'root-folder-id',
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import FileTreeRoot from '../../../../../frontend/js/features/file-tree/components/file-tree-root'
|
||||
import { EditorProviders } from '../../../helpers/editor-providers'
|
||||
import { SocketIOMock } from '@/ide/connection/SocketIoShim'
|
||||
import type { Socket } from '@/features/ide-react/connection/types/socket'
|
||||
|
||||
describe('FileTree Rename Entity Flow', function () {
|
||||
beforeEach(function () {
|
||||
@@ -9,9 +10,9 @@ describe('FileTree Rename Entity Flow', function () {
|
||||
})
|
||||
})
|
||||
|
||||
let socket: SocketIOMock
|
||||
let socket: SocketIOMock & Socket
|
||||
beforeEach(function () {
|
||||
socket = new SocketIOMock()
|
||||
socket = new SocketIOMock() as any
|
||||
const rootFolder = [
|
||||
{
|
||||
_id: 'root-folder-id',
|
||||
|
||||
@@ -3,7 +3,14 @@
|
||||
import { merge } from 'lodash'
|
||||
import { SocketIOMock } from '@/ide/connection/SocketIoShim'
|
||||
import { IdeContext } from '@/shared/context/ide-context'
|
||||
import React, { useCallback, useEffect, useMemo, useState } from 'react'
|
||||
import React, {
|
||||
useCallback,
|
||||
useEffect,
|
||||
useState,
|
||||
useMemo,
|
||||
type FC,
|
||||
type PropsWithChildren,
|
||||
} from 'react'
|
||||
import {
|
||||
createReactScopeValueStore,
|
||||
IdeReactContext,
|
||||
@@ -12,12 +19,25 @@ import { IdeEventEmitter } from '@/features/ide-react/create-ide-event-emitter'
|
||||
import { ReactScopeValueStore } from '@/features/ide-react/scope-value-store/react-scope-value-store'
|
||||
import { ReactScopeEventEmitter } from '@/features/ide-react/scope-event-emitter/react-scope-event-emitter'
|
||||
import { ConnectionContext } from '@/features/ide-react/context/connection-context'
|
||||
import { EditorOpenDocContext } from '@/features/ide-react/context/editor-open-doc-context'
|
||||
import {
|
||||
EditorOpenDocContext,
|
||||
type EditorOpenDocContextState,
|
||||
} from '@/features/ide-react/context/editor-open-doc-context'
|
||||
import { ReactContextRoot } from '@/features/ide-react/context/react-context-root'
|
||||
import useEventListener from '@/shared/hooks/use-event-listener'
|
||||
import useDetachLayout from '@/shared/hooks/use-detach-layout'
|
||||
import { LayoutContext } from '@/shared/context/layout-context'
|
||||
import useExposedState from '@/shared/hooks/use-exposed-state'
|
||||
import {
|
||||
type IdeLayout,
|
||||
type IdeView,
|
||||
LayoutContext,
|
||||
type LayoutContextValue,
|
||||
} from '@/shared/context/layout-context'
|
||||
import type { Socket } from '@/features/ide-react/connection/types/socket'
|
||||
import type { PermissionsLevel } from '@/features/ide-react/types/permissions'
|
||||
import type { Folder } from '../../../types/folder'
|
||||
import type { SocketDebuggingInfo } from '@/features/ide-react/connection/types/connection-state'
|
||||
import type { DocumentContainer } from '@/features/ide-react/editor/document-container'
|
||||
|
||||
// these constants can be imported in tests instead of
|
||||
// using magic strings
|
||||
@@ -41,10 +61,26 @@ const defaultUserSettings = {
|
||||
mathPreview: true,
|
||||
}
|
||||
|
||||
/**
|
||||
* @typedef {import('@/shared/context/layout-context').LayoutContextValue} LayoutContextValue
|
||||
* @type Partial<LayoutContextValue>
|
||||
*/
|
||||
export type EditorProvidersProps = {
|
||||
user?: { id: string; email: string }
|
||||
projectId?: string
|
||||
projectOwner?: { _id: string; email: string }
|
||||
rootDocId?: string
|
||||
imageName?: string
|
||||
compiler?: string
|
||||
socket?: Socket
|
||||
isRestrictedTokenMember?: boolean
|
||||
scope?: Record<string, any>
|
||||
features?: Record<string, boolean>
|
||||
projectFeatures?: Record<string, boolean>
|
||||
permissionsLevel?: PermissionsLevel
|
||||
children?: React.ReactNode
|
||||
rootFolder?: Folder[]
|
||||
layoutContext?: Partial<LayoutContextValue>
|
||||
userSettings?: Record<string, any>
|
||||
providers?: Record<string, React.FC<React.PropsWithChildren<any>>>
|
||||
}
|
||||
|
||||
const layoutContextDefault = {
|
||||
view: 'editor',
|
||||
openFile: null,
|
||||
@@ -55,7 +91,7 @@ const layoutContextDefault = {
|
||||
projectSearchIsOpen: false,
|
||||
pdfLayout: 'sideBySide',
|
||||
loadingStyleSheet: false,
|
||||
}
|
||||
} satisfies Partial<LayoutContextValue>
|
||||
|
||||
export function EditorProviders({
|
||||
user = { id: USER_ID, email: USER_EMAIL },
|
||||
@@ -67,7 +103,7 @@ export function EditorProviders({
|
||||
rootDocId = '_root_doc_id',
|
||||
imageName = 'texlive-full:2024.1',
|
||||
compiler = 'pdflatex',
|
||||
socket = new SocketIOMock(),
|
||||
socket = new SocketIOMock() as any as Socket,
|
||||
isRestrictedTokenMember = false,
|
||||
scope: defaultScope = {},
|
||||
features = {
|
||||
@@ -94,7 +130,7 @@ export function EditorProviders({
|
||||
layoutContext = layoutContextDefault,
|
||||
userSettings = {},
|
||||
providers = {},
|
||||
}) {
|
||||
}: EditorProvidersProps) {
|
||||
window.metaAttributesCache.set(
|
||||
'ol-gitBridgePublicBaseUrl',
|
||||
'https://git.overleaf.test'
|
||||
@@ -121,7 +157,7 @@ export function EditorProviders({
|
||||
on: () => {},
|
||||
off: () => {},
|
||||
leaveAndCleanUpPromise: async () => {},
|
||||
},
|
||||
} as any as DocumentContainer,
|
||||
openDocName: null,
|
||||
currentDocumentId: null,
|
||||
},
|
||||
@@ -150,7 +186,7 @@ export function EditorProviders({
|
||||
ConnectionProvider: makeConnectionProvider(socket),
|
||||
IdeReactProvider: makeIdeReactProvider(scope, socket),
|
||||
EditorOpenDocProvider: makeEditorOpenDocProvider({
|
||||
openDocId: scope.editor.currentDocumentId,
|
||||
currentDocumentId: scope.editor.currentDocumentId,
|
||||
openDocName: scope.editor.openDocName,
|
||||
currentDocument: scope.editor.sharejs_doc,
|
||||
}),
|
||||
@@ -163,8 +199,8 @@ export function EditorProviders({
|
||||
)
|
||||
}
|
||||
|
||||
const makeConnectionProvider = socket => {
|
||||
const ConnectionProvider = ({ children }) => {
|
||||
const makeConnectionProvider = (socket: Socket) => {
|
||||
const ConnectionProvider: FC<PropsWithChildren> = ({ children }) => {
|
||||
const [value] = useState(() => ({
|
||||
socket,
|
||||
connectionState: {
|
||||
@@ -174,7 +210,7 @@ const makeConnectionProvider = socket => {
|
||||
reconnectAt: null,
|
||||
forcedDisconnectDelay: 0,
|
||||
lastConnectionAttempt: 0,
|
||||
error: '',
|
||||
error: '' as const,
|
||||
},
|
||||
isConnected: true,
|
||||
isStillReconnecting: false,
|
||||
@@ -182,6 +218,8 @@ const makeConnectionProvider = socket => {
|
||||
tryReconnectNow: () => {},
|
||||
registerUserActivity: () => {},
|
||||
disconnect: () => {},
|
||||
closeConnection: () => {},
|
||||
getSocketDebuggingInfo: () => ({}) as SocketDebuggingInfo,
|
||||
}))
|
||||
|
||||
return (
|
||||
@@ -193,8 +231,11 @@ const makeConnectionProvider = socket => {
|
||||
return ConnectionProvider
|
||||
}
|
||||
|
||||
const makeIdeReactProvider = (scope, socket) => {
|
||||
const IdeReactProvider = ({ children }) => {
|
||||
const makeIdeReactProvider = (
|
||||
scope: Record<string, unknown>,
|
||||
socket: Socket
|
||||
) => {
|
||||
const IdeReactProvider: FC<PropsWithChildren> = ({ children }) => {
|
||||
const [startedFreeTrial, setStartedFreeTrial] = useState(false)
|
||||
|
||||
const [ideReactContextValue] = useState(() => ({
|
||||
@@ -204,7 +245,9 @@ const makeIdeReactProvider = (scope, socket) => {
|
||||
setStartedFreeTrial,
|
||||
reportError: () => {},
|
||||
projectJoined: true,
|
||||
permissionsLevel: scope.permissionsLevel,
|
||||
permissionsLevel: scope.permissionsLevel as PermissionsLevel,
|
||||
setPermissionsLevel: () => {},
|
||||
setOutOfSync: () => {},
|
||||
}))
|
||||
|
||||
const [ideContextValue] = useState(() => {
|
||||
@@ -247,13 +290,15 @@ const makeIdeReactProvider = (scope, socket) => {
|
||||
return IdeReactProvider
|
||||
}
|
||||
|
||||
export function makeEditorOpenDocProvider(initialValues) {
|
||||
export function makeEditorOpenDocProvider(
|
||||
initialValues: EditorOpenDocContextState
|
||||
) {
|
||||
const {
|
||||
currentDocumentId: initialCurrentDocumentId,
|
||||
openDocName: initialOpenDocName,
|
||||
currentDocument: initialCurrentDocument,
|
||||
} = initialValues
|
||||
const EditorOpenDocProvider = ({ children }) => {
|
||||
const EditorOpenDocProvider: FC<PropsWithChildren> = ({ children }) => {
|
||||
const [currentDocumentId, setCurrentDocumentId] = useExposedState(
|
||||
initialCurrentDocumentId,
|
||||
'editor.open_doc_id'
|
||||
@@ -285,13 +330,15 @@ export function makeEditorOpenDocProvider(initialValues) {
|
||||
return EditorOpenDocProvider
|
||||
}
|
||||
|
||||
const makeLayoutProvider = layoutContextOverrides => {
|
||||
const makeLayoutProvider = (
|
||||
layoutContextOverrides?: Partial<LayoutContextValue>
|
||||
) => {
|
||||
const layout = {
|
||||
...layoutContextDefault,
|
||||
...layoutContextOverrides,
|
||||
}
|
||||
const LayoutProvider = ({ children }) => {
|
||||
const [view, setView] = useState(layout.view)
|
||||
const LayoutProvider: FC<PropsWithChildren> = ({ children }) => {
|
||||
const [view, setView] = useState<IdeView | null>(layout.view)
|
||||
const [openFile, setOpenFile] = useState(layout.openFile)
|
||||
const [chatIsOpen, setChatIsOpen] = useState(layout.chatIsOpen)
|
||||
const [reviewPanelOpen, setReviewPanelOpen] = useState(
|
||||
@@ -316,7 +363,7 @@ const makeLayoutProvider = layoutContextOverrides => {
|
||||
}, [setReviewPanelOpen])
|
||||
)
|
||||
const changeLayout = useCallback(
|
||||
(newLayout, newView = 'editor') => {
|
||||
(newLayout: IdeLayout, newView: IdeView = 'editor') => {
|
||||
setPdfLayout(newLayout)
|
||||
setView(newLayout === 'sideBySide' ? 'editor' : newView)
|
||||
},
|
||||
@@ -1,20 +0,0 @@
|
||||
// Disable prop type checks for test harnesses
|
||||
/* eslint-disable react/prop-types */
|
||||
|
||||
import { render } from '@testing-library/react'
|
||||
import { EditorProviders } from './editor-providers'
|
||||
|
||||
export function renderWithEditorContext(
|
||||
component,
|
||||
contextProps,
|
||||
renderOptions = {}
|
||||
) {
|
||||
const EditorProvidersWrapper = ({ children }) => (
|
||||
<EditorProviders {...contextProps}>{children}</EditorProviders>
|
||||
)
|
||||
|
||||
return render(component, {
|
||||
wrapper: EditorProvidersWrapper,
|
||||
...renderOptions,
|
||||
})
|
||||
}
|
||||
20
services/web/test/frontend/helpers/render-with-context.tsx
Normal file
20
services/web/test/frontend/helpers/render-with-context.tsx
Normal file
@@ -0,0 +1,20 @@
|
||||
import React from 'react'
|
||||
import { render, type RenderOptions } from '@testing-library/react'
|
||||
import { EditorProviders, type EditorProvidersProps } from './editor-providers'
|
||||
|
||||
export function renderWithEditorContext(
|
||||
component: React.ReactElement,
|
||||
contextProps: EditorProvidersProps = {},
|
||||
renderOptions: RenderOptions = {}
|
||||
) {
|
||||
const EditorProvidersWrapper = ({
|
||||
children,
|
||||
}: {
|
||||
children: React.ReactNode
|
||||
}) => <EditorProviders {...contextProps}>{children}</EditorProviders>
|
||||
|
||||
return render(component, {
|
||||
wrapper: EditorProvidersWrapper,
|
||||
...renderOptions,
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user