file-tree-root.test.js 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  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 deleteButton = screen.getByRole('menuitem', { name: 'Delete' })
  85. fireEvent.click(deleteButton)
  86. await waitFor(() => screen.getByRole('button', { name: 'Cancel' }))
  87. })
  88. it('renders disconnected overlay', function() {
  89. const rootFolder = [
  90. {
  91. _id: 'root-folder-id',
  92. docs: [{ _id: '456def', name: 'main.tex' }],
  93. folders: [],
  94. fileRefs: []
  95. }
  96. ]
  97. const { container } = render(
  98. <FileTreeRoot
  99. rootFolder={rootFolder}
  100. projectId="123abc"
  101. hasWritePermissions={false}
  102. rootDocId="456def"
  103. onSelect={onSelect}
  104. onInit={onInit}
  105. isConnected={false}
  106. userHasFeature={() => true}
  107. refProviders={{}}
  108. reindexReferences={() => null}
  109. setRefProviderEnabled={() => null}
  110. setStartedFreeTrial={() => null}
  111. />
  112. )
  113. expect(container.querySelector('.disconnected-overlay')).to.exist
  114. })
  115. it('fire onSelect', function() {
  116. const rootFolder = [
  117. {
  118. _id: 'root-folder-id',
  119. docs: [
  120. { _id: '456def', name: 'main.tex' },
  121. { _id: '789ghi', name: 'other.tex' }
  122. ],
  123. folders: [],
  124. fileRefs: []
  125. }
  126. ]
  127. render(
  128. <FileTreeRoot
  129. rootFolder={rootFolder}
  130. projectId="123abc"
  131. rootDocId="456def"
  132. hasWritePermissions={false}
  133. userHasFeature={() => true}
  134. refProviders={{}}
  135. reindexReferences={() => null}
  136. setRefProviderEnabled={() => null}
  137. setStartedFreeTrial={() => null}
  138. onSelect={onSelect}
  139. onInit={onInit}
  140. isConnected
  141. />
  142. )
  143. sinon.assert.calledOnce(onSelect)
  144. sinon.assert.calledWithMatch(onSelect, [
  145. sinon.match({
  146. entity: {
  147. _id: '456def',
  148. name: 'main.tex'
  149. }
  150. })
  151. ])
  152. onSelect.reset()
  153. screen.queryByRole('tree')
  154. const treeitem = screen.getByRole('treeitem', { name: 'other.tex' })
  155. fireEvent.click(treeitem)
  156. sinon.assert.calledOnce(onSelect)
  157. sinon.assert.calledWithMatch(onSelect, [
  158. sinon.match({
  159. entity: {
  160. _id: '789ghi',
  161. name: 'other.tex'
  162. }
  163. })
  164. ])
  165. })
  166. it('listen to editor.openDoc', function() {
  167. const rootFolder = [
  168. {
  169. _id: 'root-folder-id',
  170. docs: [
  171. { _id: '456def', name: 'main.tex' },
  172. { _id: '789ghi', name: 'other.tex' }
  173. ],
  174. folders: [],
  175. fileRefs: []
  176. }
  177. ]
  178. render(
  179. <FileTreeRoot
  180. rootFolder={rootFolder}
  181. projectId="123abc"
  182. rootDocId="456def"
  183. hasWritePermissions={false}
  184. userHasFeature={() => true}
  185. refProviders={{}}
  186. reindexReferences={() => null}
  187. setRefProviderEnabled={() => null}
  188. setStartedFreeTrial={() => null}
  189. onSelect={onSelect}
  190. onInit={onInit}
  191. isConnected
  192. />
  193. )
  194. screen.getByRole('treeitem', { name: 'main.tex', selected: true })
  195. // entities not found should be ignored
  196. window.dispatchEvent(
  197. new CustomEvent('editor.openDoc', { detail: 'not-an-id' })
  198. )
  199. screen.getByRole('treeitem', { name: 'main.tex', selected: true })
  200. window.dispatchEvent(
  201. new CustomEvent('editor.openDoc', { detail: '789ghi' })
  202. )
  203. screen.getByRole('treeitem', { name: 'main.tex', selected: false })
  204. screen.getByRole('treeitem', { name: 'other.tex', selected: true })
  205. })
  206. })