button.test.tsx 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. import { render, fireEvent } from '@testing-library/react'
  2. import { Button } from '@/components/ui/button'
  3. describe('Button', () => {
  4. it('应该渲染按钮', () => {
  5. const { getByText } = render(<Button>测试按钮</Button>)
  6. expect(getByText('测试按钮')).toBeTruthy()
  7. })
  8. it('应该处理点击事件', () => {
  9. const handleClick = jest.fn()
  10. const { getByText } = render(
  11. <Button onClick={handleClick}>点击我</Button>
  12. )
  13. const button = getByText('点击我')
  14. fireEvent.click(button)
  15. expect(handleClick).toHaveBeenCalled()
  16. })
  17. it('应该应用默认变体样式', () => {
  18. const { container } = render(<Button>默认按钮</Button>)
  19. const button = container.querySelector('button')
  20. expect(button?.className).toContain('bg-primary')
  21. expect(button?.className).toContain('text-primary-foreground')
  22. })
  23. it('应该应用不同的变体样式', () => {
  24. const { container: defaultContainer } = render(<Button variant="default">默认</Button>)
  25. const { container: destructiveContainer } = render(<Button variant="destructive">危险</Button>)
  26. const { container: outlineContainer } = render(<Button variant="outline">轮廓</Button>)
  27. const { container: secondaryContainer } = render(<Button variant="secondary">次要</Button>)
  28. const { container: ghostContainer } = render(<Button variant="ghost">幽灵</Button>)
  29. const { container: linkContainer } = render(<Button variant="link">链接</Button>)
  30. const defaultButton = defaultContainer.querySelector('button')
  31. const destructiveButton = destructiveContainer.querySelector('button')
  32. const outlineButton = outlineContainer.querySelector('button')
  33. const secondaryButton = secondaryContainer.querySelector('button')
  34. const ghostButton = ghostContainer.querySelector('button')
  35. const linkButton = linkContainer.querySelector('button')
  36. expect(defaultButton?.className).toContain('bg-primary')
  37. expect(destructiveButton?.className).toContain('bg-destructive')
  38. expect(outlineButton?.className).toContain('border-input')
  39. expect(secondaryButton?.className).toContain('bg-secondary')
  40. expect(ghostButton?.className).toContain('hover:bg-accent')
  41. expect(linkButton?.className).toContain('text-primary')
  42. })
  43. it('应该应用不同的大小样式', () => {
  44. const { container: defaultContainer } = render(<Button size="default">默认</Button>)
  45. const { container: smContainer } = render(<Button size="sm">小</Button>)
  46. const { container: lgContainer } = render(<Button size="lg">大</Button>)
  47. const { container: iconContainer } = render(<Button size="icon">图标</Button>)
  48. const defaultButton = defaultContainer.querySelector('button')
  49. const smButton = smContainer.querySelector('button')
  50. const lgButton = lgContainer.querySelector('button')
  51. const iconButton = iconContainer.querySelector('button')
  52. expect(defaultButton?.className).toContain('h-10')
  53. expect(smButton?.className).toContain('h-9')
  54. expect(lgButton?.className).toContain('h-11')
  55. expect(iconButton?.className).toContain('h-10 w-10')
  56. })
  57. it('应该禁用按钮', () => {
  58. const { container } = render(<Button disabled>禁用按钮</Button>)
  59. const button = container.querySelector('button')
  60. expect(button?.disabled).toBe(true)
  61. expect(button?.className).toContain('[&[disabled]]:opacity-50')
  62. expect(button?.className).toContain('[&[disabled]]:pointer-events-none')
  63. })
  64. it('应该应用自定义类名', () => {
  65. const { container } = render(
  66. <Button className="custom-class">自定义样式</Button>
  67. )
  68. const button = container.querySelector('button')
  69. expect(button?.className).toContain('custom-class')
  70. })
  71. it('应该渲染子元素', () => {
  72. const { getByText } = render(
  73. <Button>
  74. <span>图标</span>
  75. 带图标的按钮
  76. </Button>
  77. )
  78. expect(getByText('带图标的按钮')).toBeTruthy()
  79. expect(getByText('图标')).toBeTruthy()
  80. })
  81. it('应该传递其他属性', () => {
  82. const { container } = render(
  83. <Button type="submit" data-testid="test-button">提交按钮</Button>
  84. )
  85. const button = container.querySelector('button')
  86. expect(button?.type).toBe('submit')
  87. })
  88. it('应该应用重置样式', () => {
  89. const { container } = render(<Button>重置按钮</Button>)
  90. const button = container.querySelector('button')
  91. expect(button?.className).toContain('w-auto')
  92. expect(button?.className).toContain('border-0')
  93. expect(button?.className).toContain('text-inherit')
  94. expect(button?.className).toContain('p-0')
  95. expect(button?.className).toContain('m-0')
  96. })
  97. it('应该组合变体样式和重置样式', () => {
  98. const { container } = render(
  99. <Button variant="outline" size="sm">组合样式</Button>
  100. )
  101. const button = container.querySelector('button')
  102. expect(button?.className).toContain('border-input') // outline变体
  103. expect(button?.className).toContain('h-9') // sm大小
  104. expect(button?.className).toContain('w-auto') // 重置样式
  105. })
  106. it('应该处理焦点状态', () => {
  107. const { container } = render(<Button>焦点按钮</Button>)
  108. const button = container.querySelector('button')
  109. expect(button?.className).toContain('focus-visible:outline-none')
  110. expect(button?.className).toContain('focus-visible:ring-2')
  111. expect(button?.className).toContain('focus-visible:ring-ring')
  112. })
  113. it('应该应用过渡效果', () => {
  114. const { container } = render(<Button>过渡按钮</Button>)
  115. const button = container.querySelector('button')
  116. expect(button?.className).toContain('transition-colors')
  117. })
  118. it('应该正确处理disabled为false的情况', () => {
  119. const { container } = render(<Button disabled={false}>非禁用按钮</Button>)
  120. const button = container.querySelector('button')
  121. expect(button?.disabled).toBe(false)
  122. })
  123. })