CommonSectionCollapse.spec.ts 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. // Copyright (C) 2012-2024 Zammad Foundation, https://zammad-foundation.org/
  2. import { within } from '@testing-library/vue'
  3. import { ref, type Ref } from 'vue'
  4. import { renderComponent } from '#tests/support/components/index.ts'
  5. import { waitForNextTick } from '#tests/support/utils.ts'
  6. import CommonSectionCollapse, { type Props } from '../CommonSectionCollapse.vue'
  7. const html = String.raw
  8. const renderCommonSectionCollapse = (
  9. props: Partial<Props> = {},
  10. modelValue: Ref<boolean> | undefined = undefined,
  11. ) => {
  12. return renderComponent(CommonSectionCollapse, {
  13. props: {
  14. id: 'test-id',
  15. title: 'foobar',
  16. ...props,
  17. },
  18. vModel: {
  19. modelValue,
  20. },
  21. slots: {
  22. default: html` <template #default="{ headerId }">
  23. <nav :aria-labelledby="headerId" />
  24. </template>`,
  25. },
  26. store: true,
  27. })
  28. }
  29. describe('CommonSectionCollapse', () => {
  30. it('toggles content on heading click', async () => {
  31. const view = renderCommonSectionCollapse()
  32. expect(view.getByRole('navigation')).toBeInTheDocument()
  33. const header = view.getByRole('banner')
  34. const heading = within(header).getByRole('heading', { level: 3 })
  35. expect(heading).toHaveTextContent('foobar')
  36. await view.events.click(heading)
  37. expect(view.queryByRole('navigation')).not.toBeInTheDocument()
  38. })
  39. it('toggles content on button click', async () => {
  40. const view = renderCommonSectionCollapse()
  41. expect(view.getByRole('navigation')).toBeInTheDocument()
  42. const header = view.getByRole('banner')
  43. const button = within(header).getByRole('button')
  44. await view.events.click(button)
  45. expect(view.queryByRole('navigation')).not.toBeInTheDocument()
  46. })
  47. it('does not restore collapsed state', () => {
  48. const view = renderCommonSectionCollapse()
  49. expect(view.getByRole('navigation')).toBeInTheDocument()
  50. })
  51. it('provides a11y text to the default slot', () => {
  52. const view = renderCommonSectionCollapse({
  53. title: 'a11y',
  54. })
  55. expect(view.getByRole('navigation', { name: 'a11y' })).toBeInTheDocument()
  56. })
  57. it('supports no collapse (title only) mode', async () => {
  58. const view = renderCommonSectionCollapse({
  59. noCollapse: true,
  60. })
  61. expect(view.getByRole('navigation')).toBeInTheDocument()
  62. const header = view.getByRole('banner')
  63. const heading = within(header).getByRole('heading', { level: 3 })
  64. expect(heading).toHaveTextContent('foobar')
  65. expect(within(header).queryByRole('button')).not.toBeInTheDocument()
  66. await view.events.click(heading)
  67. expect(view.getByRole('navigation')).toBeInTheDocument()
  68. })
  69. it('supports hiding the header', async () => {
  70. const view = renderCommonSectionCollapse({
  71. noHeader: true,
  72. })
  73. expect(view.getByRole('navigation')).toBeInTheDocument()
  74. expect(view.queryByRole('banner')).not.toBeInTheDocument()
  75. })
  76. it('supports scrollable content mode', async () => {
  77. const view = renderCommonSectionCollapse({
  78. scrollable: true,
  79. })
  80. const header = view.getByRole('banner')
  81. expect(header.parentElement).toHaveClass('overflow-y-auto')
  82. const nav = view.getByRole('navigation')
  83. expect(nav.parentElement).toHaveClass('overflow-y-auto')
  84. await view.rerender({
  85. scrollable: false,
  86. })
  87. expect(header.parentElement).not.toHaveClass('overflow-y-auto')
  88. expect(nav.parentElement).not.toHaveClass('overflow-y-auto')
  89. })
  90. it('supports model value for the collapsed state', async () => {
  91. const modelValue = ref(false)
  92. const view = renderCommonSectionCollapse({}, modelValue)
  93. expect(view.getByRole('navigation')).toBeInTheDocument()
  94. modelValue.value = true
  95. await waitForNextTick()
  96. expect(view.queryByRole('navigation')).not.toBeInTheDocument()
  97. const header = view.getByRole('banner')
  98. const button = within(header).getByRole('button')
  99. await view.events.click(button)
  100. expect(modelValue.value).toBe(false)
  101. const heading = within(header).getByRole('heading', { level: 3 })
  102. await view.events.click(heading)
  103. expect(modelValue.value).toBe(true)
  104. })
  105. })