@1doc/1ds-react 2.8.0 → 2.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (287) hide show
  1. package/CHANGELOG.md +1540 -0
  2. package/dist/components/AILabel/AILabel.js +1 -1
  3. package/dist/components/Accordion/Accordion.css +13 -0
  4. package/dist/components/Accordion/Accordion.d.ts +9 -2
  5. package/dist/components/Accordion/Accordion.js +1 -0
  6. package/dist/components/AppSubheader/AppSubheader.css +10 -1
  7. package/dist/components/AttachmentCard/AttachmentCard.css +26 -8
  8. package/dist/components/AttachmentCard/AttachmentCard.d.ts +22 -2
  9. package/dist/components/AttachmentCard/AttachmentCard.js +47 -3
  10. package/dist/components/Avatar/Avatar.css +7 -2
  11. package/dist/components/Avatar/AvatarGroup.d.ts +17 -0
  12. package/dist/components/Avatar/AvatarGroup.js +22 -8
  13. package/dist/components/Badge/Badge.css +67 -2
  14. package/dist/components/Badge/Badge.d.ts +23 -4
  15. package/dist/components/Badge/Badge.js +4 -0
  16. package/dist/components/Box/Box.css +83 -0
  17. package/dist/components/Box/Box.d.ts +82 -2
  18. package/dist/components/Box/Box.js +42 -2
  19. package/dist/components/Button/Button.css +29 -0
  20. package/dist/components/Button/Button.d.ts +4 -4
  21. package/dist/components/Button/Button.js +4 -1
  22. package/dist/components/Calendar/Calendar.css +245 -0
  23. package/dist/components/Calendar/Calendar.d.ts +126 -0
  24. package/dist/components/Calendar/Calendar.js +320 -0
  25. package/dist/components/Chips/Chips.css +38 -0
  26. package/dist/components/Chips/Chips.d.ts +5 -2
  27. package/dist/components/Chips/Chips.js +2 -1
  28. package/dist/components/Coachmark/Coachmark.css +128 -0
  29. package/dist/components/Coachmark/Coachmark.d.ts +87 -0
  30. package/dist/components/Coachmark/Coachmark.js +362 -0
  31. package/dist/components/CodeBlock/CodeBlock.css +96 -0
  32. package/dist/components/CodeBlock/CodeBlock.d.ts +47 -0
  33. package/dist/components/CodeBlock/CodeBlock.js +103 -0
  34. package/dist/components/ColorPicker/ColorPicker.css +140 -0
  35. package/dist/components/ColorPicker/ColorPicker.d.ts +73 -0
  36. package/dist/components/ColorPicker/ColorPicker.js +219 -0
  37. package/dist/components/Combobox/Combobox.css +8 -0
  38. package/dist/components/DataTable/DataTable.css +254 -0
  39. package/dist/components/DataTable/DataTable.d.ts +81 -5
  40. package/dist/components/DataTable/DataTable.js +335 -19
  41. package/dist/components/DatePicker/DatePicker.css +8 -0
  42. package/dist/components/DatePicker/DatePicker.js +10 -1
  43. package/dist/components/DescriptionList/DescriptionList.css +127 -0
  44. package/dist/components/DescriptionList/DescriptionList.d.ts +62 -0
  45. package/dist/components/DescriptionList/DescriptionList.js +52 -0
  46. package/dist/components/EmptyState/EmptyState.d.ts +4 -2
  47. package/dist/components/EmptyState/EmptyState.js +2 -2
  48. package/dist/components/FileInput/FileInput.css +16 -0
  49. package/dist/components/FileInput/FileInput.d.ts +4 -2
  50. package/dist/components/FileInput/FileInput.js +8 -2
  51. package/dist/components/Grid/Grid.js +5 -5
  52. package/dist/components/IconPicker/IconPicker.css +107 -0
  53. package/dist/components/IconPicker/IconPicker.d.ts +74 -0
  54. package/dist/components/IconPicker/IconPicker.js +194 -0
  55. package/dist/components/Input/Input.css +59 -0
  56. package/dist/components/Input/Input.d.ts +17 -1
  57. package/dist/components/Input/Input.js +67 -5
  58. package/dist/components/Kanban/Kanban.css +4 -0
  59. package/dist/components/Kbd/Kbd.css +66 -0
  60. package/dist/components/Kbd/Kbd.d.ts +32 -0
  61. package/dist/components/Kbd/Kbd.js +40 -0
  62. package/dist/components/List/List.css +136 -0
  63. package/dist/components/List/List.d.ts +82 -0
  64. package/dist/components/List/List.js +53 -0
  65. package/dist/components/List/ListItem.d.ts +97 -0
  66. package/dist/components/List/ListItem.js +82 -0
  67. package/dist/components/Modal/Modal.css +80 -0
  68. package/dist/components/Modal/Modal.d.ts +33 -6
  69. package/dist/components/Modal/Modal.js +101 -6
  70. package/dist/components/MultiSelect/MultiSelect.css +8 -0
  71. package/dist/components/MultiSelect/MultiSelect.js +10 -1
  72. package/dist/components/OrgChart/OrgChart.css +149 -0
  73. package/dist/components/OrgChart/OrgChart.d.ts +83 -0
  74. package/dist/components/OrgChart/OrgChart.js +297 -0
  75. package/dist/components/OtpInput/OtpInput.css +93 -0
  76. package/dist/components/OtpInput/OtpInput.d.ts +60 -0
  77. package/dist/components/OtpInput/OtpInput.js +215 -0
  78. package/dist/components/PhoneInput/PhoneInput.css +8 -0
  79. package/dist/components/Popover/Popover.d.ts +7 -0
  80. package/dist/components/Popover/Popover.js +11 -1
  81. package/dist/components/RichTextEditor/RichTextEditor.css +250 -0
  82. package/dist/components/RichTextEditor/RichTextEditor.d.ts +97 -0
  83. package/dist/components/RichTextEditor/RichTextEditor.js +951 -0
  84. package/dist/components/SegmentedControl/SegmentedControl.css +24 -0
  85. package/dist/components/SegmentedControl/SegmentedControl.d.ts +2 -0
  86. package/dist/components/SegmentedControl/SegmentedControl.js +10 -2
  87. package/dist/components/Select/Select.css +164 -0
  88. package/dist/components/Select/Select.d.ts +34 -0
  89. package/dist/components/Select/Select.js +258 -28
  90. package/dist/components/Stack/Stack.css +49 -0
  91. package/dist/components/Stack/Stack.d.ts +65 -7
  92. package/dist/components/Stack/Stack.js +30 -2
  93. package/dist/components/StatCard/StatCard.css +138 -0
  94. package/dist/components/StatCard/StatCard.d.ts +26 -0
  95. package/dist/components/StatCard/StatCard.js +13 -1
  96. package/dist/components/Tabs/Tab.d.ts +15 -0
  97. package/dist/components/Tabs/Tab.js +30 -1
  98. package/dist/components/Tabs/Tabs.css +132 -0
  99. package/dist/components/Tabs/Tabs.d.ts +7 -0
  100. package/dist/components/Tabs/Tabs.js +13 -2
  101. package/dist/components/Tag/Tag.css +85 -2
  102. package/dist/components/Tag/Tag.d.ts +13 -6
  103. package/dist/components/Tag/Tag.js +1 -0
  104. package/dist/components/Text/Text.js +2 -2
  105. package/dist/components/Textarea/Textarea.css +8 -0
  106. package/dist/components/TimePicker/TimePicker.css +8 -0
  107. package/dist/components/Toast/Toast.css +32 -0
  108. package/dist/components/Toast/Toast.d.ts +18 -0
  109. package/dist/components/Toast/Toast.js +14 -1
  110. package/dist/components/Toast/ToastStack.js +8 -1
  111. package/dist/components/Tooltip/Tooltip.css +25 -0
  112. package/dist/components/Tooltip/Tooltip.d.ts +11 -0
  113. package/dist/components/Tooltip/Tooltip.js +18 -3
  114. package/dist/index.d.ts +25 -0
  115. package/dist/index.js +14 -0
  116. package/dist/teste/AILabel.test.d.ts +1 -0
  117. package/dist/teste/AILabel.test.js +33 -0
  118. package/dist/teste/AccordionConteudoLivre.test.d.ts +1 -0
  119. package/dist/teste/AccordionConteudoLivre.test.js +29 -0
  120. package/dist/teste/AccordionTituloNeutro.test.d.ts +1 -0
  121. package/dist/teste/AccordionTituloNeutro.test.js +23 -0
  122. package/dist/teste/AppSubheaderRegiao.test.d.ts +1 -0
  123. package/dist/teste/AppSubheaderRegiao.test.js +13 -0
  124. package/dist/teste/AtributosRepassados.test.d.ts +1 -0
  125. package/dist/teste/AtributosRepassados.test.js +52 -0
  126. package/dist/teste/AttachmentCardIA.test.d.ts +1 -0
  127. package/dist/teste/AttachmentCardIA.test.js +89 -0
  128. package/dist/teste/AttachmentCardLista.test.d.ts +1 -0
  129. package/dist/teste/AttachmentCardLista.test.js +49 -0
  130. package/dist/teste/AttachmentCardSm.test.d.ts +1 -0
  131. package/dist/teste/AttachmentCardSm.test.js +26 -0
  132. package/dist/teste/AvatarGroupOverlap.test.d.ts +1 -0
  133. package/dist/teste/AvatarGroupOverlap.test.js +56 -0
  134. package/dist/teste/BadgeNeutroColado.test.d.ts +1 -0
  135. package/dist/teste/BadgeNeutroColado.test.js +11 -0
  136. package/dist/teste/BadgeTag.test.d.ts +1 -0
  137. package/dist/teste/BadgeTag.test.js +55 -0
  138. package/dist/teste/BoxItemFlex.test.d.ts +1 -0
  139. package/dist/teste/BoxItemFlex.test.js +54 -0
  140. package/dist/teste/BoxLayout.test.d.ts +1 -0
  141. package/dist/teste/BoxLayout.test.js +35 -0
  142. package/dist/teste/Button.test.d.ts +1 -0
  143. package/dist/teste/Button.test.js +27 -0
  144. package/dist/teste/Calendar.test.d.ts +1 -0
  145. package/dist/teste/Calendar.test.js +221 -0
  146. package/dist/teste/CalendarCabecalho.test.d.ts +1 -0
  147. package/dist/teste/CalendarCabecalho.test.js +11 -0
  148. package/dist/teste/ChipsXs.test.d.ts +1 -0
  149. package/dist/teste/ChipsXs.test.js +31 -0
  150. package/dist/teste/Coachmark.test.d.ts +1 -0
  151. package/dist/teste/Coachmark.test.js +149 -0
  152. package/dist/teste/CoachmarkSemVeu.test.d.ts +1 -0
  153. package/dist/teste/CoachmarkSemVeu.test.js +85 -0
  154. package/dist/teste/ColorPicker.test.d.ts +1 -0
  155. package/dist/teste/ColorPicker.test.js +132 -0
  156. package/dist/teste/ColorPickerXs.test.d.ts +1 -0
  157. package/dist/teste/ColorPickerXs.test.js +21 -0
  158. package/dist/teste/DataTableArvoreEVariantes.test.d.ts +1 -0
  159. package/dist/teste/DataTableArvoreEVariantes.test.js +190 -0
  160. package/dist/teste/DataTableCelulaLivre.test.d.ts +1 -0
  161. package/dist/teste/DataTableCelulaLivre.test.js +76 -0
  162. package/dist/teste/DataTableDocumento.test.d.ts +1 -0
  163. package/dist/teste/DataTableDocumento.test.js +92 -0
  164. package/dist/teste/DatePicker.test.js +23 -0
  165. package/dist/teste/DescriptionListCompacta.test.d.ts +1 -0
  166. package/dist/teste/DescriptionListCompacta.test.js +22 -0
  167. package/dist/teste/EmptyStateTituloRico.test.d.ts +1 -0
  168. package/dist/teste/EmptyStateTituloRico.test.js +23 -0
  169. package/dist/teste/FileInputTrigger.test.d.ts +1 -0
  170. package/dist/teste/FileInputTrigger.test.js +53 -0
  171. package/dist/teste/IconPicker.test.d.ts +1 -0
  172. package/dist/teste/IconPicker.test.js +130 -0
  173. package/dist/teste/InputAgrupado.test.d.ts +1 -0
  174. package/dist/teste/InputAgrupado.test.js +24 -0
  175. package/dist/teste/InputMascaraEAfins.test.d.ts +1 -0
  176. package/dist/teste/InputMascaraEAfins.test.js +99 -0
  177. package/dist/teste/KbdCodeBlock.test.d.ts +1 -0
  178. package/dist/teste/KbdCodeBlock.test.js +95 -0
  179. package/dist/teste/List.test.d.ts +1 -0
  180. package/dist/teste/List.test.js +153 -0
  181. package/dist/teste/ListItemTooltipStandalone.test.d.ts +1 -0
  182. package/dist/teste/ListItemTooltipStandalone.test.js +39 -0
  183. package/dist/teste/ModalVariantes.test.d.ts +1 -0
  184. package/dist/teste/ModalVariantes.test.js +151 -0
  185. package/dist/teste/NomeAcessivelSsr.test.d.ts +1 -0
  186. package/dist/teste/NomeAcessivelSsr.test.js +88 -0
  187. package/dist/teste/OrgChart.test.d.ts +1 -0
  188. package/dist/teste/OrgChart.test.js +162 -0
  189. package/dist/teste/OtpInput.test.d.ts +1 -0
  190. package/dist/teste/OtpInput.test.js +143 -0
  191. package/dist/teste/PopoverMaxHeight.test.d.ts +1 -0
  192. package/dist/teste/PopoverMaxHeight.test.js +38 -0
  193. package/dist/teste/RichTextEditor.test.d.ts +1 -0
  194. package/dist/teste/RichTextEditor.test.js +287 -0
  195. package/dist/teste/RichTextEditorAlinhaImagemTabela.test.d.ts +1 -0
  196. package/dist/teste/RichTextEditorAlinhaImagemTabela.test.js +212 -0
  197. package/dist/teste/RichTextEditorEstiloDeTexto.test.d.ts +1 -0
  198. package/dist/teste/RichTextEditorEstiloDeTexto.test.js +120 -0
  199. package/dist/teste/SegmentedControlContador.test.d.ts +1 -0
  200. package/dist/teste/SegmentedControlContador.test.js +39 -0
  201. package/dist/teste/SelectAbertoControladoEFlutuante.test.d.ts +1 -0
  202. package/dist/teste/SelectAbertoControladoEFlutuante.test.js +145 -0
  203. package/dist/teste/SelectFiltroCorETamanho.test.d.ts +1 -0
  204. package/dist/teste/SelectFiltroCorETamanho.test.js +77 -0
  205. package/dist/teste/SelectPlacementFiltro.test.d.ts +1 -0
  206. package/dist/teste/SelectPlacementFiltro.test.js +88 -0
  207. package/dist/teste/Stack.test.d.ts +1 -0
  208. package/dist/teste/Stack.test.js +57 -0
  209. package/dist/teste/StatCardRotuloTopo.test.d.ts +1 -0
  210. package/dist/teste/StatCardRotuloTopo.test.js +34 -0
  211. package/dist/teste/StatCardSecundariaETom.test.d.ts +1 -0
  212. package/dist/teste/StatCardSecundariaETom.test.js +45 -0
  213. package/dist/teste/TabsContadorFechavel.test.d.ts +1 -0
  214. package/dist/teste/TabsContadorFechavel.test.js +79 -0
  215. package/dist/teste/ToastAcaoEDetalhes.test.d.ts +1 -0
  216. package/dist/teste/ToastAcaoEDetalhes.test.js +94 -0
  217. package/dist/teste/TooltipDark.test.d.ts +1 -0
  218. package/dist/teste/TooltipDark.test.js +31 -0
  219. package/dist/utils/calendario.d.ts +28 -0
  220. package/dist/utils/calendario.js +73 -0
  221. package/dist/utils/html-seguro.d.ts +45 -0
  222. package/dist/utils/html-seguro.js +208 -0
  223. package/dist/utils/paleta-de-cores.d.ts +26 -0
  224. package/dist/utils/paleta-de-cores.js +10 -0
  225. package/dist/utils/texto.d.ts +5 -0
  226. package/dist/utils/texto.js +5 -0
  227. package/dist/utils/toast.d.ts +10 -1
  228. package/dist/utils/toast.js +2 -1
  229. package/package.json +3 -3
  230. package/src/index.ts +26 -0
  231. package/src/teste/AILabel.test.tsx +41 -0
  232. package/src/teste/AccordionConteudoLivre.test.tsx +39 -0
  233. package/src/teste/AccordionTituloNeutro.test.tsx +25 -0
  234. package/src/teste/AppSubheaderRegiao.test.tsx +17 -0
  235. package/src/teste/AtributosRepassados.test.tsx +73 -0
  236. package/src/teste/AttachmentCardIA.test.tsx +126 -0
  237. package/src/teste/AttachmentCardLista.test.tsx +53 -0
  238. package/src/teste/AttachmentCardSm.test.tsx +29 -0
  239. package/src/teste/AvatarGroupOverlap.test.tsx +74 -0
  240. package/src/teste/BadgeNeutroColado.test.tsx +15 -0
  241. package/src/teste/BadgeTag.test.tsx +85 -0
  242. package/src/teste/BoxItemFlex.test.tsx +81 -0
  243. package/src/teste/BoxLayout.test.tsx +50 -0
  244. package/src/teste/Button.test.tsx +39 -0
  245. package/src/teste/Calendar.test.tsx +282 -0
  246. package/src/teste/CalendarCabecalho.test.tsx +11 -0
  247. package/src/teste/ChipsXs.test.tsx +41 -0
  248. package/src/teste/Coachmark.test.tsx +198 -0
  249. package/src/teste/CoachmarkSemVeu.test.tsx +101 -0
  250. package/src/teste/ColorPicker.test.tsx +153 -0
  251. package/src/teste/ColorPickerXs.test.tsx +22 -0
  252. package/src/teste/DataTableArvoreEVariantes.test.tsx +240 -0
  253. package/src/teste/DataTableCelulaLivre.test.tsx +103 -0
  254. package/src/teste/DataTableDocumento.test.tsx +102 -0
  255. package/src/teste/DatePicker.test.tsx +38 -0
  256. package/src/teste/DescriptionListCompacta.test.tsx +24 -0
  257. package/src/teste/EmptyStateTituloRico.test.tsx +34 -0
  258. package/src/teste/FileInputTrigger.test.tsx +89 -0
  259. package/src/teste/IconPicker.test.tsx +145 -0
  260. package/src/teste/InputAgrupado.test.tsx +26 -0
  261. package/src/teste/InputMascaraEAfins.test.tsx +124 -0
  262. package/src/teste/KbdCodeBlock.test.tsx +106 -0
  263. package/src/teste/List.test.tsx +269 -0
  264. package/src/teste/ListItemTooltipStandalone.test.tsx +64 -0
  265. package/src/teste/ModalVariantes.test.tsx +173 -0
  266. package/src/teste/NomeAcessivelSsr.test.tsx +110 -0
  267. package/src/teste/OrgChart.test.tsx +183 -0
  268. package/src/teste/OtpInput.test.tsx +163 -0
  269. package/src/teste/PopoverMaxHeight.test.tsx +47 -0
  270. package/src/teste/RichTextEditor.test.tsx +329 -0
  271. package/src/teste/RichTextEditorAlinhaImagemTabela.test.tsx +238 -0
  272. package/src/teste/RichTextEditorEstiloDeTexto.test.tsx +137 -0
  273. package/src/teste/SegmentedControlContador.test.tsx +43 -0
  274. package/src/teste/SelectAbertoControladoEFlutuante.test.tsx +180 -0
  275. package/src/teste/SelectFiltroCorETamanho.test.tsx +90 -0
  276. package/src/teste/SelectPlacementFiltro.test.tsx +110 -0
  277. package/src/teste/Stack.test.tsx +80 -0
  278. package/src/teste/StatCardRotuloTopo.test.tsx +44 -0
  279. package/src/teste/StatCardSecundariaETom.test.tsx +51 -0
  280. package/src/teste/TabsContadorFechavel.test.tsx +144 -0
  281. package/src/teste/ToastAcaoEDetalhes.test.tsx +109 -0
  282. package/src/teste/TooltipDark.test.tsx +51 -0
  283. package/src/utils/calendario.ts +78 -0
  284. package/src/utils/html-seguro.ts +197 -0
  285. package/src/utils/paleta-de-cores.ts +34 -0
  286. package/src/utils/texto.ts +5 -0
  287. package/src/utils/toast.ts +12 -2
