render-with-context.js 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. // Disable prop type checks for test harnesses
  2. /* eslint-disable react/prop-types */
  3. import { render } from '@testing-library/react'
  4. import { renderHook } from '@testing-library/react-hooks'
  5. import sinon from 'sinon'
  6. import { UserProvider } from '../../../frontend/js/shared/context/user-context'
  7. import { EditorProvider } from '../../../frontend/js/shared/context/editor-context'
  8. import { LayoutProvider } from '../../../frontend/js/shared/context/layout-context'
  9. import { DetachProvider } from '../../../frontend/js/shared/context/detach-context'
  10. import { ChatProvider } from '../../../frontend/js/features/chat/context/chat-context'
  11. import { IdeProvider } from '../../../frontend/js/shared/context/ide-context'
  12. import { get } from 'lodash'
  13. import { ProjectProvider } from '../../../frontend/js/shared/context/project-context'
  14. import { SplitTestProvider } from '../../../frontend/js/shared/context/split-test-context'
  15. import { CompileProvider } from '../../../frontend/js/shared/context/compile-context'
  16. import { FileTreeDataProvider } from '../../../frontend/js/shared/context/file-tree-data-context'
  17. // these constants can be imported in tests instead of
  18. // using magic strings
  19. export const PROJECT_ID = 'project123'
  20. export const PROJECT_NAME = 'project-name'
  21. export function EditorProviders({
  22. user = { id: '123abd', email: 'testuser@example.com' },
  23. projectId = PROJECT_ID,
  24. rootDocId = '_root_doc_id',
  25. socket = {
  26. on: sinon.stub(),
  27. removeListener: sinon.stub(),
  28. },
  29. isRestrictedTokenMember = false,
  30. clsiServerId = '1234',
  31. scope,
  32. features = {
  33. referencesSearch: true,
  34. },
  35. permissionsLevel = 'owner',
  36. children,
  37. rootFolder = [
  38. {
  39. _id: 'root-folder-id',
  40. name: 'rootFolder',
  41. docs: [],
  42. folders: [],
  43. fileRefs: [],
  44. },
  45. ],
  46. ui = { view: null, pdfLayout: 'flat', chatOpen: true },
  47. fileTreeManager = {
  48. findEntityById: () => null,
  49. findEntityByPath: () => null,
  50. getEntityPath: () => '',
  51. getRootDocDirname: () => '',
  52. },
  53. editorManager = {
  54. getCurrentDocId: () => 'foo',
  55. getCurrentDocValue: () => {},
  56. openDoc: sinon.stub(),
  57. },
  58. }) {
  59. window.user = user || window.user
  60. window.gitBridgePublicBaseUrl = 'git.overleaf.test'
  61. window.project_id = projectId != null ? projectId : window.project_id
  62. window.isRestrictedTokenMember = isRestrictedTokenMember
  63. const $scope = {
  64. user: window.user,
  65. project: {
  66. _id: window.project_id,
  67. name: PROJECT_NAME,
  68. owner: {
  69. _id: '124abd',
  70. email: 'owner@example.com',
  71. },
  72. features,
  73. rootDoc_id: rootDocId,
  74. rootFolder,
  75. },
  76. ui,
  77. $watch: (path, callback) => {
  78. callback(get($scope, path))
  79. return () => null
  80. },
  81. $applyAsync: sinon.stub(),
  82. toggleHistory: sinon.stub(),
  83. permissionsLevel,
  84. ...scope,
  85. }
  86. const metadataManager = {
  87. metadata: {
  88. state: {
  89. documents: {},
  90. },
  91. },
  92. }
  93. window._ide = {
  94. $scope,
  95. socket,
  96. clsiServerId,
  97. editorManager,
  98. fileTreeManager,
  99. metadataManager,
  100. }
  101. return (
  102. <SplitTestProvider>
  103. <IdeProvider ide={window._ide}>
  104. <UserProvider>
  105. <ProjectProvider>
  106. <FileTreeDataProvider>
  107. <EditorProvider settings={{}}>
  108. <DetachProvider>
  109. <LayoutProvider>
  110. <CompileProvider>{children}</CompileProvider>
  111. </LayoutProvider>
  112. </DetachProvider>
  113. </EditorProvider>
  114. </FileTreeDataProvider>
  115. </ProjectProvider>
  116. </UserProvider>
  117. </IdeProvider>
  118. </SplitTestProvider>
  119. )
  120. }
  121. export function renderWithEditorContext(
  122. component,
  123. contextProps,
  124. renderOptions = {}
  125. ) {
  126. const EditorProvidersWrapper = ({ children }) => (
  127. <EditorProviders {...contextProps}>{children}</EditorProviders>
  128. )
  129. return render(component, {
  130. wrapper: EditorProvidersWrapper,
  131. ...renderOptions,
  132. })
  133. }
  134. export function renderHookWithEditorContext(hook, contextProps) {
  135. const EditorProvidersWrapper = ({ children }) => (
  136. <EditorProviders {...contextProps}>{children}</EditorProviders>
  137. )
  138. return renderHook(hook, { wrapper: EditorProvidersWrapper })
  139. }
  140. export function ChatProviders({ children, ...props }) {
  141. return (
  142. <EditorProviders {...props}>
  143. <ChatProvider>{children}</ChatProvider>
  144. </EditorProviders>
  145. )
  146. }
  147. export function renderWithChatContext(component, props) {
  148. const ChatProvidersWrapper = ({ children }) => (
  149. <ChatProviders {...props}>{children}</ChatProviders>
  150. )
  151. return render(component, { wrapper: ChatProvidersWrapper })
  152. }
  153. export function cleanUpContext() {
  154. delete window.user
  155. delete window.project_id
  156. delete window._ide
  157. }