roving-focus-group.test.ts 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. // @ts-nocheck
  2. import { defineComponent, h, inject, nextTick } from 'vue'
  3. import { mount } from '@vue/test-utils'
  4. import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
  5. import { COLLECTION_ITEM_SIGN } from '@element-plus/components/collection'
  6. import { composeRefs } from '@element-plus/utils'
  7. import ElRovingFocusGroup from '../src/roving-focus-group.vue'
  8. import { ROVING_FOCUS_GROUP_INJECTION_KEY } from '../src/tokens'
  9. import { ROVING_FOCUS_COLLECTION_INJECTION_KEY } from '../src/roving-focus-group'
  10. const AXIOM = 'rem is the best girl'
  11. const RovingFocusGroupChild = defineComponent({
  12. setup() {
  13. const rovingFocusGroupInjection = inject(
  14. ROVING_FOCUS_GROUP_INJECTION_KEY,
  15. undefined
  16. )!
  17. const { itemMap, collectionRef } = inject(
  18. ROVING_FOCUS_COLLECTION_INJECTION_KEY,
  19. undefined
  20. )!
  21. Array.from({
  22. length: 3,
  23. }).forEach((_, id) => {
  24. const div = document.createElement('div')
  25. div.id = id.toString()
  26. itemMap.set(div, {
  27. ref: div,
  28. focusable: true,
  29. active: false,
  30. id: id.toString(),
  31. })
  32. })
  33. const composedRef = composeRefs(
  34. rovingFocusGroupInjection.rovingFocusGroupRef,
  35. collectionRef
  36. )
  37. return {
  38. ...rovingFocusGroupInjection,
  39. composedRef,
  40. }
  41. },
  42. template: `<div
  43. :ref="composedRef"
  44. :tabindex="tabIndex"
  45. @blur="onBlur"
  46. @focus="onFocus"
  47. @mousedown="onMousedown"
  48. >
  49. <template v-for="i in 3">
  50. <div class="${COLLECTION_ITEM_SIGN}">
  51. ${AXIOM} {{ i }}
  52. </div>
  53. </template>
  54. </div>`,
  55. })
  56. const onFocus = vi.fn()
  57. const onBlur = vi.fn()
  58. const onMousedown = vi.fn()
  59. describe('<ElRovingFocusGroup />', () => {
  60. const createComponent = (
  61. props = {
  62. onFocus,
  63. onBlur,
  64. onMousedown,
  65. }
  66. ) =>
  67. mount(ElRovingFocusGroup, {
  68. props,
  69. slots: {
  70. default: () => h(RovingFocusGroupChild),
  71. },
  72. })
  73. let wrapper: ReturnType<typeof createComponent>
  74. const findChild = () => wrapper.findComponent(RovingFocusGroupChild)
  75. beforeEach(async () => {
  76. wrapper = createComponent()
  77. await nextTick()
  78. })
  79. afterEach(() => {
  80. wrapper.unmount()
  81. })
  82. it('should be able to render', () => {
  83. expect(wrapper.html()).toContain(AXIOM)
  84. expect(findChild().attributes('tabindex')).toBe('0')
  85. })
  86. it('should be able to control current tab', async () => {
  87. const child = findChild()
  88. expect(child.vm.currentTabbedId).toBe(null)
  89. const currentTabId = 'test_id'
  90. await wrapper.setProps({
  91. currentTabId,
  92. })
  93. expect(child.vm.currentTabbedId).toBe(currentTabId)
  94. })
  95. it('should be able to combine style', async () => {
  96. const style = {
  97. position: 'absolute',
  98. }
  99. await wrapper.setProps({
  100. style,
  101. })
  102. const child = findChild()
  103. expect(child.vm.rovingFocusGroupRootStyle).toHaveLength(2)
  104. expect(child.vm.rovingFocusGroupRootStyle[1]).toEqual(style)
  105. })
  106. describe('provides', () => {
  107. it('should provide onFocus and onBlur event for children', async () => {
  108. expect(onFocus).not.toHaveBeenCalled()
  109. expect(onBlur).not.toHaveBeenCalled()
  110. const child = findChild()
  111. await child.trigger('focus')
  112. expect(onFocus).toHaveBeenCalled()
  113. await child.trigger('blur')
  114. expect(onBlur).toHaveBeenCalled()
  115. })
  116. it('should provide onMousedown event for children', async () => {
  117. expect(onMousedown).not.toHaveBeenCalled()
  118. const child = findChild()
  119. await child.trigger('mousedown')
  120. expect(onMousedown).toHaveBeenCalled()
  121. })
  122. it('should be able to provide item tabbing handlers', async () => {
  123. const onTabChange = vi.fn()
  124. const tabbedId = 'test_id'
  125. const child = findChild()
  126. await wrapper.setProps({
  127. onCurrentTabIdChange: onTabChange,
  128. })
  129. child.vm.onItemFocus(tabbedId)
  130. await nextTick()
  131. expect(onTabChange).toHaveBeenCalledWith(tabbedId)
  132. expect(child.attributes('tabindex')).toBe('0')
  133. child.vm.onItemShiftTab()
  134. await nextTick()
  135. expect(child.attributes('tabindex')).toBe('-1')
  136. })
  137. })
  138. })