CollapseButton.spec.ts 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  1. // Copyright (C) 2012-2024 Zammad Foundation, https://zammad-foundation.org/
  2. import { renderComponent } from '#tests/support/components/index.ts'
  3. import { EnumTextDirection } from '#shared/graphql/types.ts'
  4. import { useLocaleStore } from '#shared/stores/locale.ts'
  5. import CollapseButton from '#desktop/components/CollapseButton/CollapseButton.vue'
  6. describe('CollapseButton', () => {
  7. it.each([
  8. {
  9. isCollapsed: true,
  10. orientation: 'horizontal',
  11. inverse: false,
  12. icon: 'arrow-bar-right',
  13. },
  14. {
  15. isCollapsed: false,
  16. orientation: 'horizontal',
  17. inverse: false,
  18. icon: 'arrow-bar-left',
  19. },
  20. {
  21. isCollapsed: true,
  22. orientation: 'vertical',
  23. inverse: false,
  24. icon: 'arrows-expand',
  25. },
  26. {
  27. isCollapsed: false,
  28. orientation: 'vertical',
  29. inverse: false,
  30. icon: 'arrows-collapse',
  31. },
  32. {
  33. isCollapsed: true,
  34. orientation: 'horizontal',
  35. inverse: true,
  36. icon: 'arrow-bar-left',
  37. },
  38. {
  39. isCollapsed: false,
  40. orientation: 'horizontal',
  41. inverse: true,
  42. icon: 'arrow-bar-right',
  43. },
  44. {
  45. isCollapsed: true,
  46. orientation: 'vertical',
  47. inverse: true,
  48. icon: 'arrows-expand',
  49. },
  50. {
  51. isCollapsed: false,
  52. orientation: 'vertical',
  53. inverse: true,
  54. icon: 'arrows-collapse',
  55. },
  56. ])(
  57. 'displays correct LTR icon (isCollapsed: $isCollapsed, orientation: $orientation, inverse: $inverse)',
  58. async ({ isCollapsed, orientation, inverse, icon }) => {
  59. const wrapper = renderComponent(CollapseButton, {
  60. props: {
  61. ownerId: 'test',
  62. isCollapsed,
  63. inverse,
  64. orientation,
  65. },
  66. })
  67. expect(wrapper.getByIconName(icon)).toBeInTheDocument()
  68. },
  69. )
  70. it.each([
  71. {
  72. isCollapsed: true,
  73. orientation: 'horizontal',
  74. inverse: false,
  75. icon: 'arrow-bar-left',
  76. },
  77. {
  78. isCollapsed: false,
  79. orientation: 'horizontal',
  80. inverse: false,
  81. icon: 'arrow-bar-right',
  82. },
  83. {
  84. isCollapsed: true,
  85. orientation: 'vertical',
  86. inverse: false,
  87. icon: 'arrows-expand',
  88. },
  89. {
  90. isCollapsed: false,
  91. orientation: 'vertical',
  92. inverse: false,
  93. icon: 'arrows-collapse',
  94. },
  95. {
  96. isCollapsed: true,
  97. orientation: 'horizontal',
  98. inverse: true,
  99. icon: 'arrow-bar-right',
  100. },
  101. {
  102. isCollapsed: false,
  103. orientation: 'horizontal',
  104. inverse: true,
  105. icon: 'arrow-bar-left',
  106. },
  107. {
  108. isCollapsed: true,
  109. orientation: 'vertical',
  110. inverse: true,
  111. icon: 'arrows-expand',
  112. },
  113. {
  114. isCollapsed: false,
  115. orientation: 'vertical',
  116. inverse: true,
  117. icon: 'arrows-collapse',
  118. },
  119. ])(
  120. 'displays correct RTL icon (isCollapsed: $isCollapsed, orientation: $orientation, inverse: $inverse)',
  121. async ({ isCollapsed, orientation, inverse, icon }) => {
  122. const locale = useLocaleStore()
  123. locale.localeData = {
  124. dir: EnumTextDirection.Rtl,
  125. } as any
  126. const wrapper = renderComponent(CollapseButton, {
  127. props: {
  128. ownerId: 'test',
  129. isCollapsed,
  130. inverse,
  131. orientation,
  132. },
  133. })
  134. expect(wrapper.getByIconName(icon)).toBeInTheDocument()
  135. },
  136. )
  137. it('emits toggle-collapse event on click', async () => {
  138. const wrapper = renderComponent(CollapseButton, {
  139. props: {
  140. ownerId: 'test',
  141. isCollapsed: true,
  142. },
  143. })
  144. await wrapper.events.click(wrapper.getByRole('button'))
  145. expect(wrapper.emitted('toggle-collapse')).toBeTruthy()
  146. })
  147. it('renders the button by default', () => {
  148. const wrapper = renderComponent(CollapseButton, {
  149. props: {
  150. ownerId: 'test',
  151. },
  152. })
  153. expect(wrapper.getByRole('button')).toBeInTheDocument()
  154. })
  155. it('shows only on hover for non-touch devices', () => {
  156. const wrapper = renderComponent(CollapseButton, {
  157. props: {
  158. ownerId: 'test',
  159. group: 'sidebar',
  160. },
  161. })
  162. expect(wrapper.getByRole('button')).toHaveClasses([
  163. 'transition-opacity',
  164. 'opacity-0',
  165. ])
  166. })
  167. it('shows always for touch devices', () => {
  168. // Impersonate a touch device by mocking the corresponding media query.
  169. Object.defineProperty(window, 'matchMedia', {
  170. value: vi.fn().mockImplementation(() => ({
  171. matches: true,
  172. addEventListener: vi.fn(),
  173. removeEventListener: vi.fn(),
  174. })),
  175. })
  176. const wrapper = renderComponent(CollapseButton, {
  177. props: {
  178. ownerId: 'test',
  179. group: 'test',
  180. },
  181. })
  182. expect(wrapper.getByRole('button')).not.toHaveClasses([
  183. 'transition-opacity',
  184. 'opacity-0',
  185. 'group-hover/test:opacity-100',
  186. ])
  187. })
  188. })