LayoutSidebar.spec.ts 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  1. // Copyright (C) 2012-2024 Zammad Foundation, https://zammad-foundation.org/
  2. import { fireEvent } from '@testing-library/vue'
  3. import { beforeEach, describe, expect } from 'vitest'
  4. import renderComponent, {
  5. type ExtendedRenderResult,
  6. } from '#tests/support/components/renderComponent.ts'
  7. import LayoutSidebar from '#desktop/components/layout/LayoutSidebar.vue'
  8. import { SidebarPosition } from '../types.ts'
  9. describe('LayoutSidebar', () => {
  10. describe('Feature: Collapsible', () => {
  11. let view: ExtendedRenderResult
  12. beforeEach(() => {
  13. view = renderComponent(LayoutSidebar, {
  14. props: {
  15. name: 'testBar-collapsible',
  16. id: 'sidebar-test',
  17. collapsible: true,
  18. resizable: false,
  19. },
  20. })
  21. })
  22. it('shows CollapseButton in expanded state when collapsible is true', async () => {
  23. expect(
  24. view.queryByLabelText('Expand this element'),
  25. ).not.toBeInTheDocument()
  26. // By default, is expanded and aria label shows collapse action
  27. expect(view.queryByLabelText('Collapse this element')).toBeInTheDocument()
  28. })
  29. it('does not show CollapseButton when collapsible is false', async () => {
  30. await view.rerender({ collapsible: false })
  31. expect(
  32. view.queryByLabelText('collapse this item'),
  33. ).not.toBeInTheDocument()
  34. expect(view.queryByLabelText('expand this item')).not.toBeInTheDocument()
  35. })
  36. it('hides action Button when no iconCollapsed is provided', async () => {
  37. expect(view.queryByTestId('action-button')).not.toBeInTheDocument()
  38. })
  39. it('shows an action Button when iconCollapsed is provided and sidebar is collapsed', async () => {
  40. await view.rerender({ iconCollapsed: 'person-gear' })
  41. const collapseButton = await view.findByLabelText('Collapse this element')
  42. await view.events.click(collapseButton)
  43. expect(view.queryByTestId('action-button')).toBeInTheDocument()
  44. })
  45. it('hides collapse button if props is set and sidebar is collapsed', async () => {
  46. await view.rerender({ hideButtonWhenCollapsed: true })
  47. expect(
  48. view.queryByLabelText('Expand this element'),
  49. ).not.toBeInTheDocument()
  50. })
  51. })
  52. describe('Feature: Resizable', () => {
  53. let view: ExtendedRenderResult
  54. beforeEach(() => {
  55. view = renderComponent(LayoutSidebar, {
  56. props: {
  57. name: 'testBar-resize',
  58. id: 'sidebar-test',
  59. collapsible: false,
  60. resizable: true,
  61. },
  62. })
  63. })
  64. it('shows ResizeHandle when resizable is true', async () => {
  65. expect(view.queryByLabelText('Resize sidebar')).toBeInTheDocument()
  66. })
  67. it('does not show ResizeHandle when resizable is false', async () => {
  68. await view.rerender({ resizable: false })
  69. expect(view.queryByLabelText('Resize sidebar')).not.toBeInTheDocument()
  70. })
  71. it('resizes sidebar when ResizeHandle is clicked and dragged', async () => {
  72. const resizeHandle = await view.findByLabelText('Resize sidebar')
  73. await view.events.click(resizeHandle)
  74. // Emulate mouse down on resize handle and mouse move on document
  75. await fireEvent.mouseDown(resizeHandle, { clientX: 0 })
  76. await fireEvent.mouseMove(document, { clientX: 100 })
  77. await fireEvent.mouseUp(document, { clientX: 100 })
  78. expect(view.emitted('resize-horizontal')).toEqual([[100]])
  79. })
  80. it('resizes sidebar when ResizeHandle is touched and dragged', async () => {
  81. const resizeHandle = await view.findByLabelText('Resize sidebar')
  82. await view.events.click(resizeHandle)
  83. // Touch device
  84. await fireEvent.touchStart(resizeHandle, { pageX: 0 })
  85. await fireEvent.touchMove(document, { pageX: 100 })
  86. await fireEvent.touchEnd(document, { pageX: 100 })
  87. // :TODO check why we can not use toEqual([[100]])
  88. expect(view.emitted('resize-horizontal')).toBeTruthy()
  89. })
  90. it('resets width when ResizeHandle is double clicked', async () => {
  91. const resizeHandle = await view.findByLabelText('Resize sidebar')
  92. await fireEvent.dblClick(resizeHandle)
  93. expect(view.emitted('reset-width')).toBeTruthy()
  94. })
  95. it('hides ResizeHandle when sidebar is collapsed', async () => {
  96. await view.rerender({ collapsible: true })
  97. const collapseButton = await view.findByLabelText('Collapse this element')
  98. await view.events.click(collapseButton)
  99. expect(view.queryByLabelText('Resize sidebar')).not.toBeInTheDocument()
  100. })
  101. })
  102. describe('Feature: Position', () => {
  103. let view: ExtendedRenderResult
  104. beforeEach(() => {
  105. view = renderComponent(LayoutSidebar, {
  106. props: {
  107. name: 'testBar-position',
  108. id: 'sidebar-test',
  109. collapsible: true,
  110. resizable: true,
  111. },
  112. })
  113. })
  114. it('defaults to start position (left)', async () => {
  115. const aside = view.getByRole('complementary')
  116. expect(aside).toHaveClass('border-e')
  117. const collapseButton = view.getByLabelText('Collapse this element')
  118. expect(collapseButton.parentElement).toHaveClasses([
  119. 'ltr:right-0',
  120. 'ltr:translate-x-1/2',
  121. 'rtl:left-0',
  122. 'rtl:-translate-x-1/2',
  123. ])
  124. const resizeHandle = view.getByLabelText('Resize sidebar')
  125. expect(resizeHandle).toHaveClasses(['ltr:right-0', 'rtl:left-0'])
  126. })
  127. it('supports end position (right)', async () => {
  128. await view.rerender({ position: SidebarPosition.End })
  129. const aside = view.getByRole('complementary')
  130. expect(aside).toHaveClass('border-s')
  131. const collapseButton = view.getByLabelText('Collapse this element')
  132. expect(collapseButton.parentElement).toHaveClasses([
  133. 'ltr:left-0',
  134. 'ltr:-translate-x-1/2',
  135. 'rtl:right-0',
  136. 'rtl:translate-x-1/2',
  137. ])
  138. const resizeHandle = view.getByLabelText('Resize sidebar')
  139. expect(resizeHandle).toHaveClasses(['ltr:left-0', 'rtl:right-0'])
  140. })
  141. })
  142. })