file-tree-root.test.js 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  1. import { expect } from 'chai'
  2. import React from 'react'
  3. import sinon from 'sinon'
  4. import { screen, render, fireEvent, waitFor } from '@testing-library/react'
  5. import fetchMock from 'fetch-mock'
  6. import FileTreeRoot from '../../../../../frontend/js/features/file-tree/components/file-tree-root'
  7. describe('<FileTreeRoot/>', function () {
  8. const onSelect = sinon.stub()
  9. const onInit = sinon.stub()
  10. beforeEach(function () {
  11. global.requestAnimationFrame = sinon.stub()
  12. })
  13. afterEach(function () {
  14. delete global.requestAnimationFrame
  15. fetchMock.restore()
  16. onSelect.reset()
  17. onInit.reset()
  18. global.localStorage.clear()
  19. })
  20. it('renders', function () {
  21. const rootFolder = [
  22. {
  23. _id: 'root-folder-id',
  24. docs: [{ _id: '456def', name: 'main.tex' }],
  25. folders: [],
  26. fileRefs: [],
  27. },
  28. ]
  29. const { container } = render(
  30. <FileTreeRoot
  31. rootFolder={rootFolder}
  32. projectId="123abc"
  33. hasWritePermissions={false}
  34. userHasFeature={() => true}
  35. refProviders={{}}
  36. reindexReferences={() => null}
  37. setRefProviderEnabled={() => null}
  38. setStartedFreeTrial={() => null}
  39. rootDocId="456def"
  40. onSelect={onSelect}
  41. onInit={onInit}
  42. isConnected
  43. />
  44. )
  45. screen.queryByRole('tree')
  46. screen.getByRole('treeitem')
  47. screen.getByRole('treeitem', { name: 'main.tex', selected: true })
  48. expect(container.querySelector('.disconnected-overlay')).to.not.exist
  49. })
  50. it('renders with invalid selected doc in local storage', async function () {
  51. global.localStorage.setItem(
  52. 'doc.open_id.123abc',
  53. JSON.stringify('not-a-valid-id')
  54. )
  55. const rootFolder = [
  56. {
  57. _id: 'root-folder-id',
  58. docs: [{ _id: '456def', name: 'main.tex' }],
  59. folders: [],
  60. fileRefs: [],
  61. },
  62. ]
  63. render(
  64. <FileTreeRoot
  65. rootFolder={rootFolder}
  66. projectId="123abc"
  67. hasWritePermissions
  68. userHasFeature={() => true}
  69. refProviders={{}}
  70. reindexReferences={() => null}
  71. setRefProviderEnabled={() => null}
  72. setStartedFreeTrial={() => null}
  73. rootDocId="456def"
  74. onSelect={onSelect}
  75. onInit={onInit}
  76. isConnected
  77. />
  78. )
  79. // as a proxy to check that the invalid entity ha not been select we start
  80. // a delete and ensure the modal is displayed (the cancel button can be
  81. // selected) This is needed to make sure the test fail.
  82. const treeitemFile = screen.getByRole('treeitem', { name: 'main.tex' })
  83. fireEvent.click(treeitemFile, { ctrlKey: true })
  84. const toggleButton = screen.getByRole('button', { name: 'Menu' })
  85. fireEvent.click(toggleButton)
  86. const deleteButton = screen.getByRole('menuitem', { name: 'Delete' })
  87. fireEvent.click(deleteButton)
  88. await waitFor(() => screen.getByRole('button', { name: 'Cancel' }))
  89. })
  90. it('renders disconnected overlay', function () {
  91. const rootFolder = [
  92. {
  93. _id: 'root-folder-id',
  94. docs: [{ _id: '456def', name: 'main.tex' }],
  95. folders: [],
  96. fileRefs: [],
  97. },
  98. ]
  99. const { container } = render(
  100. <FileTreeRoot
  101. rootFolder={rootFolder}
  102. projectId="123abc"
  103. hasWritePermissions={false}
  104. rootDocId="456def"
  105. onSelect={onSelect}
  106. onInit={onInit}
  107. isConnected={false}
  108. userHasFeature={() => true}
  109. refProviders={{}}
  110. reindexReferences={() => null}
  111. setRefProviderEnabled={() => null}
  112. setStartedFreeTrial={() => null}
  113. />
  114. )
  115. expect(container.querySelector('.disconnected-overlay')).to.exist
  116. })
  117. it('fire onSelect', function () {
  118. const rootFolder = [
  119. {
  120. _id: 'root-folder-id',
  121. docs: [
  122. { _id: '456def', name: 'main.tex' },
  123. { _id: '789ghi', name: 'other.tex' },
  124. ],
  125. folders: [],
  126. fileRefs: [],
  127. },
  128. ]
  129. render(
  130. <FileTreeRoot
  131. rootFolder={rootFolder}
  132. projectId="123abc"
  133. rootDocId="456def"
  134. hasWritePermissions={false}
  135. userHasFeature={() => true}
  136. refProviders={{}}
  137. reindexReferences={() => null}
  138. setRefProviderEnabled={() => null}
  139. setStartedFreeTrial={() => null}
  140. onSelect={onSelect}
  141. onInit={onInit}
  142. isConnected
  143. />
  144. )
  145. sinon.assert.calledOnce(onSelect)
  146. sinon.assert.calledWithMatch(onSelect, [
  147. sinon.match({
  148. entity: {
  149. _id: '456def',
  150. name: 'main.tex',
  151. },
  152. }),
  153. ])
  154. onSelect.reset()
  155. screen.queryByRole('tree')
  156. const treeitem = screen.getByRole('treeitem', { name: 'other.tex' })
  157. fireEvent.click(treeitem)
  158. sinon.assert.calledOnce(onSelect)
  159. sinon.assert.calledWithMatch(onSelect, [
  160. sinon.match({
  161. entity: {
  162. _id: '789ghi',
  163. name: 'other.tex',
  164. },
  165. }),
  166. ])
  167. })
  168. it('listen to editor.openDoc', function () {
  169. const rootFolder = [
  170. {
  171. _id: 'root-folder-id',
  172. docs: [
  173. { _id: '456def', name: 'main.tex' },
  174. { _id: '789ghi', name: 'other.tex' },
  175. ],
  176. folders: [],
  177. fileRefs: [],
  178. },
  179. ]
  180. render(
  181. <FileTreeRoot
  182. rootFolder={rootFolder}
  183. projectId="123abc"
  184. rootDocId="456def"
  185. hasWritePermissions={false}
  186. userHasFeature={() => true}
  187. refProviders={{}}
  188. reindexReferences={() => null}
  189. setRefProviderEnabled={() => null}
  190. setStartedFreeTrial={() => null}
  191. onSelect={onSelect}
  192. onInit={onInit}
  193. isConnected
  194. />
  195. )
  196. screen.getByRole('treeitem', { name: 'main.tex', selected: true })
  197. // entities not found should be ignored
  198. window.dispatchEvent(
  199. new CustomEvent('editor.openDoc', { detail: 'not-an-id' })
  200. )
  201. screen.getByRole('treeitem', { name: 'main.tex', selected: true })
  202. window.dispatchEvent(
  203. new CustomEvent('editor.openDoc', { detail: '789ghi' })
  204. )
  205. screen.getByRole('treeitem', { name: 'main.tex', selected: false })
  206. screen.getByRole('treeitem', { name: 'other.tex', selected: true })
  207. })
  208. })