@1doc/1ds-react 2.7.2 → 2.9.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 (302) hide show
  1. package/CHANGELOG.md +1280 -0
  2. package/dist/components/AIContent/AIContent.d.ts +10 -0
  3. package/dist/components/AIContent/AIContent.js +1 -1
  4. package/dist/components/AILabel/AILabel.d.ts +4 -0
  5. package/dist/components/AILabel/AILabel.js +2 -2
  6. package/dist/components/Accordion/Accordion.d.ts +6 -2
  7. package/dist/components/Alert/Alert.css +2 -0
  8. package/dist/components/Alert/Alert.d.ts +3 -1
  9. package/dist/components/Alert/Alert.js +7 -1
  10. package/dist/components/AppHeader/AppHeader.css +82 -8
  11. package/dist/components/AppHeader/AppHeader.d.ts +12 -1
  12. package/dist/components/AppHeader/AppHeader.js +186 -1
  13. package/dist/components/AppNavItem/AppNavItem.css +11 -3
  14. package/dist/components/AppShell/AppShell.css +9 -0
  15. package/dist/components/AppShell/AppShell.d.ts +8 -0
  16. package/dist/components/AppShell/AppShell.js +4 -1
  17. package/dist/components/AppSidebar/AppSidebar.css +1 -1
  18. package/dist/components/AppSidebar/AppSidebar.d.ts +4 -0
  19. package/dist/components/AppSidebar/AppSidebar.js +3 -1
  20. package/dist/components/AttachmentCard/AttachmentCard.css +17 -1
  21. package/dist/components/AttachmentCard/AttachmentCard.d.ts +29 -2
  22. package/dist/components/AttachmentCard/AttachmentCard.js +88 -20
  23. package/dist/components/Avatar/Avatar.css +7 -2
  24. package/dist/components/Avatar/AvatarGroup.d.ts +27 -0
  25. package/dist/components/Avatar/AvatarGroup.js +28 -4
  26. package/dist/components/Badge/Badge.css +61 -3
  27. package/dist/components/Badge/Badge.d.ts +14 -4
  28. package/dist/components/Badge/Badge.js +1 -0
  29. package/dist/components/BottomSheet/BottomSheet.css +1 -0
  30. package/dist/components/BottomSheet/BottomSheet.d.ts +8 -0
  31. package/dist/components/BottomSheet/BottomSheet.js +14 -2
  32. package/dist/components/Box/Box.css +83 -0
  33. package/dist/components/Box/Box.d.ts +82 -2
  34. package/dist/components/Box/Box.js +42 -2
  35. package/dist/components/Button/Button.css +29 -0
  36. package/dist/components/Button/Button.d.ts +4 -4
  37. package/dist/components/Button/Button.js +4 -1
  38. package/dist/components/Calendar/Calendar.css +245 -0
  39. package/dist/components/Calendar/Calendar.d.ts +125 -0
  40. package/dist/components/Calendar/Calendar.js +320 -0
  41. package/dist/components/Chart/BarChart.d.ts +6 -0
  42. package/dist/components/Chart/BarChart.js +3 -1
  43. package/dist/components/Chart/LineChart.d.ts +6 -0
  44. package/dist/components/Chart/LineChart.js +3 -1
  45. package/dist/components/Checkbox/Checkbox.css +4 -1
  46. package/dist/components/Chips/Chips.css +39 -0
  47. package/dist/components/Chips/Chips.d.ts +7 -2
  48. package/dist/components/Chips/Chips.js +6 -2
  49. package/dist/components/Coachmark/Coachmark.css +118 -0
  50. package/dist/components/Coachmark/Coachmark.d.ts +75 -0
  51. package/dist/components/Coachmark/Coachmark.js +321 -0
  52. package/dist/components/CodeBlock/CodeBlock.css +96 -0
  53. package/dist/components/CodeBlock/CodeBlock.d.ts +47 -0
  54. package/dist/components/CodeBlock/CodeBlock.js +103 -0
  55. package/dist/components/ColorPicker/ColorPicker.css +133 -0
  56. package/dist/components/ColorPicker/ColorPicker.d.ts +73 -0
  57. package/dist/components/ColorPicker/ColorPicker.js +219 -0
  58. package/dist/components/Combobox/Combobox.css +11 -3
  59. package/dist/components/ConfirmAIAction/ConfirmAIAction.d.ts +11 -1
  60. package/dist/components/ConfirmAIAction/ConfirmAIAction.js +6 -1
  61. package/dist/components/ConfirmDialog/ConfirmDialog.css +3 -0
  62. package/dist/components/ConfirmDialog/ConfirmDialog.d.ts +14 -0
  63. package/dist/components/ConfirmDialog/ConfirmDialog.js +2 -2
  64. package/dist/components/DataTable/DataTable.css +80 -0
  65. package/dist/components/DataTable/DataTable.d.ts +23 -4
  66. package/dist/components/DataTable/DataTable.js +61 -15
  67. package/dist/components/DatePicker/DatePicker.css +8 -0
  68. package/dist/components/DatePicker/DatePicker.d.ts +4 -0
  69. package/dist/components/DatePicker/DatePicker.js +14 -1
  70. package/dist/components/DescriptionList/DescriptionList.css +113 -0
  71. package/dist/components/DescriptionList/DescriptionList.d.ts +59 -0
  72. package/dist/components/DescriptionList/DescriptionList.js +51 -0
  73. package/dist/components/Drawer/Drawer.css +1 -0
  74. package/dist/components/Dropdown/Dropdown.js +47 -29
  75. package/dist/components/FileInput/FileInput.css +24 -4
  76. package/dist/components/FileInput/FileInput.d.ts +22 -2
  77. package/dist/components/FileInput/FileInput.js +23 -2
  78. package/dist/components/Grid/Grid.js +5 -5
  79. package/dist/components/IconPicker/IconPicker.css +107 -0
  80. package/dist/components/IconPicker/IconPicker.d.ts +74 -0
  81. package/dist/components/IconPicker/IconPicker.js +194 -0
  82. package/dist/components/Input/Input.css +41 -3
  83. package/dist/components/Input/Input.d.ts +14 -1
  84. package/dist/components/Input/Input.js +72 -6
  85. package/dist/components/Kanban/Kanban.css +5 -0
  86. package/dist/components/Kanban/Kanban.d.ts +41 -0
  87. package/dist/components/Kanban/Kanban.js +59 -27
  88. package/dist/components/Kanban/KanbanCard.d.ts +2 -0
  89. package/dist/components/Kanban/KanbanCard.js +1 -1
  90. package/dist/components/Kanban/KanbanColumn.d.ts +2 -0
  91. package/dist/components/Kanban/KanbanColumn.js +3 -0
  92. package/dist/components/Kbd/Kbd.css +66 -0
  93. package/dist/components/Kbd/Kbd.d.ts +32 -0
  94. package/dist/components/Kbd/Kbd.js +40 -0
  95. package/dist/components/Link/Link.css +1 -1
  96. package/dist/components/List/List.css +136 -0
  97. package/dist/components/List/List.d.ts +82 -0
  98. package/dist/components/List/List.js +53 -0
  99. package/dist/components/List/ListItem.d.ts +85 -0
  100. package/dist/components/List/ListItem.js +81 -0
  101. package/dist/components/Modal/Modal.css +93 -8
  102. package/dist/components/Modal/Modal.d.ts +45 -7
  103. package/dist/components/Modal/Modal.js +106 -6
  104. package/dist/components/MultiSelect/MultiSelect.css +9 -1
  105. package/dist/components/MultiSelect/MultiSelect.js +45 -8
  106. package/dist/components/OrgChart/OrgChart.css +149 -0
  107. package/dist/components/OrgChart/OrgChart.d.ts +83 -0
  108. package/dist/components/OrgChart/OrgChart.js +297 -0
  109. package/dist/components/OtpInput/OtpInput.css +93 -0
  110. package/dist/components/OtpInput/OtpInput.d.ts +60 -0
  111. package/dist/components/OtpInput/OtpInput.js +215 -0
  112. package/dist/components/Pagination/Pagination.d.ts +6 -0
  113. package/dist/components/Pagination/Pagination.js +9 -1
  114. package/dist/components/PhoneInput/PhoneInput.css +9 -1
  115. package/dist/components/PhoneInput/PhoneInput.d.ts +10 -0
  116. package/dist/components/PhoneInput/PhoneInput.js +20 -3
  117. package/dist/components/Popover/Popover.d.ts +7 -0
  118. package/dist/components/Popover/Popover.js +11 -1
  119. package/dist/components/RichTextEditor/RichTextEditor.css +203 -0
  120. package/dist/components/RichTextEditor/RichTextEditor.d.ts +83 -0
  121. package/dist/components/RichTextEditor/RichTextEditor.js +494 -0
  122. package/dist/components/SegmentedControl/SegmentedControl.d.ts +2 -0
  123. package/dist/components/SegmentedControl/SegmentedControl.js +21 -8
  124. package/dist/components/Select/Select.css +71 -1
  125. package/dist/components/Select/Select.d.ts +12 -0
  126. package/dist/components/Select/Select.js +93 -10
  127. package/dist/components/SidePanel/SidePanel.css +4 -4
  128. package/dist/components/SidePanelItem/SidePanelItem.css +7 -5
  129. package/dist/components/SidePanelSearch/SidePanelSearch.css +2 -2
  130. package/dist/components/SidePanelSection/SidePanelSection.css +7 -5
  131. package/dist/components/Stack/Stack.css +49 -0
  132. package/dist/components/Stack/Stack.d.ts +65 -7
  133. package/dist/components/Stack/Stack.js +30 -2
  134. package/dist/components/StatCard/StatCard.css +73 -0
  135. package/dist/components/StatCard/StatCard.d.ts +17 -0
  136. package/dist/components/StatCard/StatCard.js +4 -1
  137. package/dist/components/Stepper/Stepper.css +4 -1
  138. package/dist/components/Stepper/Stepper.d.ts +8 -0
  139. package/dist/components/Stepper/Stepper.js +4 -4
  140. package/dist/components/Switch/Switch.css +1 -0
  141. package/dist/components/Tabs/Tab.d.ts +15 -0
  142. package/dist/components/Tabs/Tab.js +30 -1
  143. package/dist/components/Tabs/Tabs.css +132 -0
  144. package/dist/components/Tabs/Tabs.d.ts +7 -0
  145. package/dist/components/Tabs/Tabs.js +13 -2
  146. package/dist/components/Tag/Tag.css +85 -2
  147. package/dist/components/Tag/Tag.d.ts +13 -6
  148. package/dist/components/Tag/Tag.js +1 -0
  149. package/dist/components/Text/Text.d.ts +9 -1
  150. package/dist/components/Text/Text.js +2 -2
  151. package/dist/components/Textarea/Textarea.css +11 -3
  152. package/dist/components/TimePicker/TimePicker.css +8 -0
  153. package/dist/components/TimePicker/TimePicker.d.ts +6 -0
  154. package/dist/components/TimePicker/TimePicker.js +1 -1
  155. package/dist/components/Tooltip/Tooltip.css +40 -0
  156. package/dist/components/Tooltip/Tooltip.d.ts +11 -0
  157. package/dist/components/Tooltip/Tooltip.js +114 -11
  158. package/dist/index.d.ts +25 -0
  159. package/dist/index.js +14 -0
  160. package/dist/teste/AILabel.test.d.ts +1 -0
  161. package/dist/teste/AILabel.test.js +33 -0
  162. package/dist/teste/AccordionConteudoLivre.test.d.ts +1 -0
  163. package/dist/teste/AccordionConteudoLivre.test.js +29 -0
  164. package/dist/teste/Alert.test.d.ts +1 -0
  165. package/dist/teste/Alert.test.js +27 -0
  166. package/dist/teste/AtributosRepassados.test.d.ts +1 -0
  167. package/dist/teste/AtributosRepassados.test.js +52 -0
  168. package/dist/teste/AttachmentCardIA.test.d.ts +1 -0
  169. package/dist/teste/AttachmentCardIA.test.js +89 -0
  170. package/dist/teste/AvatarGroupOverlap.test.d.ts +1 -0
  171. package/dist/teste/AvatarGroupOverlap.test.js +56 -0
  172. package/dist/teste/BadgeTag.test.d.ts +1 -0
  173. package/dist/teste/BadgeTag.test.js +42 -0
  174. package/dist/teste/BottomSheet.test.d.ts +1 -0
  175. package/dist/teste/BottomSheet.test.js +23 -0
  176. package/dist/teste/BoxItemFlex.test.d.ts +1 -0
  177. package/dist/teste/BoxItemFlex.test.js +54 -0
  178. package/dist/teste/BoxLayout.test.d.ts +1 -0
  179. package/dist/teste/BoxLayout.test.js +35 -0
  180. package/dist/teste/Button.test.d.ts +1 -0
  181. package/dist/teste/Button.test.js +27 -0
  182. package/dist/teste/Calendar.test.d.ts +1 -0
  183. package/dist/teste/Calendar.test.js +221 -0
  184. package/dist/teste/ChipsXs.test.d.ts +1 -0
  185. package/dist/teste/ChipsXs.test.js +31 -0
  186. package/dist/teste/Coachmark.test.d.ts +1 -0
  187. package/dist/teste/Coachmark.test.js +149 -0
  188. package/dist/teste/ColorPicker.test.d.ts +1 -0
  189. package/dist/teste/ColorPicker.test.js +132 -0
  190. package/dist/teste/ConfirmAIAction.test.d.ts +1 -0
  191. package/dist/teste/ConfirmAIAction.test.js +33 -0
  192. package/dist/teste/DataTableCelulaLivre.test.d.ts +1 -0
  193. package/dist/teste/DataTableCelulaLivre.test.js +76 -0
  194. package/dist/teste/DataTableDocumento.test.d.ts +1 -0
  195. package/dist/teste/DataTableDocumento.test.js +92 -0
  196. package/dist/teste/DatePicker.test.js +23 -0
  197. package/dist/teste/Dropdown.test.js +111 -0
  198. package/dist/teste/FileInputTrigger.test.d.ts +1 -0
  199. package/dist/teste/FileInputTrigger.test.js +53 -0
  200. package/dist/teste/IconPicker.test.d.ts +1 -0
  201. package/dist/teste/IconPicker.test.js +130 -0
  202. package/dist/teste/InputMascaraEAfins.test.d.ts +1 -0
  203. package/dist/teste/InputMascaraEAfins.test.js +99 -0
  204. package/dist/teste/KbdCodeBlock.test.d.ts +1 -0
  205. package/dist/teste/KbdCodeBlock.test.js +95 -0
  206. package/dist/teste/List.test.d.ts +1 -0
  207. package/dist/teste/List.test.js +153 -0
  208. package/dist/teste/Modal.test.d.ts +1 -0
  209. package/dist/teste/Modal.test.js +26 -0
  210. package/dist/teste/ModalVariantes.test.d.ts +1 -0
  211. package/dist/teste/ModalVariantes.test.js +151 -0
  212. package/dist/teste/MultiSelectErro.test.d.ts +1 -0
  213. package/dist/teste/MultiSelectErro.test.js +62 -0
  214. package/dist/teste/NomeAcessivelSsr.test.d.ts +1 -0
  215. package/dist/teste/NomeAcessivelSsr.test.js +88 -0
  216. package/dist/teste/OrgChart.test.d.ts +1 -0
  217. package/dist/teste/OrgChart.test.js +162 -0
  218. package/dist/teste/OtpInput.test.d.ts +1 -0
  219. package/dist/teste/OtpInput.test.js +143 -0
  220. package/dist/teste/PopoverMaxHeight.test.d.ts +1 -0
  221. package/dist/teste/PopoverMaxHeight.test.js +38 -0
  222. package/dist/teste/RichTextEditor.test.d.ts +1 -0
  223. package/dist/teste/RichTextEditor.test.js +287 -0
  224. package/dist/teste/RotulosTraduziveis.test.d.ts +1 -0
  225. package/dist/teste/RotulosTraduziveis.test.js +405 -0
  226. package/dist/teste/SegmentedControl.test.js +33 -0
  227. package/dist/teste/Select.test.d.ts +1 -0
  228. package/dist/teste/Select.test.js +62 -0
  229. package/dist/teste/SelectPlacementFiltro.test.d.ts +1 -0
  230. package/dist/teste/SelectPlacementFiltro.test.js +88 -0
  231. package/dist/teste/Stack.test.d.ts +1 -0
  232. package/dist/teste/Stack.test.js +57 -0
  233. package/dist/teste/StatCardRotuloTopo.test.d.ts +1 -0
  234. package/dist/teste/StatCardRotuloTopo.test.js +34 -0
  235. package/dist/teste/TabsContadorFechavel.test.d.ts +1 -0
  236. package/dist/teste/TabsContadorFechavel.test.js +79 -0
  237. package/dist/teste/Tooltip.test.d.ts +1 -0
  238. package/dist/teste/Tooltip.test.js +109 -0
  239. package/dist/teste/TooltipDark.test.d.ts +1 -0
  240. package/dist/teste/TooltipDark.test.js +31 -0
  241. package/dist/utils/calendario.d.ts +28 -0
  242. package/dist/utils/calendario.js +73 -0
  243. package/dist/utils/chart.d.ts +4 -0
  244. package/dist/utils/chart.js +3 -2
  245. package/dist/utils/html-seguro.d.ts +27 -0
  246. package/dist/utils/html-seguro.js +97 -0
  247. package/dist/utils/id.d.ts +2 -0
  248. package/dist/utils/id.js +23 -0
  249. package/dist/utils/paleta-de-cores.d.ts +26 -0
  250. package/dist/utils/paleta-de-cores.js +10 -0
  251. package/dist/utils/texto.d.ts +5 -0
  252. package/dist/utils/texto.js +5 -0
  253. package/package.json +3 -3
  254. package/src/index.ts +26 -0
  255. package/src/teste/AILabel.test.tsx +41 -0
  256. package/src/teste/AccordionConteudoLivre.test.tsx +39 -0
  257. package/src/teste/Alert.test.tsx +32 -0
  258. package/src/teste/AtributosRepassados.test.tsx +73 -0
  259. package/src/teste/AttachmentCardIA.test.tsx +126 -0
  260. package/src/teste/AvatarGroupOverlap.test.tsx +74 -0
  261. package/src/teste/BadgeTag.test.tsx +64 -0
  262. package/src/teste/BottomSheet.test.tsx +25 -0
  263. package/src/teste/BoxItemFlex.test.tsx +81 -0
  264. package/src/teste/BoxLayout.test.tsx +50 -0
  265. package/src/teste/Button.test.tsx +39 -0
  266. package/src/teste/Calendar.test.tsx +282 -0
  267. package/src/teste/ChipsXs.test.tsx +41 -0
  268. package/src/teste/Coachmark.test.tsx +198 -0
  269. package/src/teste/ColorPicker.test.tsx +153 -0
  270. package/src/teste/ConfirmAIAction.test.tsx +41 -0
  271. package/src/teste/DataTableCelulaLivre.test.tsx +103 -0
  272. package/src/teste/DataTableDocumento.test.tsx +102 -0
  273. package/src/teste/DatePicker.test.tsx +38 -0
  274. package/src/teste/Dropdown.test.tsx +146 -0
  275. package/src/teste/FileInputTrigger.test.tsx +89 -0
  276. package/src/teste/IconPicker.test.tsx +145 -0
  277. package/src/teste/InputMascaraEAfins.test.tsx +124 -0
  278. package/src/teste/KbdCodeBlock.test.tsx +106 -0
  279. package/src/teste/List.test.tsx +269 -0
  280. package/src/teste/Modal.test.tsx +28 -0
  281. package/src/teste/ModalVariantes.test.tsx +173 -0
  282. package/src/teste/MultiSelectErro.test.tsx +97 -0
  283. package/src/teste/NomeAcessivelSsr.test.tsx +110 -0
  284. package/src/teste/OrgChart.test.tsx +183 -0
  285. package/src/teste/OtpInput.test.tsx +163 -0
  286. package/src/teste/PopoverMaxHeight.test.tsx +47 -0
  287. package/src/teste/RichTextEditor.test.tsx +329 -0
  288. package/src/teste/RotulosTraduziveis.test.tsx +545 -0
  289. package/src/teste/SegmentedControl.test.tsx +57 -0
  290. package/src/teste/Select.test.tsx +97 -0
  291. package/src/teste/SelectPlacementFiltro.test.tsx +110 -0
  292. package/src/teste/Stack.test.tsx +80 -0
  293. package/src/teste/StatCardRotuloTopo.test.tsx +44 -0
  294. package/src/teste/TabsContadorFechavel.test.tsx +144 -0
  295. package/src/teste/Tooltip.test.tsx +219 -0
  296. package/src/teste/TooltipDark.test.tsx +51 -0
  297. package/src/utils/calendario.ts +78 -0
  298. package/src/utils/chart.ts +7 -2
  299. package/src/utils/html-seguro.ts +94 -0
  300. package/src/utils/id.ts +24 -0
  301. package/src/utils/paleta-de-cores.ts +34 -0
  302. package/src/utils/texto.ts +5 -0
