layout-dropdown-button.test.jsx 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229
  1. import sinon from 'sinon'
  2. import fetchMock from 'fetch-mock'
  3. import { expect } from 'chai'
  4. import { screen, waitFor } from '@testing-library/react'
  5. import LayoutDropdownButton from '../../../../../frontend/js/features/editor-navigation-toolbar/components/layout-dropdown-button'
  6. import { renderWithEditorContext } from '../../../helpers/render-with-context'
  7. import * as eventTracking from '@/infrastructure/event-tracking'
  8. describe('<LayoutDropdownButton />', function () {
  9. let openStub
  10. let sendMBSpy
  11. const defaultUi = {
  12. pdfLayout: 'flat',
  13. view: 'pdf',
  14. }
  15. beforeEach(function () {
  16. openStub = sinon.stub(window, 'open')
  17. sendMBSpy = sinon.spy(eventTracking, 'sendMB')
  18. })
  19. afterEach(function () {
  20. openStub.restore()
  21. sendMBSpy.restore()
  22. fetchMock.removeRoutes().clearHistory()
  23. })
  24. it('should mark current layout option as selected', async function () {
  25. // Selected is aria-label, visually we show a checkmark
  26. renderWithEditorContext(<LayoutDropdownButton />, { ui: defaultUi })
  27. screen.getByRole('button', { name: 'Layout' }).click()
  28. await waitFor(() =>
  29. expect(
  30. screen
  31. .getByRole('menuitem', {
  32. name: 'Editor & PDF',
  33. })
  34. .getAttribute('aria-selected')
  35. ).to.equal('false')
  36. )
  37. expect(
  38. screen
  39. .getByRole('menuitem', {
  40. name: 'PDF only (hide editor)',
  41. })
  42. .getAttribute('aria-selected')
  43. ).to.equal('true')
  44. expect(
  45. screen
  46. .getByRole('menuitem', {
  47. name: 'Editor only (hide PDF)',
  48. })
  49. .getAttribute('aria-selected')
  50. ).to.equal('false')
  51. expect(
  52. screen
  53. .getByRole('menuitem', {
  54. name: 'PDF in separate tab',
  55. })
  56. .getAttribute('aria-selected')
  57. ).to.equal('false')
  58. })
  59. it('should not select any option in history view', async function () {
  60. // Selected is aria-label, visually we show a checkmark
  61. renderWithEditorContext(<LayoutDropdownButton />, {
  62. ui: { ...defaultUi, view: 'history' },
  63. })
  64. screen.getByRole('button', { name: 'Layout' }).click()
  65. await waitFor(() =>
  66. expect(
  67. screen
  68. .getByRole('menuitem', {
  69. name: 'Editor & PDF',
  70. })
  71. .getAttribute('aria-selected')
  72. ).to.equal('false')
  73. )
  74. expect(
  75. screen
  76. .getByRole('menuitem', {
  77. name: 'PDF only (hide editor)',
  78. })
  79. .getAttribute('aria-selected')
  80. ).to.equal('false')
  81. expect(
  82. screen
  83. .getByRole('menuitem', {
  84. name: 'Editor only (hide PDF)',
  85. })
  86. .getAttribute('aria-selected')
  87. ).to.equal('false')
  88. expect(
  89. screen
  90. .getByRole('menuitem', {
  91. name: 'PDF in separate tab',
  92. })
  93. .getAttribute('aria-selected')
  94. ).to.equal('false')
  95. })
  96. it('should treat file and editor views the same way', async function () {
  97. // Selected is aria-label, visually we show a checkmark
  98. renderWithEditorContext(<LayoutDropdownButton />, {
  99. ui: {
  100. pdfLayout: 'flat',
  101. view: 'file',
  102. },
  103. })
  104. screen.getByRole('button', { name: 'Layout' }).click()
  105. await waitFor(() =>
  106. expect(
  107. screen
  108. .getByRole('menuitem', {
  109. name: 'Editor & PDF',
  110. })
  111. .getAttribute('aria-selected')
  112. ).to.equal('false')
  113. )
  114. expect(
  115. screen
  116. .getByRole('menuitem', {
  117. name: 'PDF only (hide editor)',
  118. })
  119. .getAttribute('aria-selected')
  120. ).to.equal('false')
  121. expect(
  122. screen
  123. .getByRole('menuitem', {
  124. name: 'Editor only (hide PDF)',
  125. })
  126. .getAttribute('aria-selected')
  127. ).to.equal('true')
  128. expect(
  129. screen
  130. .getByRole('menuitem', {
  131. name: 'PDF in separate tab',
  132. })
  133. .getAttribute('aria-selected')
  134. ).to.equal('false')
  135. })
  136. describe('on detach', async function () {
  137. let originalBroadcastChannel
  138. beforeEach(async function () {
  139. window.BroadcastChannel = originalBroadcastChannel || true // ensure that window.BroadcastChannel is truthy
  140. renderWithEditorContext(<LayoutDropdownButton />, {
  141. ui: { ...defaultUi, view: 'editor' },
  142. })
  143. screen.getByRole('button', { name: 'Layout' }).click()
  144. await waitFor(() =>
  145. screen
  146. .getByRole('menuitem', {
  147. name: 'PDF in separate tab',
  148. })
  149. .click()
  150. )
  151. })
  152. afterEach(function () {
  153. window.BroadcastChannel = originalBroadcastChannel
  154. })
  155. it('should show processing', async function () {
  156. await screen.findByText('Layout processing')
  157. })
  158. it('should record event', function () {
  159. sinon.assert.calledWith(sendMBSpy, 'project-layout-detach')
  160. })
  161. })
  162. describe('on layout change / reattach', async function () {
  163. beforeEach(async function () {
  164. window.metaAttributesCache.set('ol-detachRole', 'detacher')
  165. renderWithEditorContext(<LayoutDropdownButton />, {
  166. ui: { ...defaultUi, view: 'editor' },
  167. })
  168. screen.getByRole('button', { name: 'Layout' }).click()
  169. await waitFor(() =>
  170. screen
  171. .getByRole('menuitem', {
  172. name: 'Editor only (hide PDF)',
  173. })
  174. .click()
  175. )
  176. })
  177. it('should not show processing', function () {
  178. const processingText = screen.queryByText('Layout processing')
  179. expect(processingText).to.not.exist
  180. })
  181. it('should record events', function () {
  182. sinon.assert.calledWith(sendMBSpy, 'project-layout-reattach')
  183. sinon.assert.calledWith(sendMBSpy, 'project-layout-change', {
  184. layout: 'flat',
  185. view: 'editor',
  186. page: '/detacher',
  187. })
  188. })
  189. it('should select new menu item', function () {
  190. screen.getByRole('menuitem', {
  191. name: 'Editor only (hide PDF)',
  192. })
  193. })
  194. })
  195. })