use-detach-layout.test.js 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208
  1. import { act } from '@testing-library/react-hooks'
  2. import { expect } from 'chai'
  3. import sinon from 'sinon'
  4. import { renderHookWithEditorContext } from '../../helpers/render-with-context'
  5. import sysendTestHelper from '../../helpers/sysend'
  6. import useDetachLayout from '../../../../frontend/js/shared/hooks/use-detach-layout'
  7. describe('useDetachLayout', function () {
  8. let openStub
  9. let closeStub
  10. beforeEach(function () {
  11. window.metaAttributesCache = new Map()
  12. openStub = sinon.stub(window, 'open')
  13. closeStub = sinon.stub(window, 'close')
  14. })
  15. afterEach(function () {
  16. window.metaAttributesCache = new Map()
  17. openStub.restore()
  18. closeStub.restore()
  19. })
  20. it('detaching', async function () {
  21. // 1. create hook in normal mode
  22. const { result } = renderHookWithEditorContext(() => useDetachLayout())
  23. expect(result.current.reattach).to.be.a('function')
  24. expect(result.current.detach).to.be.a('function')
  25. expect(result.current.isLinked).to.be.false
  26. expect(result.current.isLinking).to.be.false
  27. expect(result.current.role).to.be.null
  28. // 2. detach
  29. act(() => {
  30. result.current.detach()
  31. })
  32. expect(result.current.isLinked).to.be.false
  33. expect(result.current.isLinking).to.be.true
  34. expect(result.current.role).to.equal('detacher')
  35. sinon.assert.calledOnce(openStub)
  36. sinon.assert.calledWith(
  37. openStub,
  38. 'https://www.test-overleaf.com/detached',
  39. '_blank'
  40. )
  41. })
  42. it('detacher role', async function () {
  43. sysendTestHelper.spy.broadcast.resetHistory()
  44. window.metaAttributesCache.set('ol-detachRole', 'detacher')
  45. // 1. create hook in detacher mode
  46. const { result } = renderHookWithEditorContext(() => useDetachLayout())
  47. expect(result.current.reattach).to.be.a('function')
  48. expect(result.current.detach).to.be.a('function')
  49. expect(result.current.isLinked).to.be.false
  50. expect(result.current.isLinking).to.be.false
  51. expect(result.current.role).to.equal('detacher')
  52. const broadcastMessagesCount =
  53. sysendTestHelper.getAllBroacastMessages().length
  54. // 2. simulate connected detached tab
  55. sysendTestHelper.spy.broadcast.resetHistory()
  56. sysendTestHelper.receiveMessage({
  57. role: 'detached',
  58. event: 'connected',
  59. })
  60. expect(sysendTestHelper.getLastBroacastMessage()).to.deep.equal({
  61. role: 'detacher',
  62. event: 'up',
  63. })
  64. expect(result.current.isLinked).to.be.true
  65. expect(result.current.isLinking).to.be.false
  66. expect(result.current.role).to.equal('detacher')
  67. // check that all message were re-broadcast for the new tab
  68. await nextTick() // necessary to ensure all event handler have run
  69. const reBroadcastMessagesCount =
  70. sysendTestHelper.getAllBroacastMessages().length
  71. expect(reBroadcastMessagesCount).to.equal(broadcastMessagesCount)
  72. // 3. simulate closed detached tab
  73. sysendTestHelper.spy.broadcast.resetHistory()
  74. sysendTestHelper.receiveMessage({
  75. role: 'detached',
  76. event: 'closed',
  77. })
  78. expect(result.current.isLinked).to.be.false
  79. expect(result.current.isLinking).to.be.false
  80. expect(result.current.role).to.equal('detacher')
  81. // 4. simulate up detached tab
  82. sysendTestHelper.spy.broadcast.resetHistory()
  83. sysendTestHelper.receiveMessage({
  84. role: 'detached',
  85. event: 'up',
  86. })
  87. expect(result.current.isLinked).to.be.true
  88. expect(result.current.isLinking).to.be.false
  89. expect(result.current.role).to.equal('detacher')
  90. // 5. reattach
  91. sysendTestHelper.spy.broadcast.resetHistory()
  92. act(() => {
  93. result.current.reattach()
  94. })
  95. expect(result.current.isLinked).to.be.false
  96. expect(result.current.isLinking).to.be.false
  97. expect(result.current.role).to.be.null
  98. expect(sysendTestHelper.getLastBroacastMessage()).to.deep.equal({
  99. role: 'detacher',
  100. event: 'reattach',
  101. })
  102. })
  103. it('reset detacher role when other detacher tab connects', function () {
  104. window.metaAttributesCache.set('ol-detachRole', 'detacher')
  105. // 1. create hook in detacher mode
  106. const { result } = renderHookWithEditorContext(() => useDetachLayout())
  107. expect(result.current.reattach).to.be.a('function')
  108. expect(result.current.detach).to.be.a('function')
  109. expect(result.current.isLinked).to.be.false
  110. expect(result.current.isLinking).to.be.false
  111. expect(result.current.role).to.equal('detacher')
  112. // 2. simulate other detacher tab
  113. sysendTestHelper.receiveMessage({
  114. role: 'detacher',
  115. event: 'up',
  116. })
  117. expect(result.current.isRedundant).to.be.true
  118. expect(result.current.role).to.equal(null)
  119. })
  120. it('detached role', async function () {
  121. window.metaAttributesCache.set('ol-detachRole', 'detached')
  122. // 1. create hook in detached mode
  123. const { result } = renderHookWithEditorContext(() => useDetachLayout())
  124. expect(result.current.reattach).to.be.a('function')
  125. expect(result.current.detach).to.be.a('function')
  126. expect(result.current.isLinked).to.be.false
  127. expect(result.current.isLinking).to.be.false
  128. expect(result.current.role).to.equal('detached')
  129. // 2. simulate up detacher tab
  130. sysendTestHelper.spy.broadcast.resetHistory()
  131. sysendTestHelper.receiveMessage({
  132. role: 'detacher',
  133. event: 'up',
  134. })
  135. expect(result.current.isLinked).to.be.true
  136. expect(result.current.isLinking).to.be.false
  137. expect(result.current.role).to.equal('detached')
  138. // 3. simulate closed detacher tab
  139. sysendTestHelper.spy.broadcast.resetHistory()
  140. sysendTestHelper.receiveMessage({
  141. role: 'detacher',
  142. event: 'closed',
  143. })
  144. expect(result.current.isLinked).to.be.false
  145. expect(result.current.isLinking).to.be.false
  146. expect(result.current.role).to.equal('detached')
  147. // 4. simulate up detacher tab
  148. sysendTestHelper.spy.broadcast.resetHistory()
  149. sysendTestHelper.receiveMessage({
  150. role: 'detacher',
  151. event: 'up',
  152. })
  153. expect(result.current.isLinked).to.be.true
  154. expect(result.current.isLinking).to.be.false
  155. expect(result.current.role).to.equal('detached')
  156. // 5. simulate closed detached tab
  157. sysendTestHelper.spy.broadcast.resetHistory()
  158. sysendTestHelper.receiveMessage({
  159. role: 'detached',
  160. event: 'closed',
  161. })
  162. expect(result.current.isLinked).to.be.true
  163. expect(result.current.isLinking).to.be.false
  164. expect(result.current.role).to.equal('detached')
  165. expect(sysendTestHelper.getLastBroacastMessage()).to.deep.equal({
  166. role: 'detached',
  167. event: 'up',
  168. })
  169. // 6. simulate reattach event
  170. sysendTestHelper.spy.broadcast.resetHistory()
  171. sysendTestHelper.receiveMessage({
  172. role: 'detacher',
  173. event: 'reattach',
  174. })
  175. expect(result.current.isLinked).to.be.false
  176. expect(result.current.isLinking).to.be.false
  177. expect(result.current.role).to.equal('detached')
  178. sinon.assert.called(closeStub)
  179. })
  180. })
  181. const nextTick = () => {
  182. return new Promise(resolve => {
  183. setTimeout(resolve)
  184. })
  185. }