@@ -0,0 +1,198 @@
1
+ import { describe, expect, it, vi } from "vitest";
2
+ import { useRef, useState } from "react";
3
+ import { render, screen, waitFor } from "@testing-library/react";
4
+ import userEvent from "@testing-library/user-event";
5
+ import Coachmark from "../components/Coachmark/Coachmark";
6
+
7
+ const PASSOS = [
8
+ { target: "#alvo-a", title: "Cada item é uma aba", content: "Fluxos e formulários abrem em abas." },
9
+ { target: "#alvo-b", title: "Salvo sozinho", content: "Tudo fica neste navegador." },
10
+ { title: "Pronto", content: "Sem alvo: o cartão fica no centro." },
11
+ ];
12
+
13
+ function Pagina(props: any) {
14
+ return (
15
+ <div>
16
+ <button id="alvo-a">A</button>
17
+ <button id="alvo-b">B</button>
18
+ <Coachmark steps={PASSOS} {...props} />
19
+ </div>
20
+ );
21
+ }
22
+
23
+ describe("Coachmark", () => {
24
+ it("fechado não desenha nada", () => {
25
+ render(<Pagina open={false} />);
26
+ expect(screen.queryByRole("dialog")).toBeNull();
27
+ });
28
+
29
+ it("aberto é um diálogo modal nomeado pelo título, com contador e texto", () => {
30
+ render(<Pagina open />);
31
+ const dialogo = screen.getByRole("dialog", { name: "Cada item é uma aba" });
32
+ expect(dialogo).toHaveAttribute("aria-modal", "true");
33
+ expect(dialogo).toHaveAccessibleDescription("Fluxos e formulários abrem em abas.");
34
+ expect(screen.getAllByText("1 de 3").length).toBeGreaterThan(0);
35
+ expect(screen.getByRole("button", { name: "Próximo" })).toBeInTheDocument();
36
+ expect(screen.queryByRole("button", { name: "Anterior" })).toBeNull();
37
+ });
38
+
39
+ it("o foco entra no cartão ao abrir", () => {
40
+ render(<Pagina open />);
41
+ expect(screen.getByRole("dialog")).toHaveFocus();
42
+ });
43
+
44
+ it("Próximo e Anterior trocam de passo e avisam em onStepChange", async () => {
45
+ const usuario = userEvent.setup();
46
+ const aoMudar = vi.fn();
47
+ render(<Pagina open onStepChange={aoMudar} />);
48
+ await usuario.click(screen.getByRole("button", { name: "Próximo" }));
49
+ expect(aoMudar).toHaveBeenLastCalledWith(1);
50
+ expect(screen.getByRole("dialog", { name: "Salvo sozinho" })).toBeInTheDocument();
51
+ await usuario.click(screen.getByRole("button", { name: "Anterior" }));
52
+ expect(aoMudar).toHaveBeenLastCalledWith(0);
53
+ expect(screen.getByRole("dialog", { name: "Cada item é uma aba" })).toBeInTheDocument();
54
+ });
55
+
56
+ it("setas direita e esquerda avançam e voltam", async () => {
57
+ const usuario = userEvent.setup();
58
+ render(<Pagina open />);
59
+ await usuario.keyboard("{ArrowRight}");
60
+ expect(screen.getByRole("dialog", { name: "Salvo sozinho" })).toBeInTheDocument();
61
+ await usuario.keyboard("{ArrowLeft}");
62
+ expect(screen.getByRole("dialog", { name: "Cada item é uma aba" })).toBeInTheDocument();
63
+ });
64
+
65
+ it("o último passo troca Próximo por Concluir e fecha com 'finish'", async () => {
66
+ const usuario = userEvent.setup();
67
+ const aoFechar = vi.fn();
68
+ render(<Pagina open defaultStep={2} onClose={aoFechar} />);
69
+ expect(screen.queryByRole("button", { name: "Próximo" })).toBeNull();
70
+ await usuario.click(screen.getByRole("button", { name: "Concluir" }));
71
+ expect(aoFechar).toHaveBeenCalledWith("finish");
72
+ });
73
+
74
+ it("Sair do tour fecha com 'skip' e hideSkip esconde o botão", async () => {
75
+ const usuario = userEvent.setup();
76
+ const aoFechar = vi.fn();
77
+ const { rerender } = render(<Pagina open onClose={aoFechar} />);
78
+ await usuario.click(screen.getByRole("button", { name: "Sair do tour" }));
79
+ expect(aoFechar).toHaveBeenCalledWith("skip");
80
+ rerender(<Pagina open hideSkip onClose={aoFechar} />);
81
+ expect(screen.queryByRole("button", { name: "Sair do tour" })).toBeNull();
82
+ });
83
+
84
+ it("Esc fecha com 'escape'", async () => {
85
+ const usuario = userEvent.setup();
86
+ const aoFechar = vi.fn();
87
+ render(<Pagina open onClose={aoFechar} />);
88
+ await usuario.keyboard("{Escape}");
89
+ expect(aoFechar).toHaveBeenCalledWith("escape");
90
+ });
91
+
92
+ it("o foco fica preso no cartão: Tab gira e Shift+Tab volta", async () => {
93
+ const usuario = userEvent.setup();
94
+ render(<Pagina open />);
95
+ const sair = screen.getByRole("button", { name: "Sair do tour" });
96
+ const proximo = screen.getByRole("button", { name: "Próximo" });
97
+ proximo.focus();
98
+ await usuario.tab();
99
+ expect(sair).toHaveFocus();
100
+ await usuario.tab({ shift: true });
101
+ expect(proximo).toHaveFocus();
102
+ });
103
+
104
+ it("todos os textos vêm por prop", () => {
105
+ render(
106
+ <Pagina
107
+ open
108
+ defaultStep={1}
109
+ nextLabel="Next"
110
+ previousLabel="Back"
111
+ skipLabel="Skip tour"
112
+ counterLabel="{current} of {total}"
113
+ />,
114
+ );
115
+ expect(screen.getByRole("button", { name: "Next" })).toBeInTheDocument();
116
+ expect(screen.getByRole("button", { name: "Back" })).toBeInTheDocument();
117
+ expect(screen.getByRole("button", { name: "Skip tour" })).toBeInTheDocument();
118
+ expect(screen.getAllByText("2 of 3").length).toBeGreaterThan(0);
119
+ });
120
+
121
+ it("finishLabel troca o texto do último passo", () => {
122
+ render(<Pagina open defaultStep={2} finishLabel="Done" />);
123
+ expect(screen.getByRole("button", { name: "Done" })).toBeInTheDocument();
124
+ });
125
+
126
+ it("com alvo, desenha o recorte; sem alvo (ou alvo que não existe), não", () => {
127
+ const { container, rerender } = render(<Pagina open />);
128
+ expect(document.querySelector(".umds-coachmark__cutout")).not.toBeNull();
129
+ rerender(<Pagina open step={2} />);
130
+ expect(document.querySelector(".umds-coachmark__cutout")).toBeNull();
131
+ expect(document.querySelector(".umds-coachmark--no-target")).not.toBeNull();
132
+ void container;
133
+ });
134
+
135
+ it("alvo por ref do React e por elemento", () => {
136
+ function ComRef() {
137
+ const ref = useRef<HTMLButtonElement>(null);
138
+ return (
139
+ <div>
140
+ <button ref={ref}>Alvo</button>
141
+ <Coachmark open steps={[{ target: ref, title: "Por ref" }]} />
142
+ </div>
143
+ );
144
+ }
145
+ render(<ComRef />);
146
+ expect(screen.getByRole("dialog", { name: "Por ref" })).toBeInTheDocument();
147
+ expect(document.querySelector(".umds-coachmark__cutout")).not.toBeNull();
148
+ });
149
+
150
+ it("step controlado manda no passo atual", () => {
151
+ render(<Pagina open step={1} />);
152
+ expect(screen.getByRole("dialog", { name: "Salvo sozinho" })).toBeInTheDocument();
153
+ });
154
+
155
+ it("ao fechar, o foco volta ao elemento de antes", async () => {
156
+ const usuario = userEvent.setup();
157
+ function Dono() {
158
+ const [aberto, setAberto] = useState(false);
159
+ return (
160
+ <div>
161
+ <button id="abrir" onClick={() => setAberto(true)}>
162
+ Fazer o tour
163
+ </button>
164
+ <Coachmark open={aberto} steps={PASSOS} onClose={() => setAberto(false)} />
165
+ </div>
166
+ );
167
+ }
168
+ render(<Dono />);
169
+ const abrir = screen.getByRole("button", { name: "Fazer o tour" });
170
+ await usuario.click(abrir);
171
+ expect(screen.getByRole("dialog")).toBeInTheDocument();
172
+ // O foco entra no cartão depois da montagem (um quadro de animação): na CI,
173
+ // mais lenta, o Esc chegava antes e caía no body.
174
+ await waitFor(() => expect(screen.getByRole("dialog").contains(document.activeElement)).toBe(true));
175
+ await usuario.keyboard("{Escape}");
176
+ await waitFor(() => expect(screen.queryByRole("dialog")).toBeNull());
177
+ expect(abrir).toHaveFocus();
178
+ });
179
+
180
+ it("reabrir recomeça do primeiro passo", async () => {
181
+ const usuario = userEvent.setup();
182
+ function Dono() {
183
+ const [aberto, setAberto] = useState(true);
184
+ return (
185
+ <div>
186
+ <button onClick={() => setAberto(true)}>Reabrir</button>
187
+ <Coachmark open={aberto} steps={PASSOS} onClose={() => setAberto(false)} />
188
+ </div>
189
+ );
190
+ }
191
+ render(<Dono />);
192
+ await usuario.keyboard("{ArrowRight}");
193
+ expect(screen.getByRole("dialog", { name: "Salvo sozinho" })).toBeInTheDocument();
194
+ await usuario.keyboard("{Escape}");
195
+ await usuario.click(screen.getByRole("button", { name: "Reabrir" }));
196
+ expect(screen.getByRole("dialog", { name: "Cada item é uma aba" })).toBeInTheDocument();
197
+ });
198
+ });
@@ -0,0 +1,153 @@
1
+ import { describe, expect, it, vi } from "vitest";
2
+ import { useState } from "react";
3
+ import { render, screen } from "@testing-library/react";
4
+ import userEvent from "@testing-library/user-event";
5
+ import ColorPicker from "../components/ColorPicker/ColorPicker";
6
+ import { COLOR_PALETTE } from "../utils/paleta-de-cores";
7
+
8
+ describe("ColorPicker", () => {
9
+ it("é um radiogroup com uma amostra por primitivo de cor, cada uma com nome", () => {
10
+ render(<ColorPicker ariaLabel="Cor do marcador" />);
11
+ const grupo = screen.getByRole("radiogroup", { name: "Cor do marcador" });
12
+ expect(grupo.querySelectorAll('[role="radio"]')).toHaveLength(COLOR_PALETTE.length);
13
+ expect(COLOR_PALETTE).toHaveLength(31);
14
+ expect(screen.getByRole("radio", { name: "Azul escuro" })).toBeInTheDocument();
15
+ expect(screen.getByRole("radio", { name: "Cinza muito claro" })).toBeInTheDocument();
16
+ });
17
+
18
+ it("pinta cada amostra com a variável do token", () => {
19
+ render(<ColorPicker ariaLabel="Cor" />);
20
+ const azul = screen.getByRole("radio", { name: "Azul" }) as HTMLElement;
21
+ expect(azul.style.backgroundColor).toBe("var(--umds-primitive-blue-pure)");
22
+ });
23
+
24
+ it("clicar escolhe e entrega o NOME do token em onChange", async () => {
25
+ const usuario = userEvent.setup();
26
+ const aoMudar = vi.fn();
27
+ render(<ColorPicker ariaLabel="Cor" onChange={aoMudar} />);
28
+ await usuario.click(screen.getByRole("radio", { name: "Verde" }));
29
+ expect(aoMudar).toHaveBeenCalledWith("--umds-primitive-green-pure");
30
+ expect(screen.getByRole("radio", { name: "Verde" })).toHaveAttribute("aria-checked", "true");
31
+ });
32
+
33
+ it("não escolhido tem aria-checked false e só a escolhida mostra a marcação", () => {
34
+ const { container } = render(<ColorPicker ariaLabel="Cor" defaultValue="--umds-primitive-red-pure" />);
35
+ expect(screen.getByRole("radio", { name: "Vermelho" })).toHaveAttribute("aria-checked", "true");
36
+ expect(screen.getByRole("radio", { name: "Azul" })).toHaveAttribute("aria-checked", "false");
37
+ expect(container.querySelectorAll(".umds-color-picker__swatch svg")).toHaveLength(1);
38
+ });
39
+
40
+ it("Tab entra na amostra escolhida (roving tabindex)", () => {
41
+ render(<ColorPicker ariaLabel="Cor" value="--umds-primitive-orange-pure" />);
42
+ const radios = screen.getAllByRole("radio");
43
+ const comTab = radios.filter((r) => r.getAttribute("tabindex") === "0");
44
+ expect(comTab).toHaveLength(1);
45
+ expect(comTab[0]).toHaveAccessibleName("Laranja");
46
+ });
47
+
48
+ it("sem valor, Tab entra na primeira amostra", () => {
49
+ render(<ColorPicker ariaLabel="Cor" />);
50
+ expect(screen.getAllByRole("radio")[0]).toHaveAttribute("tabindex", "0");
51
+ });
52
+
53
+ it("setas movem a escolha e o foco; Home e End vão às pontas; dá a volta", async () => {
54
+ const usuario = userEvent.setup();
55
+ const aoMudar = vi.fn();
56
+ render(<ColorPicker ariaLabel="Cor" families={["blue"]} defaultValue="--umds-primitive-blue-dark" onChange={aoMudar} />);
57
+ const radios = screen.getAllByRole("radio");
58
+ radios[0].focus();
59
+ await usuario.keyboard("{ArrowRight}");
60
+ expect(aoMudar).toHaveBeenLastCalledWith("--umds-primitive-blue-pure");
61
+ expect(radios[1]).toHaveFocus();
62
+ await usuario.keyboard("{ArrowLeft}{ArrowLeft}");
63
+ expect(aoMudar).toHaveBeenLastCalledWith("--umds-primitive-blue-light");
64
+ expect(radios[3]).toHaveFocus();
65
+ await usuario.keyboard("{Home}");
66
+ expect(radios[0]).toHaveFocus();
67
+ await usuario.keyboard("{End}");
68
+ expect(radios[3]).toHaveFocus();
69
+ await usuario.keyboard("{ArrowDown}");
70
+ expect(radios[0]).toHaveFocus();
71
+ });
72
+
73
+ it("pula amostra desabilitada no teclado", async () => {
74
+ const usuario = userEvent.setup();
75
+ const aoMudar = vi.fn();
76
+ render(
77
+ <ColorPicker
78
+ ariaLabel="Cor"
79
+ defaultValue="a"
80
+ onChange={aoMudar}
81
+ swatches={[
82
+ { value: "a", label: "A" },
83
+ { value: "b", label: "B", disabled: true },
84
+ { value: "c", label: "C" },
85
+ ]}
86
+ />,
87
+ );
88
+ screen.getByRole("radio", { name: "A" }).focus();
89
+ await usuario.keyboard("{ArrowRight}");
90
+ expect(aoMudar).toHaveBeenLastCalledWith("c");
91
+ });
92
+
93
+ it("families recorta a paleta", () => {
94
+ render(<ColorPicker ariaLabel="Cor" families={["blue", "gray"]} />);
95
+ expect(screen.getAllByRole("radio")).toHaveLength(11);
96
+ });
97
+
98
+ it("swatches substitui a paleta (nomes traduzidos)", () => {
99
+ render(<ColorPicker ariaLabel="Color" swatches={[{ value: "--umds-primitive-blue-pure", label: "Blue" }]} />);
100
+ expect(screen.getAllByRole("radio")).toHaveLength(1);
101
+ expect(screen.getByRole("radio", { name: "Blue" })).toBeInTheDocument();
102
+ });
103
+
104
+ it("disabled desabilita todas as amostras", () => {
105
+ render(<ColorPicker ariaLabel="Cor" disabled />);
106
+ for (const r of screen.getAllByRole("radio")) expect(r).toBeDisabled();
107
+ });
108
+
109
+ it("label visível nomeia o grupo", () => {
110
+ render(<ColorPicker label="Cor de fundo" id="cp" />);
111
+ expect(screen.getByRole("radiogroup", { name: "Cor de fundo" })).toBeInTheDocument();
112
+ });
113
+
114
+ it("cor livre vem desligada: sem campo de hexadecimal", () => {
115
+ render(<ColorPicker ariaLabel="Cor" />);
116
+ expect(screen.queryByLabelText(/hexadecimal/i)).toBeNull();
117
+ });
118
+
119
+ it("allowCustom: hexadecimal completo vira #RRGGBB em maiúsculas; incompleto não emite", async () => {
120
+ const usuario = userEvent.setup();
121
+ const aoMudar = vi.fn();
122
+ render(<ColorPicker ariaLabel="Cor" allowCustom onChange={aoMudar} />);
123
+ const campo = screen.getByLabelText("Cor livre (hexadecimal)");
124
+ await usuario.type(campo, "0058d");
125
+ expect(aoMudar).not.toHaveBeenCalled();
126
+ await usuario.type(campo, "b");
127
+ expect(aoMudar).toHaveBeenCalledTimes(1);
128
+ expect(aoMudar).toHaveBeenCalledWith("#0058DB");
129
+ });
130
+
131
+ it("allowCustom: hexadecimal inválido mostra a mensagem ao sair do campo", async () => {
132
+ const usuario = userEvent.setup();
133
+ render(<ColorPicker ariaLabel="Cor" allowCustom customErrorMessage="Formato inválido" />);
134
+ const campo = screen.getByLabelText("Cor livre (hexadecimal)");
135
+ await usuario.type(campo, "xyz");
136
+ expect(screen.queryByText("Formato inválido")).toBeNull();
137
+ await usuario.tab();
138
+ expect(screen.getByText("Formato inválido")).toBeInTheDocument();
139
+ });
140
+
141
+ it("controlado: reflete o value e escolher uma amostra limpa o campo livre", async () => {
142
+ const usuario = userEvent.setup();
143
+ function Controlado() {
144
+ const [valor, setValor] = useState("#336699");
145
+ return <ColorPicker ariaLabel="Cor" allowCustom value={valor} onChange={setValor} />;
146
+ }
147
+ render(<Controlado />);
148
+ const campo = screen.getByLabelText("Cor livre (hexadecimal)") as HTMLInputElement;
149
+ expect(campo.value).toBe("#336699");
150
+ await usuario.click(screen.getByRole("radio", { name: "Azul" }));
151
+ expect(campo.value).toBe("");
152
+ });
153
+ });
@@ -0,0 +1,41 @@
1
+ import { describe, expect, it, vi } from "vitest";
2
+ import { render, screen } from "@testing-library/react";
3
+ import ConfirmDialog from "../components/ConfirmDialog/ConfirmDialog";
4
+ import ConfirmAIAction from "../components/ConfirmAIAction/ConfirmAIAction";
5
+
6
+ /**
7
+ * O ConfirmAIAction dizia "digite CONFIRMAR", mas o botão continuava
8
+ * clicável: o ConfirmDialog não tinha como desabilitá-lo. Agora tem
9
+ * (`confirmDisabled`), e em risco alto o botão só libera com a frase.
10
+ */
11
+ describe("ConfirmDialog · confirmDisabled", () => {
12
+ it("desabilita o confirmar sem mudar o texto do botão", () => {
13
+ render(<ConfirmDialog open inline title="Excluir?" confirmLabel="Excluir" confirmDisabled />);
14
+ expect(screen.getByRole("button", { name: "Excluir" })).toBeDisabled();
15
+ });
16
+
17
+ it("sem a prop, o confirmar fica habilitado", () => {
18
+ render(<ConfirmDialog open inline title="Excluir?" confirmLabel="Excluir" />);
19
+ expect(screen.getByRole("button", { name: "Excluir" })).toBeEnabled();
20
+ });
21
+ });
22
+
23
+ describe("ConfirmAIAction · risco alto", () => {
24
+ it("botão desabilitado até a frase conferir", () => {
25
+ const onConfirm = vi.fn();
26
+ const { rerender } = render(
27
+ <ConfirmAIAction open risk="alto" title="Arquivar" affected={["Processo 1"]} typedValue="" onConfirm={onConfirm} />,
28
+ );
29
+ expect(screen.getByRole("button", { name: "Confirmar" })).toBeDisabled();
30
+
31
+ rerender(
32
+ <ConfirmAIAction open risk="alto" title="Arquivar" affected={["Processo 1"]} typedValue="confirmar" onConfirm={onConfirm} />,
33
+ );
34
+ expect(screen.getByRole("button", { name: "Confirmar" })).toBeEnabled();
35
+ });
36
+
37
+ it("risco médio não exige digitação", () => {
38
+ render(<ConfirmAIAction open risk="medio" title="Tramitar" />);
39
+ expect(screen.getByRole("button", { name: "Confirmar" })).toBeEnabled();
40
+ });
41
+ });
@@ -0,0 +1,103 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import { render, screen, within } from "@testing-library/react";
3
+ import DataTable, { type DataTableColumn } from "../components/DataTable/DataTable";
4
+
5
+ /**
6
+ * Célula livre (`render` devolvendo nó) e linha de grupo (`rowGroup`).
7
+ * No Vue o equivalente é o slot `#cell-<key>`: ver `datatable-slots.test.mjs`.
8
+ */
9
+
10
+ const USUARIOS = [
11
+ { id: 1, nome: "Lucas Andrade", setor: "SADM", perfil: "Administrador" },
12
+ { id: 2, nome: "Marina Souza", setor: "SADM", perfil: "Nível 1" },
13
+ { id: 3, nome: "Rafael Pereira", setor: "SOBR", perfil: "Nível 2" },
14
+ ];
15
+
16
+ describe("DataTable · célula livre", () => {
17
+ it("render devolvendo elemento desenha o nó, não texto", () => {
18
+ const colunas: DataTableColumn[] = [
19
+ { key: "nome", label: "Usuário", render: (row) => <strong data-testid="nome">{row.nome}</strong> },
20
+ { key: "perfil", label: "Perfil" },
21
+ ];
22
+ render(<DataTable columns={colunas} data={USUARIOS} />);
23
+
24
+ const nos = screen.getAllByTestId("nome");
25
+ expect(nos).toHaveLength(3);
26
+ expect(nos[0].tagName).toBe("STRONG");
27
+ expect(nos[0]).toHaveTextContent("Lucas Andrade");
28
+ });
29
+
30
+ it("render recebe a linha e o índice", () => {
31
+ const colunas: DataTableColumn[] = [
32
+ { key: "nome", label: "Usuário", render: (row, i) => `${i + 1}. ${row.nome}` },
33
+ ];
34
+ render(<DataTable columns={colunas} data={USUARIOS} />);
35
+ expect(screen.getByText("2. Marina Souza")).toBeInTheDocument();
36
+ });
37
+
38
+ it("DataTableColumn é exportado e tipa a coluna com render de nó", () => {
39
+ const coluna: DataTableColumn = {
40
+ key: "acoes",
41
+ label: "Ações",
42
+ render: () => <button type="button">Editar</button>,
43
+ };
44
+ render(<DataTable columns={[coluna]} data={USUARIOS} />);
45
+ expect(screen.getAllByRole("button", { name: "Editar" })).toHaveLength(3);
46
+ });
47
+ });
48
+
49
+ describe("DataTable · linha de grupo (rowGroup)", () => {
50
+ const colunas: DataTableColumn[] = [
51
+ { key: "nome", label: "Usuário" },
52
+ { key: "perfil", label: "Perfil" },
53
+ ];
54
+
55
+ it("sem rowGroup não desenha linha de grupo", () => {
56
+ const { container } = render(<DataTable columns={colunas} data={USUARIOS} />);
57
+ expect(container.querySelector("th[scope='rowgroup']")).toBeNull();
58
+ });
59
+
60
+ it("rowGroup por campo abre um grupo por valor consecutivo", () => {
61
+ const { container } = render(<DataTable columns={colunas} data={USUARIOS} rowGroup="setor" />);
62
+ const grupos = container.querySelectorAll("th[scope='rowgroup']");
63
+ expect(Array.from(grupos).map((g) => g.textContent)).toEqual(["SADM", "SOBR"]);
64
+ // a linha de grupo atravessa as colunas todas
65
+ expect(grupos[0]).toHaveAttribute("colspan", "2");
66
+ });
67
+
68
+ it("rowGroup por função e colspan com selectable", () => {
69
+ const { container } = render(
70
+ <DataTable
71
+ columns={colunas}
72
+ data={USUARIOS}
73
+ selectable
74
+ rowGroup={(row) => (row.id === 3 ? undefined : "Equipe A")}
75
+ />,
76
+ );
77
+ const grupos = container.querySelectorAll("th[scope='rowgroup']");
78
+ expect(grupos).toHaveLength(1);
79
+ expect(grupos[0]).toHaveTextContent("Equipe A");
80
+ expect(grupos[0]).toHaveAttribute("colspan", "3");
81
+ });
82
+
83
+ it("renderRowGroup devolve nó", () => {
84
+ render(
85
+ <DataTable
86
+ columns={colunas}
87
+ data={USUARIOS}
88
+ rowGroup="setor"
89
+ renderRowGroup={(rotulo) => <em data-testid="grupo">{rotulo}!</em>}
90
+ />,
91
+ );
92
+ expect(screen.getAllByTestId("grupo").map((n) => n.textContent)).toEqual(["SADM!", "SOBR!"]);
93
+ });
94
+
95
+ it("a linha de grupo não entra na seleção por índice", async () => {
96
+ const { container } = render(
97
+ <DataTable columns={colunas} data={USUARIOS} rowGroup="setor" selectable selectedRows={[2]} />,
98
+ );
99
+ const selecionadas = container.querySelectorAll(".umds-datatable__row--selected");
100
+ expect(selecionadas).toHaveLength(1);
101
+ expect(within(selecionadas[0] as HTMLElement).getByText("Rafael Pereira")).toBeInTheDocument();
102
+ });
103
+ });
@@ -0,0 +1,102 @@
1
+ import { describe, expect, it, vi } from "vitest";
2
+ import { render, screen } from "@testing-library/react";
3
+ import userEvent from "@testing-library/user-event";
4
+ import DataTable from "../components/DataTable/DataTable";
5
+ import DescriptionList from "../components/DescriptionList/DescriptionList";
6
+
7
+ const COLUNAS = [
8
+ { key: "descricao", label: "Descrição", sortable: true },
9
+ { key: "quantidade", label: "Quantidade", align: "right" as const },
10
+ ];
11
+ const DADOS = [
12
+ { descricao: "Diesel S10", quantidade: "5.760" },
13
+ { descricao: "Gasolina comum", quantidade: "1.200" },
14
+ ];
15
+
16
+ describe("DataTable variant=document", () => {
17
+ it("é a tabela de documento: classe própria, cabeçalho e linhas", () => {
18
+ const { container } = render(<DataTable variant="document" columns={COLUNAS} data={DADOS} />);
19
+ expect(container.querySelector(".umds-datatable--document")).not.toBeNull();
20
+ expect(screen.getAllByRole("columnheader")).toHaveLength(2);
21
+ expect(screen.getByText("Diesel S10")).toBeInTheDocument();
22
+ });
23
+
24
+ it("não ordena: sem botão de ordenar, sem aria-sort", () => {
25
+ render(<DataTable variant="document" columns={COLUNAS} data={DADOS} sortKey="descricao" sortDirection="asc" />);
26
+ expect(screen.queryByRole("button")).toBeNull();
27
+ for (const th of screen.getAllByRole("columnheader")) expect(th).not.toHaveAttribute("aria-sort");
28
+ });
29
+
30
+ it("não seleciona: selectable é ignorado", () => {
31
+ render(<DataTable variant="document" selectable columns={COLUNAS} data={DADOS} />);
32
+ expect(screen.queryByRole("checkbox")).toBeNull();
33
+ expect(screen.getAllByRole("columnheader")).toHaveLength(2);
34
+ });
35
+
36
+ it("linha não é clicável nem entra na ordem de Tab", async () => {
37
+ const usuario = userEvent.setup();
38
+ const aoClicar = vi.fn();
39
+ const { container } = render(<DataTable variant="document" columns={COLUNAS} data={DADOS} onRowClick={aoClicar} />);
40
+ const linha = container.querySelector("tbody tr") as HTMLElement;
41
+ expect(linha).not.toHaveAttribute("tabindex");
42
+ expect(linha).not.toHaveClass("umds-datatable__row--clickable");
43
+ await usuario.click(linha);
44
+ expect(aoClicar).not.toHaveBeenCalled();
45
+ });
46
+
47
+ it("a tabela de interface continua igual (ordena, seleciona, clica)", async () => {
48
+ const usuario = userEvent.setup();
49
+ const aoOrdenar = vi.fn();
50
+ render(<DataTable columns={COLUNAS} data={DADOS} selectable onSort={aoOrdenar} />);
51
+ expect(screen.getAllByRole("checkbox").length).toBeGreaterThan(0);
52
+ await usuario.click(screen.getByRole("button", { name: /Descrição/ }));
53
+ expect(aoOrdenar).toHaveBeenCalledWith("descricao", "asc");
54
+ });
55
+ });
56
+
57
+ describe("DescriptionList", () => {
58
+ const ITENS = [
59
+ { label: "Dotação", value: "02.031.0001" },
60
+ { label: "Empenho", value: "2026NE000184" },
61
+ { label: "Fonte", value: "" },
62
+ ];
63
+
64
+ it("é um dl com um dt e um dd por par", () => {
65
+ const { container } = render(<DescriptionList items={ITENS} ariaLabel="Dados de empenho" />);
66
+ const dl = container.querySelector("dl") as HTMLElement;
67
+ expect(dl).toHaveAttribute("aria-label", "Dados de empenho");
68
+ expect(dl.querySelectorAll("dt")).toHaveLength(3);
69
+ expect(dl.querySelectorAll("dd")).toHaveLength(3);
70
+ expect(dl.querySelector("dt")).toHaveTextContent("Dotação");
71
+ expect(dl.querySelector("dd")).toHaveTextContent("02.031.0001");
72
+ });
73
+
74
+ it("valor vazio mostra o traço, ou o texto de emptyValue", () => {
75
+ const { container, rerender } = render(<DescriptionList items={ITENS} />);
76
+ expect(container.querySelectorAll("dd")[2]).toHaveTextContent("—");
77
+ rerender(<DescriptionList items={ITENS} emptyValue="Não informado" />);
78
+ expect(container.querySelectorAll("dd")[2]).toHaveTextContent("Não informado");
79
+ });
80
+
81
+ it("inline é o padrão; fit encolhe", () => {
82
+ const { container, rerender } = render(<DescriptionList items={ITENS} />);
83
+ const dl = container.querySelector("dl") as HTMLElement;
84
+ expect(dl).toHaveClass("umds-description-list--inline");
85
+ expect(dl).not.toHaveClass("umds-description-list--fit");
86
+ rerender(<DescriptionList items={ITENS} fit />);
87
+ expect(container.querySelector("dl")).toHaveClass("umds-description-list--fit");
88
+ });
89
+
90
+ it("stacked ganha as colunas e a caixa do valor", () => {
91
+ const { container } = render(<DescriptionList items={ITENS} layout="stacked" columns={3} bordered />);
92
+ const dl = container.querySelector("dl") as HTMLElement;
93
+ expect(dl).toHaveClass("umds-description-list--stacked");
94
+ expect(dl).toHaveClass("umds-description-list--cols-3");
95
+ expect(dl).toHaveClass("umds-description-list--bordered");
96
+ });
97
+
98
+ it("sem itens, não desenha par nenhum", () => {
99
+ const { container } = render(<DescriptionList />);
100
+ expect(container.querySelectorAll("dt")).toHaveLength(0);
101
+ });
102
+ });
@@ -84,3 +84,41 @@ describe("DatePicker · teclado", () => {
84
84
  expect(screen.getByRole("combobox")).toHaveTextContent(/15\/\d{2}\/\d{4}/);
85
85
  });
