NavigationMenu.spec.ts 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. // Copyright (C) 2012-2024 Zammad Foundation, https://zammad-foundation.org/
  2. import { renderComponent } from '#tests/support/components/index.ts'
  3. import type { ExtendedRenderResult } from '#tests/support/components/index.ts'
  4. import { waitForNextTick } from '#tests/support/utils.ts'
  5. import NavigationMenu from '../NavigationMenu.vue'
  6. const renderMenu = () => {
  7. return renderComponent(NavigationMenu, {
  8. props: {
  9. categories: [
  10. {
  11. label: 'Personal',
  12. id: 'category-personal',
  13. order: 10,
  14. },
  15. {
  16. label: 'Security',
  17. id: 'category-security',
  18. order: 20,
  19. },
  20. ],
  21. entries: {
  22. Personal: [
  23. {
  24. label: 'Downloads',
  25. keywords: 'Ačiū',
  26. route: { name: '' },
  27. },
  28. {
  29. label: 'Calls',
  30. keywords: 'Another,Keyword',
  31. route: { name: '' },
  32. },
  33. ],
  34. Security: [
  35. {
  36. label: 'Devices',
  37. route: { name: '' },
  38. },
  39. {
  40. label: 'Sessions',
  41. route: { name: '' },
  42. },
  43. ],
  44. },
  45. },
  46. router: true,
  47. })
  48. }
  49. describe('menu', () => {
  50. it('renders the menu', async () => {
  51. const view = renderMenu()
  52. expect(view.getByText('Personal')).toBeInTheDocument()
  53. expect(view.getByText('Downloads')).toBeInTheDocument()
  54. expect(view.getByText('Calls')).toBeInTheDocument()
  55. expect(view.getByText('Security')).toBeInTheDocument()
  56. expect(view.getByText('Devices')).toBeInTheDocument()
  57. expect(view.getByText('Sessions')).toBeInTheDocument()
  58. })
  59. it('supports collapsing sections', async () => {
  60. const view = renderMenu()
  61. const collapseButton = view.getAllByLabelText('Collapse this element').at(0)
  62. expect(view.queryByText('Personal')).toBeInTheDocument()
  63. await view.events.click(collapseButton as HTMLElement)
  64. expect(view.queryByText('Downloads')).not.toBeVisible()
  65. expect(view.queryByText('Calls')).not.toBeVisible()
  66. })
  67. })
  68. describe('menu filtering', () => {
  69. const filterBy = async (view: ExtendedRenderResult, input: string) => {
  70. view.getByText('apply filter').click()
  71. await waitForNextTick()
  72. await view.events.type(view.getByRole('searchbox'), input)
  73. await waitForNextTick()
  74. }
  75. it('filters the menu entries list', async () => {
  76. const view = renderMenu()
  77. await filterBy(view, 'es')
  78. expect(view.queryByText('Downloads')).not.toBeInTheDocument()
  79. expect(view.queryByText('Calls')).not.toBeInTheDocument()
  80. expect(view.queryByText('Devices')).toBeInTheDocument()
  81. expect(view.queryByText('Sessions')).toBeInTheDocument()
  82. })
  83. it('does not show categories when filtering', async () => {
  84. const view = renderMenu()
  85. await filterBy(view, 'es')
  86. expect(view.queryByText('Personal')).not.toBeInTheDocument()
  87. expect(view.queryByText('Security')).not.toBeInTheDocument()
  88. })
  89. it('filters the list by keyword', async () => {
  90. const view = renderMenu()
  91. await filterBy(view, 'Keyword')
  92. expect(view.queryByText('Calls')).toBeInTheDocument()
  93. expect(view.queryByText('Downloads')).not.toBeInTheDocument()
  94. expect(view.queryByText('Devices')).not.toBeInTheDocument()
  95. expect(view.queryByText('Sessions')).not.toBeInTheDocument()
  96. })
  97. it('allows any case and skips diacritics', async () => {
  98. const view = renderMenu()
  99. await filterBy(view, 'ąciu')
  100. expect(view.queryByText('Downloads')).toBeInTheDocument()
  101. expect(view.queryByText('Calls')).not.toBeInTheDocument()
  102. expect(view.queryByText('Devices')).not.toBeInTheDocument()
  103. expect(view.queryByText('Sessions')).not.toBeInTheDocument()
  104. })
  105. it('shows empty list if nothing matches the search', async () => {
  106. const view = renderMenu()
  107. await filterBy(view, 'nonexistantkeyword')
  108. expect(view.queryByText('Downloads')).not.toBeInTheDocument()
  109. expect(view.queryByText('Calls')).not.toBeInTheDocument()
  110. expect(view.queryByText('Devices')).not.toBeInTheDocument()
  111. expect(view.queryByText('Sessions')).not.toBeInTheDocument()
  112. })
  113. it('goes back to categorized view', async () => {
  114. const view = renderMenu()
  115. await filterBy(view, 'nonexistantkeyword')
  116. expect(view.queryByText('apply filter')).not.toBeInTheDocument()
  117. expect(view.queryByText('Personal')).not.toBeInTheDocument()
  118. view.getByLabelText('Clear filter').click()
  119. await waitForNextTick()
  120. expect(view.queryByText('apply filter')).toBeInTheDocument()
  121. expect(view.queryByText('Personal')).toBeInTheDocument()
  122. })
  123. })