@@ -0,0 +1,39 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { describe, expect, it } from "vitest";
3
+ import { render, screen } from "@testing-library/react";
4
+ import userEvent from "@testing-library/user-event";
5
+ import SegmentedControl from "../components/SegmentedControl/SegmentedControl";
6
+ const FILA = [
7
+ { label: "Todas", value: "todas", count: 31 },
8
+ { label: "Minhas", value: "minhas", count: 0 },
9
+ { label: "Arquivadas", value: "arquivadas" },
10
+ { label: "Vazias", value: "vazias", count: "" },
11
+ ];
12
+ describe("SegmentedControl · count", () => {
13
+ it("desenha a pílula do contador depois do texto; 0 aparece, vazio e ausente não", () => {
14
+ const { container } = render(_jsx(SegmentedControl, { label: "Fila", options: FILA }));
15
+ const itens = [...container.querySelectorAll(".umds-segmented__item")];
16
+ expect(itens[0].querySelector(".umds-segmented__count")).toHaveTextContent("31");
17
+ expect(itens[1].querySelector(".umds-segmented__count")).toHaveTextContent("0");
18
+ expect(itens[2].querySelector(".umds-segmented__count")).toBeNull();
19
+ expect(itens[3].querySelector(".umds-segmented__count")).toBeNull();
20
+ const conteudo = itens[0].querySelector(".umds-segmented__conteudo");
21
+ expect(conteudo.lastElementChild).toHaveClass("umds-segmented__count");
22
+ });
23
+ it("o contador entra no nome acessível do segmento (o texto visível manda)", () => {
24
+ render(_jsx(SegmentedControl, { label: "Fila", id: "fila", options: FILA }));
25
+ expect(screen.getByRole("radio", { name: /Todas\s*31/ })).toBeInTheDocument();
26
+ });
27
+ it("o contador acompanha a escolha e a escolha segue funcionando", async () => {
28
+ const usuario = userEvent.setup();
29
+ const { container } = render(_jsx(SegmentedControl, { label: "Fila", options: FILA, defaultValue: "todas" }));
30
+ expect(screen.getByRole("radio", { name: /Todas/ })).toBeChecked();
31
+ await usuario.click(screen.getByText("Minhas"));
32
+ expect(screen.getByRole("radio", { name: /Minhas/ })).toBeChecked();
33
+ expect(container.querySelectorAll(".umds-segmented__count")).toHaveLength(2);
34
+ });
35
+ it("sem count em nenhum segmento, nada muda", () => {
36
+ const { container } = render(_jsx(SegmentedControl, { label: "x", options: [{ label: "25", value: "25" }] }));
37
+ expect(container.querySelector(".umds-segmented__count")).toBeNull();
38
+ });
39
+ });
@@ -0,0 +1,145 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { afterEach, describe, expect, it, vi } from "vitest";
3
+ import { fireEvent, render, screen, waitFor } from "@testing-library/react";
4
+ import { faFilter } from "@fortawesome/free-solid-svg-icons";
5
+ import Select from "../components/Select/Select";
6
+ const OPCOES = [
7
+ { label: "Urgente", value: "urgente" },
8
+ { label: "Revisão", value: "revisao" },
9
+ ];
10
+ afterEach(() => vi.restoreAllMocks());
11
+ describe("Select · open e onOpenChange", () => {
12
+ it("open controlado mostra a lista sem clique; fechado, não mostra", () => {
13
+ const { rerender } = render(_jsx(Select, { ariaLabel: "x", options: OPCOES, open: false }));
14
+ expect(screen.queryByRole("listbox")).toBeNull();
15
+ rerender(_jsx(Select, { ariaLabel: "x", options: OPCOES, open: true }));
16
+ expect(screen.getByRole("listbox")).toBeInTheDocument();
17
+ expect(screen.getByRole("combobox")).toHaveAttribute("aria-expanded", "true");
18
+ });
19
+ it("controlado: o clique só avisa; quem abre é o pai", () => {
20
+ const aoAbrir = vi.fn();
21
+ const { rerender } = render(_jsx(Select, { ariaLabel: "x", options: OPCOES, open: false, onOpenChange: aoAbrir }));
22
+ fireEvent.click(screen.getByRole("combobox"));
23
+ expect(aoAbrir).toHaveBeenCalledWith(true);
24
+ expect(screen.queryByRole("listbox")).toBeNull();
25
+ rerender(_jsx(Select, { ariaLabel: "x", options: OPCOES, open: true, onOpenChange: aoAbrir }));
26
+ expect(screen.getByRole("listbox")).toBeInTheDocument();
27
+ });
28
+ it("controlado aberto: escolher uma opção, Esc e clique fora pedem para fechar", () => {
29
+ const aoAbrir = vi.fn();
30
+ const { rerender } = render(_jsx(Select, { ariaLabel: "x", options: OPCOES, open: true, onOpenChange: aoAbrir }));
31
+ fireEvent.click(screen.getAllByRole("option")[0]);
32
+ expect(aoAbrir).toHaveBeenLastCalledWith(false);
33
+ aoAbrir.mockClear();
34
+ rerender(_jsx(Select, { ariaLabel: "x", options: OPCOES, open: true, onOpenChange: aoAbrir }));
35
+ fireEvent.keyDown(screen.getByRole("combobox"), { key: "Escape" });
36
+ expect(aoAbrir).toHaveBeenLastCalledWith(false);
37
+ aoAbrir.mockClear();
38
+ fireEvent.mouseDown(document.body);
39
+ expect(aoAbrir).toHaveBeenCalledWith(false);
40
+ });
41
+ it("o clique fora não avisa quando a lista está fechada", () => {
42
+ const aoAbrir = vi.fn();
43
+ render(_jsx(Select, { ariaLabel: "x", options: OPCOES, open: false, onOpenChange: aoAbrir }));
44
+ fireEvent.mouseDown(document.body);
45
+ expect(aoAbrir).not.toHaveBeenCalled();
46
+ });
47
+ it("clique fora vê o open de agora, não o do primeiro render", () => {
48
+ const aoAbrir = vi.fn();
49
+ const { rerender } = render(_jsx(Select, { ariaLabel: "x", options: OPCOES, open: false, onOpenChange: aoAbrir }));
50
+ rerender(_jsx(Select, { ariaLabel: "x", options: OPCOES, open: true, onOpenChange: aoAbrir }));
51
+ fireEvent.mouseDown(document.body);
52
+ expect(aoAbrir).toHaveBeenCalledWith(false);
53
+ });
54
+ it("sem open, o Select abre e fecha sozinho e também avisa", () => {
55
+ const aoAbrir = vi.fn();
56
+ render(_jsx(Select, { ariaLabel: "x", options: OPCOES, onOpenChange: aoAbrir }));
57
+ fireEvent.click(screen.getByRole("combobox"));
58
+ expect(screen.getByRole("listbox")).toBeInTheDocument();
59
+ expect(aoAbrir).toHaveBeenLastCalledWith(true);
60
+ fireEvent.click(screen.getAllByRole("option")[1]);
61
+ expect(screen.queryByRole("listbox")).toBeNull();
62
+ expect(aoAbrir).toHaveBeenLastCalledWith(false);
63
+ });
64
+ });
65
+ describe("Select · gatilho com ícone, amostra e aria-required", () => {
66
+ it("triggerIcon e triggerSwatch aparecem no gatilho, decorativos", () => {
67
+ const { container } = render(_jsx(Select, { ariaLabel: "x", options: OPCOES, triggerIcon: faFilter, triggerSwatch: "var(--umds-semantic-color-primary-pure)" }));
68
+ const icone = container.querySelector(".umds-select__trigger-icon");
69
+ expect(icone).toHaveAttribute("aria-hidden", "true");
70
+ expect(icone.querySelector("svg")).toHaveAttribute("data-icon", "filter");
71
+ const amostra = container.querySelector(".umds-select__swatch");
72
+ expect(amostra).toHaveAttribute("aria-hidden", "true");
73
+ expect(amostra.style.background).toContain("--umds-semantic-color-primary-pure");
74
+ expect(container.querySelector(".umds-select--has-trigger-icon")).not.toBeNull();
75
+ });
76
+ it("sem as props, não há ícone nem amostra", () => {
77
+ const { container } = render(_jsx(Select, { ariaLabel: "x", options: OPCOES }));
78
+ expect(container.querySelector(".umds-select__trigger-icon")).toBeNull();
79
+ expect(container.querySelector(".umds-select__swatch")).toBeNull();
80
+ });
81
+ it("required repassa aria-required ao combobox", () => {
82
+ const { rerender } = render(_jsx(Select, { ariaLabel: "x", options: OPCOES, required: true }));
83
+ expect(screen.getByRole("combobox")).toHaveAttribute("aria-required", "true");
84
+ rerender(_jsx(Select, { ariaLabel: "x", options: OPCOES }));
85
+ expect(screen.getByRole("combobox")).not.toHaveAttribute("aria-required");
86
+ });
87
+ });
88
+ describe("Select · variantes de filtro", () => {
89
+ it("search e combo escrevem a classe do filtro e a própria", () => {
90
+ const { container, rerender } = render(_jsx(Select, { ariaLabel: "x", options: OPCOES, variant: "search" }));
91
+ expect(container.querySelector(".umds-select--filter.umds-select--filter-search")).not.toBeNull();
92
+ rerender(_jsx(Select, { ariaLabel: "x", options: OPCOES, variant: "combo" }));
93
+ expect(container.querySelector(".umds-select--filter.umds-select--filter-combo")).not.toBeNull();
94
+ expect(container.querySelector(".umds-select--filter-search")).toBeNull();
95
+ });
96
+ it("search foca a busca ao abrir, como o filter", async () => {
97
+ render(_jsx(Select, { ariaLabel: "x", options: OPCOES, variant: "search", searchable: true }));
98
+ fireEvent.click(screen.getByRole("combobox"));
99
+ await waitFor(() => expect(document.activeElement).toBe(screen.getByRole("textbox")));
100
+ });
101
+ });
102
+ describe("Select · por cima do diálogo", () => {
103
+ it("dentro de role=dialog a lista vira fixed, ancorada no gatilho", async () => {
104
+ const { container } = render(_jsx("div", { role: "dialog", "aria-label": "Filtros", style: { overflow: "clip" }, children: _jsx(Select, { ariaLabel: "x", options: OPCOES }) }));
105
+ fireEvent.click(screen.getByRole("combobox"));
106
+ const lista = container.querySelector(".umds-select__dropdown");
107
+ expect(container.querySelector(".umds-select--floating")).not.toBeNull();
108
+ expect(lista.style.position).toBe("fixed");
109
+ await waitFor(() => expect(lista.style.visibility).toBe("visible"));
110
+ });
111
+ it("fora de diálogo a lista continua posicionada pelo CSS (sem fixed)", () => {
112
+ const { container } = render(_jsx(Select, { ariaLabel: "x", options: OPCOES }));
113
+ fireEvent.click(screen.getByRole("combobox"));
114
+ const lista = container.querySelector(".umds-select__dropdown");
115
+ expect(container.querySelector(".umds-select--floating")).toBeNull();
116
+ expect(lista.style.position).toBe("");
117
+ });
118
+ it("aria-modal também conta como diálogo", () => {
119
+ const { container } = render(_jsx("div", { "aria-modal": "true", children: _jsx(Select, { ariaLabel: "x", options: OPCOES }) }));
120
+ fireEvent.click(screen.getByRole("combobox"));
121
+ expect(container.querySelector(".umds-select--floating")).not.toBeNull();
122
+ });
123
+ });
124
+ describe("Select · placement auto mede o ancestral que rola", () => {
125
+ it("abre para cima e limita a altura da lista ao espaço do ancestral", () => {
126
+ vi.spyOn(HTMLElement.prototype, "getBoundingClientRect").mockImplementation(function () {
127
+ const rolante = this.getAttribute("data-rolante") !== null;
128
+ const [topo, base] = rolante ? [100, 300] : [200, 244];
129
+ return { top: topo, bottom: base, left: 0, right: 0, width: 0, height: base - topo, x: 0, y: topo, toJSON() { } };
130
+ });
131
+ Object.defineProperty(window, "innerHeight", { value: 900, configurable: true });
132
+ const { container } = render(_jsx("div", { "data-rolante": true, style: { overflowY: "auto" }, children: _jsx(Select, { ariaLabel: "x", options: OPCOES, placement: "auto" }) }));
133
+ fireEvent.click(screen.getByRole("combobox"));
134
+ expect(container.querySelector(".umds-select--placement-top")).not.toBeNull();
135
+ expect(container.querySelector(".umds-select__dropdown").style.maxHeight).toBe("96px");
136
+ });
137
+ it("sem ancestral que corta, só a janela conta e a lista não ganha teto", () => {
138
+ vi.spyOn(HTMLElement.prototype, "getBoundingClientRect").mockImplementation(() => ({ top: 20, bottom: 64, left: 0, right: 0, width: 0, height: 44, x: 0, y: 20, toJSON() { } }));
139
+ Object.defineProperty(window, "innerHeight", { value: 900, configurable: true });
140
+ const { container } = render(_jsx(Select, { ariaLabel: "x", options: OPCOES, placement: "auto" }));
141
+ fireEvent.click(screen.getByRole("combobox"));
142
+ expect(container.querySelector(".umds-select--placement-top")).toBeNull();
143
+ expect(container.querySelector(".umds-select__dropdown").style.maxHeight).toBe("");
144
+ });
145
+ });
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,77 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { describe, expect, it } from "vitest";
3
+ import { fireEvent, render, screen } from "@testing-library/react";
4
+ import Select from "../components/Select/Select";
5
+ const MARCADORES = [
6
+ { label: "Urgente", value: "urgente", color: "var(--umds-semantic-color-feedback-negative-pure)" },
7
+ { label: "Revisão", value: "revisao", color: "var(--umds-semantic-color-primary-pure)" },
8
+ { label: "Sem marcador", value: "nenhum" },
9
+ ];
10
+ describe("Select filtro · tamanho e fundo", () => {
11
+ it("as variantes de filtro nascem no tamanho sm; size explícito manda; o padrão segue md", () => {
12
+ const { container, rerender } = render(_jsx(Select, { ariaLabel: "x", options: MARCADORES, variant: "filter" }));
13
+ const raiz = () => container.firstElementChild;
14
+ expect(raiz()).toHaveClass("umds-select--sm");
15
+ rerender(_jsx(Select, { ariaLabel: "x", options: MARCADORES, variant: "search" }));
16
+ expect(raiz()).toHaveClass("umds-select--sm");
17
+ rerender(_jsx(Select, { ariaLabel: "x", options: MARCADORES, variant: "combo" }));
18
+ expect(raiz()).toHaveClass("umds-select--sm");
19
+ rerender(_jsx(Select, { ariaLabel: "x", options: MARCADORES, variant: "filter", size: "md" }));
20
+ expect(raiz()).toHaveClass("umds-select--md");
21
+ rerender(_jsx(Select, { ariaLabel: "x", options: MARCADORES }));
22
+ expect(raiz()).toHaveClass("umds-select--md");
23
+ expect(raiz()).not.toHaveClass("umds-select--sm");
24
+ });
25
+ it("o azul-claro do gatilho só vem com valor escolhido (--has-value); sem valor, não", () => {
26
+ const { container, rerender } = render(_jsx(Select, { ariaLabel: "x", options: MARCADORES, variant: "filter", placeholder: "Marcadores" }));
27
+ const raiz = () => container.firstElementChild;
28
+ expect(raiz()).not.toHaveClass("umds-select--has-value");
29
+ rerender(_jsx(Select, { ariaLabel: "x", options: MARCADORES, variant: "filter", placeholder: "Marcadores", value: "urgente" }));
30
+ expect(raiz()).toHaveClass("umds-select--has-value");
31
+ rerender(_jsx(Select, { ariaLabel: "x", options: MARCADORES, placeholder: "Marcadores", value: "urgente" }));
32
+ expect(raiz()).not.toHaveClass("umds-select--has-value");
33
+ });
34
+ it("o valor vazio do emptyOptionLabel volta ao estado sem valor", () => {
35
+ const { container } = render(_jsx(Select, { ariaLabel: "x", options: MARCADORES, variant: "filter", placeholder: "Marcadores", emptyOptionLabel: "Todos", value: "" }));
36
+ expect(container.firstElementChild).not.toHaveClass("umds-select--has-value");
37
+ });
38
+ });
39
+ describe("Select · cor por opção", () => {
40
+ it("a lista mostra uma amostra por opção com color; sem color, não", () => {
41
+ const { container } = render(_jsx(Select, { ariaLabel: "x", options: MARCADORES, variant: "filter" }));
42
+ fireEvent.click(screen.getByRole("combobox"));
43
+ const opcoes = [...container.querySelectorAll('[role="option"]')];
44
+ expect(opcoes[0].querySelector(".umds-select__swatch")).toHaveAttribute("aria-hidden", "true");
45
+ expect(opcoes[0].querySelector(".umds-select__swatch").style.background).toContain("--umds-semantic-color-feedback-negative-pure");
46
+ expect(opcoes[1].querySelector(".umds-select__swatch")).not.toBeNull();
47
+ expect(opcoes[2].querySelector(".umds-select__swatch")).toBeNull();
48
+ });
49
+ it("o gatilho ganha a cor da opção escolhida (seleção única)", () => {
50
+ const { container } = render(_jsx(Select, { ariaLabel: "x", options: MARCADORES, variant: "filter", placeholder: "Marcadores", value: "revisao" }));
51
+ const amostra = container.querySelector(".umds-select__trigger .umds-select__swatch");
52
+ expect(amostra.style.background).toContain("--umds-semantic-color-primary-pure");
53
+ });
54
+ it("opção escolhida sem color e estado sem valor: o gatilho não tem amostra", () => {
55
+ const { container, rerender } = render(_jsx(Select, { ariaLabel: "x", options: MARCADORES, placeholder: "Marcadores", value: "nenhum" }));
56
+ expect(container.querySelector(".umds-select__trigger .umds-select__swatch")).toBeNull();
57
+ rerender(_jsx(Select, { ariaLabel: "x", options: MARCADORES, placeholder: "Marcadores" }));
58
+ expect(container.querySelector(".umds-select__trigger .umds-select__swatch")).toBeNull();
59
+ });
60
+ it("triggerSwatch explícito manda sobre a cor da opção", () => {
61
+ const { container } = render(_jsx(Select, { ariaLabel: "x", options: MARCADORES, value: "urgente", triggerSwatch: "var(--umds-semantic-color-feedback-positive-pure)" }));
62
+ const amostras = container.querySelectorAll(".umds-select__trigger .umds-select__swatch");
63
+ expect(amostras).toHaveLength(1);
64
+ expect(amostras[0].style.background).toContain("--umds-semantic-color-feedback-positive-pure");
65
+ });
66
+ it("na seleção múltipla o gatilho não pinta amostra (são várias), mas a lista mostra as cores", () => {
67
+ const { container } = render(_jsx(Select, { ariaLabel: "x", options: MARCADORES, multiple: true, value: ["urgente", "revisao"] }));
68
+ expect(container.querySelector(".umds-select__trigger .umds-select__swatch")).toBeNull();
69
+ fireEvent.click(screen.getByRole("combobox"));
70
+ expect(container.querySelectorAll('[role="option"] .umds-select__swatch')).toHaveLength(2);
71
+ });
72
+ it("a cor não vira texto nem entra no nome acessível da opção", () => {
73
+ render(_jsx(Select, { ariaLabel: "x", options: MARCADORES }));
74
+ fireEvent.click(screen.getByRole("combobox"));
75
+ expect(screen.getByRole("option", { name: "Urgente" })).toBeInTheDocument();
76
+ });
77
+ });
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,88 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { afterEach, describe, expect, it, vi } from "vitest";
3
+ import { fireEvent, render, screen } from "@testing-library/react";
4
+ import Select from "../components/Select/Select";
5
+ const OPCOES = [
6
+ { label: "Urgente", value: "urgente" },
7
+ { label: "Revisão", value: "revisao" },
8
+ ];
9
+ afterEach(() => vi.restoreAllMocks());
10
+ /** jsdom não tem layout: o gatilho "mede" o que o teste mandar. */
11
+ function medirGatilho(topo, base, alturaDaTela) {
12
+ vi.spyOn(HTMLElement.prototype, "getBoundingClientRect").mockImplementation(() => ({ top: topo, bottom: base, left: 0, right: 0, width: 0, height: base - topo, x: 0, y: topo, toJSON() { } }));
13
+ Object.defineProperty(window, "innerHeight", { value: alturaDaTela, configurable: true });
14
+ }
15
+ describe("Select · placement", () => {
16
+ it("padrão abre para baixo", () => {
17
+ const { container } = render(_jsx(Select, { ariaLabel: "x", options: OPCOES }));
18
+ fireEvent.click(screen.getByRole("combobox"));
19
+ expect(container.querySelector(".umds-select--placement-top")).toBeNull();
20
+ });
21
+ it("top abre para cima", () => {
22
+ const { container } = render(_jsx(Select, { ariaLabel: "x", options: OPCOES, placement: "top" }));
23
+ fireEvent.click(screen.getByRole("combobox"));
24
+ expect(container.querySelector(".umds-select--placement-top")).not.toBeNull();
25
+ });
26
+ it("auto abre para cima quando falta espaço embaixo e há mais em cima", () => {
27
+ medirGatilho(500, 544, 600);
28
+ const { container } = render(_jsx(Select, { ariaLabel: "x", options: OPCOES, placement: "auto" }));
29
+ fireEvent.click(screen.getByRole("combobox"));
30
+ expect(container.querySelector(".umds-select--placement-top")).not.toBeNull();
31
+ });
32
+ it("auto abre para baixo quando cabe", () => {
33
+ medirGatilho(20, 64, 900);
34
+ const { container } = render(_jsx(Select, { ariaLabel: "x", options: OPCOES, placement: "auto" }));
35
+ fireEvent.click(screen.getByRole("combobox"));
36
+ expect(container.querySelector(".umds-select--placement-top")).toBeNull();
37
+ });
38
+ it("auto abre para baixo quando falta espaço dos dois lados e embaixo é maior", () => {
39
+ medirGatilho(60, 104, 220);
40
+ const { container } = render(_jsx(Select, { ariaLabel: "x", options: OPCOES, placement: "auto" }));
41
+ fireEvent.click(screen.getByRole("combobox"));
42
+ expect(container.querySelector(".umds-select--placement-top")).toBeNull();
43
+ });
44
+ });
45
+ describe("Select · variant filter", () => {
46
+ it("escreve a classe do filtro; sem variant não escreve", () => {
47
+ const { container, rerender } = render(_jsx(Select, { ariaLabel: "x", options: OPCOES, variant: "filter" }));
48
+ expect(container.querySelector(".umds-select--filter")).not.toBeNull();
49
+ rerender(_jsx(Select, { ariaLabel: "x", options: OPCOES }));
50
+ expect(container.querySelector(".umds-select--filter")).toBeNull();
51
+ });
52
+ it("emptyOptionLabel vem no topo, marcada sem seleção; escolher chama onChange com vazio e volta ao placeholder", () => {
53
+ const aoMudar = vi.fn();
54
+ const { rerender } = render(_jsx(Select, { ariaLabel: "Marcadores", placeholder: "Marcadores", options: OPCOES, emptyOptionLabel: "Todos os marcadores", onChange: aoMudar }));
55
+ fireEvent.click(screen.getByRole("combobox"));
56
+ const opcoes = screen.getAllByRole("option");
57
+ expect(opcoes[0]).toHaveTextContent("Todos os marcadores");
58
+ expect(opcoes[0]).toHaveAttribute("aria-selected", "true");
59
+ fireEvent.click(opcoes[1]);
60
+ expect(aoMudar).toHaveBeenLastCalledWith("urgente");
61
+ rerender(_jsx(Select, { ariaLabel: "Marcadores", placeholder: "Marcadores", options: OPCOES, emptyOptionLabel: "Todos os marcadores", value: "urgente", onChange: aoMudar }));
62
+ expect(screen.getByRole("combobox")).toHaveTextContent("Urgente");
63
+ fireEvent.click(screen.getByRole("combobox"));
64
+ fireEvent.click(screen.getAllByRole("option")[0]);
65
+ expect(aoMudar).toHaveBeenLastCalledWith("");
66
+ rerender(_jsx(Select, { ariaLabel: "Marcadores", placeholder: "Marcadores", options: OPCOES, emptyOptionLabel: "Todos os marcadores", value: "", onChange: aoMudar }));
67
+ expect(screen.getByRole("combobox")).toHaveTextContent("Marcadores");
68
+ });
69
+ it("sem emptyOptionLabel não há opção extra", () => {
70
+ render(_jsx(Select, { ariaLabel: "x", options: OPCOES }));
71
+ fireEvent.click(screen.getByRole("combobox"));
72
+ expect(screen.getAllByRole("option")).toHaveLength(2);
73
+ });
74
+ it("footer aparece dentro da lista aberta, e não fecha ao clicar nele", () => {
75
+ render(_jsx(Select, { ariaLabel: "x", options: OPCOES, footer: _jsx("button", { children: "Gerenciar marcadores" }) }));
76
+ expect(screen.queryByText("Gerenciar marcadores")).toBeNull();
77
+ fireEvent.click(screen.getByRole("combobox"));
78
+ const acao = screen.getByText("Gerenciar marcadores");
79
+ expect(acao.closest(".umds-select__footer")).not.toBeNull();
80
+ fireEvent.mouseDown(acao);
81
+ expect(screen.getByRole("combobox")).toHaveAttribute("aria-expanded", "true");
82
+ });
83
+ it("sem footer não há rodapé", () => {
84
+ const { container } = render(_jsx(Select, { ariaLabel: "x", options: OPCOES }));
85
+ fireEvent.click(screen.getByRole("combobox"));
86
+ expect(container.querySelector(".umds-select__footer")).toBeNull();
87
+ });
88
+ });
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,57 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { describe, expect, it, vi } from "vitest";
3
+ import { fireEvent, render, screen } from "@testing-library/react";
4
+ import Stack from "../components/Stack/Stack";
5
+ const TAGS = ["div", "span", "ul", "ol", "li", "section", "nav", "header", "footer", "form"];
6
+ describe("Stack", () => {
7
+ it("sem props continua um div vertical com gap xxxs", () => {
8
+ const { container } = render(_jsx(Stack, { children: "x" }));
9
+ const el = container.firstElementChild;
10
+ expect(el.tagName).toBe("DIV");
11
+ expect(el.className).toBe("umds-stack umds-stack--vertical umds-stack--gap-xxxs");
12
+ });
13
+ it("aceita gap none", () => {
14
+ const { container } = render(_jsx(Stack, { gap: "none", children: "x" }));
15
+ expect(container.firstElementChild).toHaveClass("umds-stack--gap-none");
16
+ });
17
+ it.each(TAGS)("as=%s renderiza o elemento certo", (tag) => {
18
+ const { container } = render(_jsx(Stack, { as: tag, children: "x" }));
19
+ expect(container.firstElementChild?.tagName.toLowerCase()).toBe(tag);
20
+ });
21
+ it("ul e ol mantêm a semântica de lista", () => {
22
+ const { container } = render(_jsx(Stack, { as: "ul", "aria-label": "Itens", children: _jsx(Stack, { as: "li", children: "um" }) }));
23
+ expect(screen.getByRole("list", { name: "Itens" })).toBeInTheDocument();
24
+ expect(container.querySelectorAll("li")).toHaveLength(1);
25
+ });
26
+ it("repassa id, aria-label, title e style ao elemento raiz", () => {
27
+ const { container } = render(_jsx(Stack, { as: "nav", id: "menu", "aria-label": "Principal", title: "Dica", style: { marginTop: 4 }, children: "x" }));
28
+ const el = container.firstElementChild;
29
+ expect(el.id).toBe("menu");
30
+ expect(el.getAttribute("aria-label")).toBe("Principal");
31
+ expect(el.getAttribute("title")).toBe("Dica");
32
+ expect(el.style.marginTop).toBe("4px");
33
+ expect(screen.getByRole("navigation", { name: "Principal" })).toBe(el);
34
+ });
35
+ it("as=form chama onSubmit", () => {
36
+ const aoEnviar = vi.fn((e) => e.preventDefault());
37
+ const { container } = render(_jsx(Stack, { as: "form", onSubmit: aoEnviar, children: _jsx("button", { type: "submit", children: "Enviar" }) }));
38
+ fireEvent.submit(container.querySelector("form"));
39
+ expect(aoEnviar).toHaveBeenCalledTimes(1);
40
+ });
41
+ it("escreve as classes de item flex", () => {
42
+ const { container } = render(_jsx(Stack, { grow: true, shrink: "0", basis: "50", minWidth: "auto", overflow: "hidden", overflowY: "auto", fullHeight: true, children: "x" }));
43
+ const el = container.firstElementChild;
44
+ for (const c of [
45
+ "umds-stack--grow",
46
+ "umds-stack--shrink-0",
47
+ "umds-stack--basis-50",
48
+ "umds-stack--min-w-auto",
49
+ "umds-stack--overflow-hidden",
50
+ "umds-stack--overflow-y-auto",
51
+ "umds-stack--full-height",
52
+ ]) {
53
+ expect(el).toHaveClass(c);
54
+ }
55
+ expect(el).not.toHaveClass("umds-stack--full-width");
56
+ });
57
+ });
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,34 @@
1
+ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { describe, expect, it } from "vitest";
3
+ import { render, screen } from "@testing-library/react";
4
+ import StatCard from "../components/StatCard/StatCard";
5
+ const raiz = (c) => c.firstElementChild;
6
+ describe("StatCard · labelPosition", () => {
7
+ it("top escreve a classe; sem a prop o cartão é o de antes", () => {
8
+ const { container } = render(_jsxs(_Fragment, { children: [_jsx(StatCard, { value: 44, label: "N\u00E3o lidos", labelPosition: "top" }), _jsx(StatCard, { value: 44, label: "N\u00E3o lidos" })] }));
9
+ expect(container.children[0]).toHaveClass("umds-stat-card--rotulo-topo");
10
+ expect(container.children[1]).not.toHaveClass("umds-stat-card--rotulo-topo");
11
+ });
12
+ it("o número continua antes do rótulo no HTML (ordem do leitor de tela)", () => {
13
+ const { container } = render(_jsx(StatCard, { value: 44, label: "N\u00E3o lidos", labelPosition: "top" }));
14
+ const valor = container.querySelector(".umds-stat-card__valor");
15
+ const rotulo = container.querySelector(".umds-stat-card__rotulo");
16
+ expect(valor.compareDocumentPosition(rotulo) & Node.DOCUMENT_POSITION_FOLLOWING).toBeTruthy();
17
+ });
18
+ });
19
+ describe("StatCard · infoTooltip", () => {
20
+ it("mostra o ⓘ como botão nomeado, dentro do rótulo, descrito pelo texto de ajuda", () => {
21
+ const { container } = render(_jsx(StatCard, { value: 44, label: "N\u00E3o lidos", infoTooltip: "Ainda n\u00E3o abertos por voc\u00EA." }));
22
+ const info = screen.getByRole("button", { name: "Mais informações" });
23
+ expect(container.querySelector(".umds-stat-card__rotulo")?.contains(info)).toBe(true);
24
+ expect(info).toHaveAccessibleDescription("Ainda não abertos por você.");
25
+ });
26
+ it("infoLabel traduz o nome do ⓘ", () => {
27
+ render(_jsx(StatCard, { value: 1, label: "Unread", infoTooltip: "Not opened yet.", infoLabel: "More info" }));
28
+ expect(screen.getByRole("button", { name: "More info" })).toBeInTheDocument();
29
+ });
30
+ it("sem infoTooltip não há botão", () => {
31
+ render(_jsx(StatCard, { value: 1, label: "x" }));
32
+ expect(screen.queryByRole("button")).toBeNull();
33
+ });
34
+ });
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,45 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { describe, expect, it } from "vitest";
3
+ import { render } from "@testing-library/react";
4
+ import StatCard from "../components/StatCard/StatCard";
5
+ describe("StatCard · segunda medida e valueTone", () => {
6
+ it("secondaryValue e secondaryLabel vêm depois do corpo, e o número principal segue antes do rótulo", () => {
7
+ const { container } = render(_jsx(StatCard, { value: "22,31%", label: "Efici\u00EAncia", description: "Meu Setor", secondaryValue: "14,11%", secondaryLabel: "Geral", labelPosition: "top" }));
8
+ const filhos = [...container.firstElementChild.children].map((e) => e.className);
9
+ expect(filhos[filhos.length - 1]).toBe("umds-stat-card__secundaria");
10
+ const secundaria = container.querySelector(".umds-stat-card__secundaria");
11
+ expect(secundaria.querySelector(".umds-stat-card__valor-secundario")).toHaveTextContent("14,11%");
12
+ expect(secundaria.querySelector(".umds-stat-card__rotulo-secundario")).toHaveTextContent("Geral");
13
+ expect(container.firstElementChild).toHaveClass("umds-stat-card--com-secundaria");
14
+ const texto = container.firstElementChild.textContent;
15
+ expect(texto.indexOf("22,31%")).toBeLessThan(texto.indexOf("Eficiência"));
16
+ expect(texto.indexOf("Eficiência")).toBeLessThan(texto.indexOf("14,11%"));
17
+ });
18
+ it("secondaryValue 0 aparece; vazio e ausente não", () => {
19
+ const { container, rerender } = render(_jsx(StatCard, { value: "5", label: "x", secondaryValue: 0 }));
20
+ expect(container.querySelector(".umds-stat-card__valor-secundario")).toHaveTextContent("0");
21
+ rerender(_jsx(StatCard, { value: "5", label: "x", secondaryValue: "" }));
22
+ expect(container.querySelector(".umds-stat-card__secundaria")).toBeNull();
23
+ rerender(_jsx(StatCard, { value: "5", label: "x" }));
24
+ expect(container.querySelector(".umds-stat-card__secundaria")).toBeNull();
25
+ expect(container.firstElementChild).not.toHaveClass("umds-stat-card--com-secundaria");
26
+ });
27
+ it("secondaryValue sem secondaryLabel não desenha o rótulo", () => {
28
+ const { container } = render(_jsx(StatCard, { value: "5", label: "x", secondaryValue: "9" }));
29
+ expect(container.querySelector(".umds-stat-card__rotulo-secundario")).toBeNull();
30
+ });
31
+ it("valueTone escreve a classe do tom; default e ausente não", () => {
32
+ const { container, rerender } = render(_jsx(StatCard, { value: "5", label: "x", valueTone: "negative" }));
33
+ expect(container.firstElementChild).toHaveClass("umds-stat-card--valor-negative");
34
+ rerender(_jsx(StatCard, { value: "5", label: "x", valueTone: "primary" }));
35
+ expect(container.firstElementChild).toHaveClass("umds-stat-card--valor-primary");
36
+ rerender(_jsx(StatCard, { value: "5", label: "x", valueTone: "default" }));
37
+ expect(container.firstElementChild.className).not.toMatch(/valor-/);
38
+ rerender(_jsx(StatCard, { value: "5", label: "x" }));
39
+ expect(container.firstElementChild.className).not.toMatch(/valor-/);
40
+ });
41
+ it("valueTone não mexe na variant do ícone", () => {
42
+ const { container } = render(_jsx(StatCard, { value: "5", label: "x", variant: "positive", valueTone: "negative" }));
43
+ expect(container.firstElementChild).toHaveClass("umds-stat-card--positive", "umds-stat-card--valor-negative");
44
+ });
45
+ });
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,79 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { describe, expect, it, vi } from "vitest";
3
+ import { fireEvent, render, screen } from "@testing-library/react";
4
+ import Tabs from "../components/Tabs/Tabs";
5
+ import Tab from "../components/Tabs/Tab";
6
+ describe("Tab · count", () => {
7
+ it("mostra o contador em pílula e ele entra no nome da aba", () => {
8
+ render(_jsxs(Tabs, { value: "0", ariaLabel: "Tarefas", children: [_jsx(Tab, { label: "Todas", index: "0", count: 31 }), _jsx(Tab, { label: "Atribu\u00EDdas", index: "1", count: 9 })] }));
9
+ expect(screen.getByRole("tab", { name: "Todas 31" })).toBeInTheDocument();
10
+ expect(screen.getByRole("tab", { name: "Atribuídas 9" })).toBeInTheDocument();
11
+ });
12
+ it("o 0 aparece; sem count, não há pílula", () => {
13
+ const { container } = render(_jsxs(Tabs, { value: "0", children: [_jsx(Tab, { label: "Conclu\u00EDdas", index: "0", count: 0 }), _jsx(Tab, { label: "Sem contador", index: "1" })] }));
14
+ const pilulas = container.querySelectorAll(".umds-tabs__count");
15
+ expect(pilulas).toHaveLength(1);
16
+ expect(pilulas[0].textContent).toBe("0");
17
+ });
18
+ it("a pílula fica dentro da aba selecionada (que a pinta de azul pelo CSS)", () => {
19
+ const { container } = render(_jsxs(Tabs, { value: "1", children: [_jsx(Tab, { label: "A", index: "0", count: 1 }), _jsx(Tab, { label: "B", index: "1", count: 2 })] }));
20
+ const selecionada = container.querySelector(".umds-tabs__tab--selected");
21
+ expect(selecionada?.querySelector(".umds-tabs__count")?.textContent).toBe("2");
22
+ });
23
+ });
24
+ describe("Tab · closable", () => {
25
+ it("o × é um botão irmão da aba, com o nome 'Fechar <aba>'", () => {
26
+ render(_jsx(Tabs, { value: "0", children: _jsx(Tab, { label: "Documento 1", index: "0", closable: true }) }));
27
+ const fechar = screen.getByRole("button", { name: "Fechar Documento 1" });
28
+ const aba = screen.getByRole("tab");
29
+ expect(aba.contains(fechar)).toBe(false);
30
+ expect(fechar.parentElement).toBe(aba.parentElement);
31
+ });
32
+ it("o rótulo do × vem por prop", () => {
33
+ render(_jsx(Tabs, { value: "0", children: _jsx(Tab, { label: "Doc 1", index: "0", closable: true, closeLabel: "Close" }) }));
34
+ expect(screen.getByRole("button", { name: "Close Doc 1" })).toBeInTheDocument();
35
+ });
36
+ it("clicar no × chama onClose com o index e não troca de aba", () => {
37
+ const aoFechar = vi.fn();
38
+ const aoTrocar = vi.fn();
39
+ render(_jsxs(Tabs, { value: "0", onChange: aoTrocar, children: [_jsx(Tab, { label: "Um", index: "0" }), _jsx(Tab, { label: "Dois", index: "1", closable: true, onClose: aoFechar })] }));
40
+ fireEvent.click(screen.getByRole("button", { name: "Fechar Dois" }));
41
+ expect(aoFechar).toHaveBeenCalledTimes(1);
42
+ expect(aoFechar.mock.calls[0][0]).toBe("1");
43
+ expect(aoTrocar).not.toHaveBeenCalled();
44
+ });
45
+ it("Delete na aba focada fecha; sem closable, não", () => {
46
+ const aoFechar = vi.fn();
47
+ render(_jsxs(Tabs, { value: "0", children: [_jsx(Tab, { label: "Fech\u00E1vel", index: "0", closable: true, onClose: aoFechar }), _jsx(Tab, { label: "Fixa", index: "1", onClose: aoFechar })] }));
48
+ fireEvent.keyDown(screen.getByRole("tab", { name: "Fechável" }), { key: "Delete" });
49
+ expect(aoFechar).toHaveBeenCalledTimes(1);
50
+ fireEvent.keyDown(screen.getByRole("tab", { name: "Fixa" }), { key: "Delete" });
51
+ expect(aoFechar).toHaveBeenCalledTimes(1);
52
+ });
53
+ it("sem closable não há ×", () => {
54
+ render(_jsx(Tabs, { value: "0", children: _jsx(Tab, { label: "Fixa", index: "0" }) }));
55
+ expect(screen.queryByRole("button")).toBeNull();
56
+ });
57
+ it("o tablist só tem abas como filhas de papel (o × não é tab)", () => {
58
+ render(_jsxs(Tabs, { value: "0", children: [_jsx(Tab, { label: "A", index: "0", closable: true }), _jsx(Tab, { label: "B", index: "1", closable: true })] }));
59
+ expect(screen.getAllByRole("tab")).toHaveLength(2);
60
+ });
61
+ });
62
+ describe("Tabs · onAdd", () => {
63
+ it("mostra o + fora do tablist e chama onAdd", () => {
64
+ const aoAdicionar = vi.fn();
65
+ render(_jsx(Tabs, { value: "0", onAdd: aoAdicionar, children: _jsx(Tab, { label: "A", index: "0" }) }));
66
+ const mais = screen.getByRole("button", { name: "Adicionar aba" });
67
+ expect(screen.getByRole("tablist").contains(mais)).toBe(false);
68
+ fireEvent.click(mais);
69
+ expect(aoAdicionar).toHaveBeenCalledTimes(1);
70
+ });
71
+ it("o rótulo do + vem por prop", () => {
72
+ render(_jsx(Tabs, { value: "0", onAdd: () => { }, addLabel: "New tab", children: _jsx(Tab, { label: "A", index: "0" }) }));
73
+ expect(screen.getByRole("button", { name: "New tab" })).toBeInTheDocument();
74
+ });
75
+ it("sem onAdd não há botão", () => {
76
+ render(_jsx(Tabs, { value: "0", children: _jsx(Tab, { label: "A", index: "0" }) }));
77
+ expect(screen.queryByRole("button")).toBeNull();
78
+ });
79
+ });
@@ -0,0 +1 @@
1
+ export {};