CommonSimpleTable.spec.ts 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  1. // Copyright (C) 2012-2024 Zammad Foundation, https://zammad-foundation.org/
  2. import { waitFor } from '@testing-library/vue'
  3. import { renderComponent } from '#tests/support/components/index.ts'
  4. import { i18n } from '#shared/i18n.ts'
  5. import type { MenuItem } from '#desktop/components/CommonPopoverMenu/types.ts'
  6. import CommonSimpleTable, { type Props } from '../CommonSimpleTable.vue'
  7. const tableHeaders = [
  8. {
  9. key: 'name',
  10. label: 'User name',
  11. },
  12. {
  13. key: 'role',
  14. label: 'Role',
  15. },
  16. ]
  17. const tableItems = [
  18. {
  19. id: 1,
  20. name: 'Lindsay Walton',
  21. role: 'Member',
  22. },
  23. ]
  24. const tableActions: MenuItem[] = [
  25. {
  26. key: 'download',
  27. label: 'Download this row',
  28. icon: 'download',
  29. },
  30. {
  31. key: 'delete',
  32. label: 'Delete this row',
  33. icon: 'trash3',
  34. },
  35. ]
  36. const renderTable = (props: Props, options = {}) => {
  37. return renderComponent(CommonSimpleTable, {
  38. ...options,
  39. props,
  40. })
  41. }
  42. beforeEach(() => {
  43. i18n.setTranslationMap(new Map([['Role', 'Rolle']]))
  44. })
  45. describe('CommonSimpleTable.vue', () => {
  46. it('displays the table without actions', async () => {
  47. const view = renderTable({
  48. headers: tableHeaders,
  49. items: tableItems,
  50. })
  51. expect(view.getByText('User name')).toBeInTheDocument()
  52. expect(view.getByText('Rolle')).toBeInTheDocument()
  53. expect(view.getByText('Lindsay Walton')).toBeInTheDocument()
  54. expect(view.getByText('Member')).toBeInTheDocument()
  55. expect(view.queryByText('Actions')).toBeNull()
  56. })
  57. it('displays the table with actions', async () => {
  58. const view = renderTable(
  59. {
  60. headers: tableHeaders,
  61. items: tableItems,
  62. actions: tableActions,
  63. },
  64. { router: true },
  65. )
  66. expect(view.getByText('Actions')).toBeInTheDocument()
  67. expect(view.getByLabelText('Action menu button')).toBeInTheDocument()
  68. })
  69. it('displays the additional data with the item suffix slot', async () => {
  70. const view = renderTable(
  71. {
  72. headers: tableHeaders,
  73. items: tableItems,
  74. actions: tableActions,
  75. },
  76. {
  77. router: true,
  78. slots: {
  79. 'item-suffix-role': '<span>Additional Example</span>',
  80. },
  81. },
  82. )
  83. expect(view.getByText('Additional Example')).toBeInTheDocument()
  84. })
  85. it('generates expected DOM', async () => {
  86. // TODO: check if such snapshot test is really the way we want to go.
  87. const view = renderTable(
  88. {
  89. headers: tableHeaders,
  90. items: tableItems,
  91. actions: tableActions,
  92. },
  93. // NB: Please don't remove this, otherwise snapshot would contain markup of many more components other than the
  94. // one under the test, which can lead to false positives.
  95. {
  96. shallow: true,
  97. },
  98. )
  99. expect(view.baseElement.querySelector('table')).toMatchFileSnapshot(
  100. `${__filename}.snapshot.txt`,
  101. )
  102. })
  103. it('supports text truncation in cell content', async () => {
  104. const view = renderTable({
  105. headers: [
  106. ...tableHeaders,
  107. {
  108. key: 'truncated',
  109. label: 'Truncated',
  110. truncate: true,
  111. },
  112. ],
  113. items: [
  114. ...tableItems,
  115. {
  116. id: 2,
  117. name: 'Max Mustermann',
  118. role: 'Admin',
  119. truncated: 'Some text to be truncated',
  120. },
  121. ],
  122. })
  123. const truncatedText = view.getByText('Some text to be truncated')
  124. expect(truncatedText.parentElement).toHaveClass('truncate')
  125. })
  126. it('supports tooltip on truncated cell content', async () => {
  127. const view = renderTable({
  128. headers: [
  129. ...tableHeaders,
  130. {
  131. key: 'truncated',
  132. label: 'Truncated',
  133. truncate: true,
  134. },
  135. ],
  136. items: [
  137. ...tableItems,
  138. {
  139. id: 2,
  140. name: 'Max Mustermann',
  141. role: 'Admin',
  142. truncated: 'Some text to be truncated',
  143. },
  144. ],
  145. })
  146. await view.events.hover(view.getByText('Max Mustermann'))
  147. await waitFor(() => {
  148. expect(view.getByText('Some text to be truncated')).toBeInTheDocument()
  149. expect(
  150. view.getByLabelText('Some text to be truncated'),
  151. ).toBeInTheDocument()
  152. })
  153. })
  154. })