CommonSimpleTable.spec.ts 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  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/CommonPopover/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. headers: tableHeaders,
  60. items: tableItems,
  61. actions: tableActions,
  62. })
  63. expect(view.getByText('Actions')).toBeInTheDocument()
  64. expect(view.getByLabelText('Action menu button')).toBeInTheDocument()
  65. })
  66. it('displays the additional data with the item suffix slot', async () => {
  67. const view = renderTable(
  68. {
  69. headers: tableHeaders,
  70. items: tableItems,
  71. actions: tableActions,
  72. },
  73. {
  74. slots: {
  75. 'item-suffix-role': '<span>Additional Example</span>',
  76. },
  77. },
  78. )
  79. expect(view.getByText('Additional Example')).toBeInTheDocument()
  80. })
  81. it('generates expected DOM', async () => {
  82. // TODO: check if such snapshot test is really the way we want to go.
  83. const view = renderTable(
  84. {
  85. headers: tableHeaders,
  86. items: tableItems,
  87. actions: tableActions,
  88. },
  89. // NB: Please don't remove this, otherwise snapshot would contain markup of many more components other than the
  90. // one under the test, which can lead to false positives.
  91. {
  92. shallow: true,
  93. },
  94. )
  95. expect(view.baseElement.querySelector('table')).toMatchFileSnapshot(
  96. `${__filename}.snapshot.txt`,
  97. )
  98. })
  99. it('supports text truncation in cell content', async () => {
  100. const view = renderTable({
  101. headers: [
  102. ...tableHeaders,
  103. {
  104. key: 'truncated',
  105. label: 'Truncated',
  106. truncate: true,
  107. },
  108. ],
  109. items: [
  110. ...tableItems,
  111. {
  112. id: 2,
  113. name: 'Max Mustermann',
  114. role: 'Admin',
  115. truncated: 'Some text to be truncated',
  116. },
  117. ],
  118. })
  119. const truncatedText = view.getByText('Some text to be truncated')
  120. expect(truncatedText.parentElement).toHaveClass('truncate')
  121. })
  122. it('supports tooltip on truncated cell content', async () => {
  123. const view = renderTable({
  124. headers: [
  125. ...tableHeaders,
  126. {
  127. key: 'truncated',
  128. label: 'Truncated',
  129. truncate: true,
  130. },
  131. ],
  132. items: [
  133. ...tableItems,
  134. {
  135. id: 2,
  136. name: 'Max Mustermann',
  137. role: 'Admin',
  138. truncated: 'Some text to be truncated',
  139. },
  140. ],
  141. })
  142. await view.events.hover(view.getByText('Max Mustermann'))
  143. await waitFor(() => {
  144. expect(view.getByText('Some text to be truncated')).toBeInTheDocument()
  145. expect(
  146. view.getByLabelText('Some text to be truncated'),
  147. ).toBeInTheDocument()
  148. })
  149. })
  150. })