Design system.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

213 lines
4.4 KiB

  1. import * as React from 'react';
  2. import {
  3. render,
  4. screen,
  5. cleanup,
  6. } from '@testing-library/react';
  7. import userEvent from '@testing-library/user-event';
  8. import { Button } from '@tesseract-design/web-base';
  9. import {
  10. vi,
  11. describe,
  12. it,
  13. expect,
  14. afterEach,
  15. } from 'vitest';
  16. import matchers from '@testing-library/jest-dom/matchers';
  17. import {
  18. ActionButton,
  19. ActionButtonDerivedElement,
  20. } from '.';
  21. expect.extend(matchers);
  22. describe('ActionButton', () => {
  23. afterEach(() => {
  24. cleanup();
  25. });
  26. it('renders a button', () => {
  27. render(
  28. <ActionButton />,
  29. );
  30. const button = screen.getByRole('button');
  31. expect(button).toBeInTheDocument();
  32. expect(button).toHaveProperty('type', 'button');
  33. });
  34. it('renders a subtext', () => {
  35. render(
  36. <ActionButton
  37. subtext="subtext"
  38. />,
  39. );
  40. const subtext = screen.getByTestId('subtext');
  41. expect(subtext).toBeInTheDocument();
  42. });
  43. it('renders a badge', () => {
  44. render(
  45. <ActionButton
  46. badge="badge"
  47. />,
  48. );
  49. const badge = screen.getByTestId('badge');
  50. expect(badge).toBeInTheDocument();
  51. });
  52. it('renders as a menu item', () => {
  53. render(
  54. <ActionButton
  55. menuItem
  56. />,
  57. );
  58. const menuItemIndicator = screen.getByTestId('menuItemIndicator');
  59. expect(menuItemIndicator).toBeInTheDocument();
  60. });
  61. it('handles click events', async () => {
  62. const onClick = vi.fn().mockImplementationOnce(
  63. (e: React.MouseEvent<ActionButtonDerivedElement>) => {
  64. e.preventDefault();
  65. },
  66. );
  67. render(
  68. <ActionButton
  69. onClick={onClick}
  70. />,
  71. );
  72. const button = screen.getByRole('button');
  73. await userEvent.click(button);
  74. expect(onClick).toBeCalled();
  75. });
  76. it('renders a compact button', () => {
  77. render(
  78. <ActionButton
  79. compact
  80. />,
  81. );
  82. const button = screen.getByRole('button');
  83. expect(button).toHaveClass('pl-2 gap-2 pr-2');
  84. });
  85. it('renders an icon', () => {
  86. render(
  87. <ActionButton
  88. icon={<span />}
  89. />,
  90. );
  91. const icon = screen.getByTestId('icon');
  92. expect(icon).toBeInTheDocument();
  93. });
  94. it('renders icon after children', () => {
  95. render(
  96. <ActionButton
  97. iconAfterChildren
  98. icon={<div />}
  99. />,
  100. );
  101. const childrenParent = screen.getByTestId('childrenParent');
  102. expect(childrenParent).toHaveClass('flex-row-reverse');
  103. });
  104. describe.each`
  105. size | className
  106. ${'small'} | ${'h-10'}
  107. ${'medium'} | ${'h-12'}
  108. ${'large'} | ${'h-16'}
  109. `('on $size size', ({
  110. size,
  111. className,
  112. }: { size: Button.Size, className: string }) => {
  113. it('renders button styles', () => {
  114. render(
  115. <ActionButton
  116. size={size}
  117. />,
  118. );
  119. const button = screen.getByRole('button');
  120. expect(button).toHaveClass(className);
  121. });
  122. it('renders badge styles', () => {
  123. render(
  124. <ActionButton
  125. size={size}
  126. badge="badge"
  127. />,
  128. );
  129. const badge = screen.getByTestId('badge');
  130. expect(badge).toBeInTheDocument();
  131. });
  132. });
  133. it.each`
  134. variant | className
  135. ${'bare'} | ${'bg-negative'}
  136. ${'outline'} | ${'border-2'}
  137. ${'filled'} | ${'bg-primary'}
  138. `('renders a button with $variant variant', ({
  139. variant,
  140. className,
  141. }: { variant: Button.Variant, className: string }) => {
  142. render(
  143. <ActionButton
  144. variant={variant}
  145. />,
  146. );
  147. const button = screen.getByRole('button');
  148. expect(button).toHaveClass(className);
  149. });
  150. it('renders a block button', () => {
  151. render(
  152. <ActionButton
  153. block
  154. />,
  155. );
  156. const button = screen.getByRole('button');
  157. expect(button).toHaveClass('w-full flex');
  158. });
  159. it('renders children', () => {
  160. render(
  161. <ActionButton>
  162. Foo
  163. </ActionButton>,
  164. );
  165. const children = screen.getByTestId('children');
  166. expect(children).toHaveTextContent('Foo');
  167. });
  168. it.each(Button.AVAILABLE_TYPES)('renders a button with type %s', (buttonType) => {
  169. render(
  170. <ActionButton
  171. type={buttonType}
  172. />,
  173. );
  174. const button = screen.getByRole('button');
  175. expect(button).toHaveProperty('type', buttonType);
  176. });
  177. it('renders a disabled button', () => {
  178. render(
  179. <ActionButton
  180. disabled
  181. />,
  182. );
  183. const button = screen.getByTestId('button');
  184. expect(button).toBeDisabled();
  185. });
  186. });