86
86
  });
87
+
88
+ /**
89
+ * A story "Com valor" mostrava "Selecione o período" com `value="2025-12-31"`.
90
+ * Não era a story: no modo single o componente só lia `range`, e `value` e
91
+ * `defaultValue` eram declarados e nunca chegavam ao campo.
92
+ */
93
+ describe("DatePicker · valor no modo single", () => {
94
+ it("`value` aparece no campo, no formato pedido", () => {
95
+ render(
96
+ <DatePicker label="Vencimento" value="2025-12-31" format="DD/MM/YYYY" />,
97
+ );
98
+ expect(screen.getByRole("combobox")).toHaveTextContent("31/12/2025");
99
+ });
100
+
101
+ it("`defaultValue` semeia o campo no modo não-controlado", () => {
102
+ render(<DatePicker label="Vencimento" defaultValue="2025-06-15" />);
103
+ expect(screen.getByRole("combobox")).toHaveTextContent("15/06/2025");
104
+ });
105
+
106
+ it("`value` vazio no modo controlado mostra o placeholder", () => {
107
+ render(<DatePicker label="Vencimento" value="" placeholder="DD/MM/AAAA" />);
108
+ expect(screen.getByRole("combobox")).toHaveTextContent("DD/MM/AAAA");
109
+ });
110
+
111
+ it("o modo range continua lendo `range`, não `value`", () => {
112
+ render(
113
+ <DatePicker
114
+ mode="range"
115
+ label="Período"
116
+ value="2025-01-01"
117
+ range={{ from: "2025-03-01", to: "2025-03-10" }}
118
+ />,
119
+ );
120
+ expect(screen.getByRole("combobox")).toHaveTextContent(
121
+ "01/03/2025 – 10/03/2025",
122
+ );
123
+ });
124
+ });