Design system.
Du kan inte välja fler än 25 ämnen Ämnen måste starta med en bokstav eller siffra, kan innehålla bindestreck ('-') och vara max 35 tecken långa.
 
 
 

300 rader
6.6 KiB

  1. import * as React from 'react';
  2. import {
  3. render,
  4. screen
  5. } from '@testing-library/react';
  6. import * as TextControlBase from '@tesseract-design/web-base-textcontrol';
  7. import userEvent from '@testing-library/user-event';
  8. import { vi } from 'vitest';
  9. import {
  10. DropdownSelect
  11. } from '.';
  12. vi.mock('@tesseract-design/web-base-textcontrol');
  13. describe('DropdownSelect', () => {
  14. it('renders a combobox', () => {
  15. render(<DropdownSelect />);
  16. const combobox = screen.getByRole('combobox');
  17. expect(combobox).toBeInTheDocument();
  18. });
  19. it('renders a border', () => {
  20. render(
  21. <DropdownSelect
  22. border
  23. />
  24. );
  25. const border = screen.getByTestId('border');
  26. expect(border).toBeInTheDocument();
  27. });
  28. it('renders a label', () => {
  29. render(
  30. <DropdownSelect
  31. label="foo"
  32. />
  33. );
  34. const combobox = screen.getByLabelText('foo');
  35. expect(combobox).toBeInTheDocument();
  36. const label = screen.getByTestId('label');
  37. expect(label).toHaveTextContent('foo');
  38. });
  39. it('renders a hidden label', () => {
  40. render(
  41. <DropdownSelect
  42. label="foo"
  43. hiddenLabel
  44. />
  45. );
  46. const combobox = screen.getByLabelText('foo');
  47. expect(combobox).toBeInTheDocument();
  48. const label = screen.queryByTestId('label');
  49. expect(label).toBeNull();
  50. });
  51. it('renders a hint', () => {
  52. render(
  53. <DropdownSelect
  54. hint="foo"
  55. />
  56. );
  57. const hint = screen.getByTestId('hint');
  58. expect(hint).toBeInTheDocument();
  59. });
  60. it('does not render invalid options', () => {
  61. render(
  62. <DropdownSelect
  63. options={[
  64. {
  65. label: 'foo',
  66. },
  67. {
  68. label: 'bar',
  69. }
  70. ]}
  71. />
  72. );
  73. const combobox = screen.getByRole('combobox');
  74. expect(combobox.children).toHaveLength(0);
  75. });
  76. it('renders valid options', () => {
  77. render(
  78. <DropdownSelect
  79. options={[
  80. {
  81. label: 'foo',
  82. value: 'foo',
  83. },
  84. {
  85. label: 'bar',
  86. value: 'bar',
  87. }
  88. ]}
  89. />
  90. );
  91. const combobox = screen.getByRole('combobox');
  92. expect(combobox.children).toHaveLength(2);
  93. });
  94. it('renders shallow option groups', () => {
  95. render(
  96. <DropdownSelect
  97. options={[
  98. {
  99. label: 'foo',
  100. children: [
  101. {
  102. label: 'baz',
  103. value: 'baz',
  104. },
  105. ],
  106. },
  107. {
  108. label: 'bar',
  109. children: [
  110. {
  111. label: 'quux',
  112. value: 'quux',
  113. },
  114. {
  115. label: 'quuux',
  116. value: 'quuux',
  117. },
  118. ],
  119. }
  120. ]}
  121. />
  122. );
  123. const combobox = screen.getByRole('combobox');
  124. expect(combobox.children).toHaveLength(2);
  125. expect(combobox.children[0].children).toHaveLength(1);
  126. expect(combobox.children[1].children).toHaveLength(2);
  127. });
  128. it('renders deep option groups', () => {
  129. render(
  130. <DropdownSelect
  131. options={[
  132. {
  133. label: 'foo',
  134. children: [
  135. {
  136. label: 'baz',
  137. children: [
  138. {
  139. label: 'quuuux',
  140. value: 'quuuux',
  141. },
  142. {
  143. label: 'quuuuux',
  144. value: 'quuuuux',
  145. },
  146. {
  147. label: 'quuuuuux',
  148. value: 'quuuuuux',
  149. },
  150. ],
  151. },
  152. ],
  153. },
  154. {
  155. label: 'bar',
  156. children: [
  157. {
  158. label: 'quux',
  159. value: 'quux',
  160. },
  161. {
  162. label: 'quuux',
  163. value: 'quuux',
  164. },
  165. ],
  166. }
  167. ]}
  168. />
  169. );
  170. const combobox = screen.getByRole('combobox');
  171. expect(combobox.children).toHaveLength(2);
  172. expect(combobox.children[0].children).toHaveLength(4);
  173. expect(combobox.children[1].children).toHaveLength(2);
  174. });
  175. describe.each(Object.values(TextControlBase.TextControlSize))('on %s size', (size) => {
  176. it('renders input styles', () => {
  177. render(
  178. <DropdownSelect
  179. size={size}
  180. />
  181. );
  182. expect(TextControlBase.Input).toBeCalledWith(expect.objectContaining({
  183. size,
  184. }));
  185. });
  186. it('renders hint styles', () => {
  187. render(
  188. <DropdownSelect
  189. size={size}
  190. hint="hint"
  191. />
  192. );
  193. expect(TextControlBase.HintWrapper).toBeCalledWith(expect.objectContaining({
  194. size,
  195. }));
  196. });
  197. it('renders indicator styles', () => {
  198. render(
  199. <DropdownSelect
  200. size={size}
  201. />
  202. );
  203. expect(TextControlBase.IndicatorWrapper).toBeCalledWith(expect.objectContaining({
  204. size,
  205. }));
  206. });
  207. });
  208. it('renders a block input', () => {
  209. render(
  210. <DropdownSelect
  211. block
  212. />
  213. );
  214. expect(TextControlBase.Root).toBeCalledWith(expect.objectContaining({
  215. block: true,
  216. }));
  217. });
  218. describe.each(Object.values(TextControlBase.TextControlStyle))('on %s style', (style) => {
  219. it('renders input styles', () => {
  220. render(
  221. <DropdownSelect
  222. style={style}
  223. />
  224. );
  225. expect(TextControlBase.Input).toBeCalledWith(expect.objectContaining({
  226. style,
  227. }));
  228. });
  229. it('renders hint styles', () => {
  230. render(
  231. <DropdownSelect
  232. style={style}
  233. hint="hint"
  234. />
  235. );
  236. expect(TextControlBase.HintWrapper).toBeCalledWith(expect.objectContaining({
  237. style,
  238. }));
  239. });
  240. it('renders indicator styles', () => {
  241. render(
  242. <DropdownSelect
  243. style={style}
  244. />
  245. );
  246. expect(TextControlBase.IndicatorWrapper).toBeCalledWith(expect.objectContaining({
  247. style,
  248. }));
  249. });
  250. });
  251. it('handles change events', () => {
  252. const onChange = vi.fn().mockImplementationOnce((e) => { e.preventDefault(); })
  253. render(
  254. <DropdownSelect
  255. onChange={onChange}
  256. options={[
  257. {
  258. label: 'foo',
  259. value: 'foo',
  260. },
  261. {
  262. label: 'bar',
  263. value: 'bar',
  264. }
  265. ]}
  266. />
  267. );
  268. const combobox: HTMLSelectElement = screen.getByRole('combobox');
  269. const [, secondOption] = screen.getAllByRole('option');
  270. userEvent.selectOptions(combobox, secondOption);
  271. expect(onChange).toBeCalled();
  272. });
  273. });