@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.
- package/CHANGELOG.md +1280 -0
- package/dist/components/AIContent/AIContent.d.ts +10 -0
- package/dist/components/AIContent/AIContent.js +1 -1
- package/dist/components/AILabel/AILabel.d.ts +4 -0
- package/dist/components/AILabel/AILabel.js +2 -2
- package/dist/components/Accordion/Accordion.d.ts +6 -2
- package/dist/components/Alert/Alert.css +2 -0
- package/dist/components/Alert/Alert.d.ts +3 -1
- package/dist/components/Alert/Alert.js +7 -1
- package/dist/components/AppHeader/AppHeader.css +82 -8
- package/dist/components/AppHeader/AppHeader.d.ts +12 -1
- package/dist/components/AppHeader/AppHeader.js +186 -1
- package/dist/components/AppNavItem/AppNavItem.css +11 -3
- package/dist/components/AppShell/AppShell.css +9 -0
- package/dist/components/AppShell/AppShell.d.ts +8 -0
- package/dist/components/AppShell/AppShell.js +4 -1
- package/dist/components/AppSidebar/AppSidebar.css +1 -1
- package/dist/components/AppSidebar/AppSidebar.d.ts +4 -0
- package/dist/components/AppSidebar/AppSidebar.js +3 -1
- package/dist/components/AttachmentCard/AttachmentCard.css +17 -1
- package/dist/components/AttachmentCard/AttachmentCard.d.ts +29 -2
- package/dist/components/AttachmentCard/AttachmentCard.js +88 -20
- package/dist/components/Avatar/Avatar.css +7 -2
- package/dist/components/Avatar/AvatarGroup.d.ts +27 -0
- package/dist/components/Avatar/AvatarGroup.js +28 -4
- package/dist/components/Badge/Badge.css +61 -3
- package/dist/components/Badge/Badge.d.ts +14 -4
- package/dist/components/Badge/Badge.js +1 -0
- package/dist/components/BottomSheet/BottomSheet.css +1 -0
- package/dist/components/BottomSheet/BottomSheet.d.ts +8 -0
- package/dist/components/BottomSheet/BottomSheet.js +14 -2
- package/dist/components/Box/Box.css +83 -0
- package/dist/components/Box/Box.d.ts +82 -2
- package/dist/components/Box/Box.js +42 -2
- package/dist/components/Button/Button.css +29 -0
- package/dist/components/Button/Button.d.ts +4 -4
- package/dist/components/Button/Button.js +4 -1
- package/dist/components/Calendar/Calendar.css +245 -0
- package/dist/components/Calendar/Calendar.d.ts +125 -0
- package/dist/components/Calendar/Calendar.js +320 -0
- package/dist/components/Chart/BarChart.d.ts +6 -0
- package/dist/components/Chart/BarChart.js +3 -1
- package/dist/components/Chart/LineChart.d.ts +6 -0
- package/dist/components/Chart/LineChart.js +3 -1
- package/dist/components/Checkbox/Checkbox.css +4 -1
- package/dist/components/Chips/Chips.css +39 -0
- package/dist/components/Chips/Chips.d.ts +7 -2
- package/dist/components/Chips/Chips.js +6 -2
- package/dist/components/Coachmark/Coachmark.css +118 -0
- package/dist/components/Coachmark/Coachmark.d.ts +75 -0
- package/dist/components/Coachmark/Coachmark.js +321 -0
- package/dist/components/CodeBlock/CodeBlock.css +96 -0
- package/dist/components/CodeBlock/CodeBlock.d.ts +47 -0
- package/dist/components/CodeBlock/CodeBlock.js +103 -0
- package/dist/components/ColorPicker/ColorPicker.css +133 -0
- package/dist/components/ColorPicker/ColorPicker.d.ts +73 -0
- package/dist/components/ColorPicker/ColorPicker.js +219 -0
- package/dist/components/Combobox/Combobox.css +11 -3
- package/dist/components/ConfirmAIAction/ConfirmAIAction.d.ts +11 -1
- package/dist/components/ConfirmAIAction/ConfirmAIAction.js +6 -1
- package/dist/components/ConfirmDialog/ConfirmDialog.css +3 -0
- package/dist/components/ConfirmDialog/ConfirmDialog.d.ts +14 -0
- package/dist/components/ConfirmDialog/ConfirmDialog.js +2 -2
- package/dist/components/DataTable/DataTable.css +80 -0
- package/dist/components/DataTable/DataTable.d.ts +23 -4
- package/dist/components/DataTable/DataTable.js +61 -15
- package/dist/components/DatePicker/DatePicker.css +8 -0
- package/dist/components/DatePicker/DatePicker.d.ts +4 -0
- package/dist/components/DatePicker/DatePicker.js +14 -1
- package/dist/components/DescriptionList/DescriptionList.css +113 -0
- package/dist/components/DescriptionList/DescriptionList.d.ts +59 -0
- package/dist/components/DescriptionList/DescriptionList.js +51 -0
- package/dist/components/Drawer/Drawer.css +1 -0
- package/dist/components/Dropdown/Dropdown.js +47 -29
- package/dist/components/FileInput/FileInput.css +24 -4
- package/dist/components/FileInput/FileInput.d.ts +22 -2
- package/dist/components/FileInput/FileInput.js +23 -2
- package/dist/components/Grid/Grid.js +5 -5
- package/dist/components/IconPicker/IconPicker.css +107 -0
- package/dist/components/IconPicker/IconPicker.d.ts +74 -0
- package/dist/components/IconPicker/IconPicker.js +194 -0
- package/dist/components/Input/Input.css +41 -3
- package/dist/components/Input/Input.d.ts +14 -1
- package/dist/components/Input/Input.js +72 -6
- package/dist/components/Kanban/Kanban.css +5 -0
- package/dist/components/Kanban/Kanban.d.ts +41 -0
- package/dist/components/Kanban/Kanban.js +59 -27
- package/dist/components/Kanban/KanbanCard.d.ts +2 -0
- package/dist/components/Kanban/KanbanCard.js +1 -1
- package/dist/components/Kanban/KanbanColumn.d.ts +2 -0
- package/dist/components/Kanban/KanbanColumn.js +3 -0
- package/dist/components/Kbd/Kbd.css +66 -0
- package/dist/components/Kbd/Kbd.d.ts +32 -0
- package/dist/components/Kbd/Kbd.js +40 -0
- package/dist/components/Link/Link.css +1 -1
- package/dist/components/List/List.css +136 -0
- package/dist/components/List/List.d.ts +82 -0
- package/dist/components/List/List.js +53 -0
- package/dist/components/List/ListItem.d.ts +85 -0
- package/dist/components/List/ListItem.js +81 -0
- package/dist/components/Modal/Modal.css +93 -8
- package/dist/components/Modal/Modal.d.ts +45 -7
- package/dist/components/Modal/Modal.js +106 -6
- package/dist/components/MultiSelect/MultiSelect.css +9 -1
- package/dist/components/MultiSelect/MultiSelect.js +45 -8
- package/dist/components/OrgChart/OrgChart.css +149 -0
- package/dist/components/OrgChart/OrgChart.d.ts +83 -0
- package/dist/components/OrgChart/OrgChart.js +297 -0
- package/dist/components/OtpInput/OtpInput.css +93 -0
- package/dist/components/OtpInput/OtpInput.d.ts +60 -0
- package/dist/components/OtpInput/OtpInput.js +215 -0
- package/dist/components/Pagination/Pagination.d.ts +6 -0
- package/dist/components/Pagination/Pagination.js +9 -1
- package/dist/components/PhoneInput/PhoneInput.css +9 -1
- package/dist/components/PhoneInput/PhoneInput.d.ts +10 -0
- package/dist/components/PhoneInput/PhoneInput.js +20 -3
- package/dist/components/Popover/Popover.d.ts +7 -0
- package/dist/components/Popover/Popover.js +11 -1
- package/dist/components/RichTextEditor/RichTextEditor.css +203 -0
- package/dist/components/RichTextEditor/RichTextEditor.d.ts +83 -0
- package/dist/components/RichTextEditor/RichTextEditor.js +494 -0
- package/dist/components/SegmentedControl/SegmentedControl.d.ts +2 -0
- package/dist/components/SegmentedControl/SegmentedControl.js +21 -8
- package/dist/components/Select/Select.css +71 -1
- package/dist/components/Select/Select.d.ts +12 -0
- package/dist/components/Select/Select.js +93 -10
- package/dist/components/SidePanel/SidePanel.css +4 -4
- package/dist/components/SidePanelItem/SidePanelItem.css +7 -5
- package/dist/components/SidePanelSearch/SidePanelSearch.css +2 -2
- package/dist/components/SidePanelSection/SidePanelSection.css +7 -5
- package/dist/components/Stack/Stack.css +49 -0
- package/dist/components/Stack/Stack.d.ts +65 -7
- package/dist/components/Stack/Stack.js +30 -2
- package/dist/components/StatCard/StatCard.css +73 -0
- package/dist/components/StatCard/StatCard.d.ts +17 -0
- package/dist/components/StatCard/StatCard.js +4 -1
- package/dist/components/Stepper/Stepper.css +4 -1
- package/dist/components/Stepper/Stepper.d.ts +8 -0
- package/dist/components/Stepper/Stepper.js +4 -4
- package/dist/components/Switch/Switch.css +1 -0
- package/dist/components/Tabs/Tab.d.ts +15 -0
- package/dist/components/Tabs/Tab.js +30 -1
- package/dist/components/Tabs/Tabs.css +132 -0
- package/dist/components/Tabs/Tabs.d.ts +7 -0
- package/dist/components/Tabs/Tabs.js +13 -2
- package/dist/components/Tag/Tag.css +85 -2
- package/dist/components/Tag/Tag.d.ts +13 -6
- package/dist/components/Tag/Tag.js +1 -0
- package/dist/components/Text/Text.d.ts +9 -1
- package/dist/components/Text/Text.js +2 -2
- package/dist/components/Textarea/Textarea.css +11 -3
- package/dist/components/TimePicker/TimePicker.css +8 -0
- package/dist/components/TimePicker/TimePicker.d.ts +6 -0
- package/dist/components/TimePicker/TimePicker.js +1 -1
- package/dist/components/Tooltip/Tooltip.css +40 -0
- package/dist/components/Tooltip/Tooltip.d.ts +11 -0
- package/dist/components/Tooltip/Tooltip.js +114 -11
- package/dist/index.d.ts +25 -0
- package/dist/index.js +14 -0
- package/dist/teste/AILabel.test.d.ts +1 -0
- package/dist/teste/AILabel.test.js +33 -0
- package/dist/teste/AccordionConteudoLivre.test.d.ts +1 -0
- package/dist/teste/AccordionConteudoLivre.test.js +29 -0
- package/dist/teste/Alert.test.d.ts +1 -0
- package/dist/teste/Alert.test.js +27 -0
- package/dist/teste/AtributosRepassados.test.d.ts +1 -0
- package/dist/teste/AtributosRepassados.test.js +52 -0
- package/dist/teste/AttachmentCardIA.test.d.ts +1 -0
- package/dist/teste/AttachmentCardIA.test.js +89 -0
- package/dist/teste/AvatarGroupOverlap.test.d.ts +1 -0
- package/dist/teste/AvatarGroupOverlap.test.js +56 -0
- package/dist/teste/BadgeTag.test.d.ts +1 -0
- package/dist/teste/BadgeTag.test.js +42 -0
- package/dist/teste/BottomSheet.test.d.ts +1 -0
- package/dist/teste/BottomSheet.test.js +23 -0
- package/dist/teste/BoxItemFlex.test.d.ts +1 -0
- package/dist/teste/BoxItemFlex.test.js +54 -0
- package/dist/teste/BoxLayout.test.d.ts +1 -0
- package/dist/teste/BoxLayout.test.js +35 -0
- package/dist/teste/Button.test.d.ts +1 -0
- package/dist/teste/Button.test.js +27 -0
- package/dist/teste/Calendar.test.d.ts +1 -0
- package/dist/teste/Calendar.test.js +221 -0
- package/dist/teste/ChipsXs.test.d.ts +1 -0
- package/dist/teste/ChipsXs.test.js +31 -0
- package/dist/teste/Coachmark.test.d.ts +1 -0
- package/dist/teste/Coachmark.test.js +149 -0
- package/dist/teste/ColorPicker.test.d.ts +1 -0
- package/dist/teste/ColorPicker.test.js +132 -0
- package/dist/teste/ConfirmAIAction.test.d.ts +1 -0
- package/dist/teste/ConfirmAIAction.test.js +33 -0
- package/dist/teste/DataTableCelulaLivre.test.d.ts +1 -0
- package/dist/teste/DataTableCelulaLivre.test.js +76 -0
- package/dist/teste/DataTableDocumento.test.d.ts +1 -0
- package/dist/teste/DataTableDocumento.test.js +92 -0
- package/dist/teste/DatePicker.test.js +23 -0
- package/dist/teste/Dropdown.test.js +111 -0
- package/dist/teste/FileInputTrigger.test.d.ts +1 -0
- package/dist/teste/FileInputTrigger.test.js +53 -0
- package/dist/teste/IconPicker.test.d.ts +1 -0
- package/dist/teste/IconPicker.test.js +130 -0
- package/dist/teste/InputMascaraEAfins.test.d.ts +1 -0
- package/dist/teste/InputMascaraEAfins.test.js +99 -0
- package/dist/teste/KbdCodeBlock.test.d.ts +1 -0
- package/dist/teste/KbdCodeBlock.test.js +95 -0
- package/dist/teste/List.test.d.ts +1 -0
- package/dist/teste/List.test.js +153 -0
- package/dist/teste/Modal.test.d.ts +1 -0
- package/dist/teste/Modal.test.js +26 -0
- package/dist/teste/ModalVariantes.test.d.ts +1 -0
- package/dist/teste/ModalVariantes.test.js +151 -0
- package/dist/teste/MultiSelectErro.test.d.ts +1 -0
- package/dist/teste/MultiSelectErro.test.js +62 -0
- package/dist/teste/NomeAcessivelSsr.test.d.ts +1 -0
- package/dist/teste/NomeAcessivelSsr.test.js +88 -0
- package/dist/teste/OrgChart.test.d.ts +1 -0
- package/dist/teste/OrgChart.test.js +162 -0
- package/dist/teste/OtpInput.test.d.ts +1 -0
- package/dist/teste/OtpInput.test.js +143 -0
- package/dist/teste/PopoverMaxHeight.test.d.ts +1 -0
- package/dist/teste/PopoverMaxHeight.test.js +38 -0
- package/dist/teste/RichTextEditor.test.d.ts +1 -0
- package/dist/teste/RichTextEditor.test.js +287 -0
- package/dist/teste/RotulosTraduziveis.test.d.ts +1 -0
- package/dist/teste/RotulosTraduziveis.test.js +405 -0
- package/dist/teste/SegmentedControl.test.js +33 -0
- package/dist/teste/Select.test.d.ts +1 -0
- package/dist/teste/Select.test.js +62 -0
- package/dist/teste/SelectPlacementFiltro.test.d.ts +1 -0
- package/dist/teste/SelectPlacementFiltro.test.js +88 -0
- package/dist/teste/Stack.test.d.ts +1 -0
- package/dist/teste/Stack.test.js +57 -0
- package/dist/teste/StatCardRotuloTopo.test.d.ts +1 -0
- package/dist/teste/StatCardRotuloTopo.test.js +34 -0
- package/dist/teste/TabsContadorFechavel.test.d.ts +1 -0
- package/dist/teste/TabsContadorFechavel.test.js +79 -0
- package/dist/teste/Tooltip.test.d.ts +1 -0
- package/dist/teste/Tooltip.test.js +109 -0
- package/dist/teste/TooltipDark.test.d.ts +1 -0
- package/dist/teste/TooltipDark.test.js +31 -0
- package/dist/utils/calendario.d.ts +28 -0
- package/dist/utils/calendario.js +73 -0
- package/dist/utils/chart.d.ts +4 -0
- package/dist/utils/chart.js +3 -2
- package/dist/utils/html-seguro.d.ts +27 -0
- package/dist/utils/html-seguro.js +97 -0
- package/dist/utils/id.d.ts +2 -0
- package/dist/utils/id.js +23 -0
- package/dist/utils/paleta-de-cores.d.ts +26 -0
- package/dist/utils/paleta-de-cores.js +10 -0
- package/dist/utils/texto.d.ts +5 -0
- package/dist/utils/texto.js +5 -0
- package/package.json +3 -3
- package/src/index.ts +26 -0
- package/src/teste/AILabel.test.tsx +41 -0
- package/src/teste/AccordionConteudoLivre.test.tsx +39 -0
- package/src/teste/Alert.test.tsx +32 -0
- package/src/teste/AtributosRepassados.test.tsx +73 -0
- package/src/teste/AttachmentCardIA.test.tsx +126 -0
- package/src/teste/AvatarGroupOverlap.test.tsx +74 -0
- package/src/teste/BadgeTag.test.tsx +64 -0
- package/src/teste/BottomSheet.test.tsx +25 -0
- package/src/teste/BoxItemFlex.test.tsx +81 -0
- package/src/teste/BoxLayout.test.tsx +50 -0
- package/src/teste/Button.test.tsx +39 -0
- package/src/teste/Calendar.test.tsx +282 -0
- package/src/teste/ChipsXs.test.tsx +41 -0
- package/src/teste/Coachmark.test.tsx +198 -0
- package/src/teste/ColorPicker.test.tsx +153 -0
- package/src/teste/ConfirmAIAction.test.tsx +41 -0
- package/src/teste/DataTableCelulaLivre.test.tsx +103 -0
- package/src/teste/DataTableDocumento.test.tsx +102 -0
- package/src/teste/DatePicker.test.tsx +38 -0
- package/src/teste/Dropdown.test.tsx +146 -0
- package/src/teste/FileInputTrigger.test.tsx +89 -0
- package/src/teste/IconPicker.test.tsx +145 -0
- package/src/teste/InputMascaraEAfins.test.tsx +124 -0
- package/src/teste/KbdCodeBlock.test.tsx +106 -0
- package/src/teste/List.test.tsx +269 -0
- package/src/teste/Modal.test.tsx +28 -0
- package/src/teste/ModalVariantes.test.tsx +173 -0
- package/src/teste/MultiSelectErro.test.tsx +97 -0
- package/src/teste/NomeAcessivelSsr.test.tsx +110 -0
- package/src/teste/OrgChart.test.tsx +183 -0
- package/src/teste/OtpInput.test.tsx +163 -0
- package/src/teste/PopoverMaxHeight.test.tsx +47 -0
- package/src/teste/RichTextEditor.test.tsx +329 -0
- package/src/teste/RotulosTraduziveis.test.tsx +545 -0
- package/src/teste/SegmentedControl.test.tsx +57 -0
- package/src/teste/Select.test.tsx +97 -0
- package/src/teste/SelectPlacementFiltro.test.tsx +110 -0
- package/src/teste/Stack.test.tsx +80 -0
- package/src/teste/StatCardRotuloTopo.test.tsx +44 -0
- package/src/teste/TabsContadorFechavel.test.tsx +144 -0
- package/src/teste/Tooltip.test.tsx +219 -0
- package/src/teste/TooltipDark.test.tsx +51 -0
- package/src/utils/calendario.ts +78 -0
- package/src/utils/chart.ts +7 -2
- package/src/utils/html-seguro.ts +94 -0
- package/src/utils/id.ts +24 -0
- package/src/utils/paleta-de-cores.ts +34 -0
- package/src/utils/texto.ts +5 -0
|
@@ -0,0 +1,52 @@
|
|
|
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 Text from "../components/Text/Text";
|
|
5
|
+
import Grid from "../components/Grid/Grid";
|
|
6
|
+
import Logo from "../components/Logo/Logo";
|
|
7
|
+
import Button from "../components/Button/Button";
|
|
8
|
+
import DataTable from "../components/DataTable/DataTable";
|
|
9
|
+
/**
|
|
10
|
+
* Paridade com o Vue: no Vue gerado, Text, Grid e Logo descartavam
|
|
11
|
+
* `title`, `style` e `aria-*`, o Button escrevia `autofocus="false"` e o
|
|
12
|
+
* DataTable a classe `--selected.value`. O React nunca teve o defeito; o teste
|
|
13
|
+
* garante que a correção do Vue não o introduza aqui (mesma fonte Mitosis).
|
|
14
|
+
*/
|
|
15
|
+
describe("atributos repassados ao elemento raiz", () => {
|
|
16
|
+
it("Text repassa title, style e aria-*", () => {
|
|
17
|
+
const { container } = render(_jsx(Text, { title: "Dica", style: { marginTop: 4 }, "aria-live": "polite", "data-x": "1", children: "Ol\u00E1" }));
|
|
18
|
+
const el = container.firstElementChild;
|
|
19
|
+
expect(el.getAttribute("title")).toBe("Dica");
|
|
20
|
+
expect(el.style.marginTop).toBe("4px");
|
|
21
|
+
expect(el.getAttribute("aria-live")).toBe("polite");
|
|
22
|
+
expect(el.getAttribute("data-x")).toBe("1");
|
|
23
|
+
});
|
|
24
|
+
it("Grid repassa title, style e aria-*", () => {
|
|
25
|
+
const { container } = render(_jsx(Grid, { container: true, spacing: "xxxs", title: "Dica", style: { marginTop: 4 }, "aria-label": "\u00C1rea", children: "x" }));
|
|
26
|
+
const el = container.firstElementChild;
|
|
27
|
+
expect(el.getAttribute("title")).toBe("Dica");
|
|
28
|
+
expect(el.style.marginTop).toBe("4px");
|
|
29
|
+
expect(el.getAttribute("aria-label")).toBe("Área");
|
|
30
|
+
});
|
|
31
|
+
it("Logo repassa title, style e aria-*", () => {
|
|
32
|
+
const { container } = render(_jsx(Logo, { title: "Dica", style: { width: 80 }, "aria-hidden": "true" }));
|
|
33
|
+
const el = container.firstElementChild;
|
|
34
|
+
expect(el.getAttribute("title")).toBe("Dica");
|
|
35
|
+
expect(el.style.width).toBe("80px");
|
|
36
|
+
expect(el.getAttribute("aria-hidden")).toBe("true");
|
|
37
|
+
});
|
|
38
|
+
});
|
|
39
|
+
describe("Button · autoFocus", () => {
|
|
40
|
+
it("não escreve autofocus quando falso ou ausente", () => {
|
|
41
|
+
const { container } = render(_jsx(Button, { children: "Salvar" }));
|
|
42
|
+
expect(container.querySelector("[autofocus]")).toBeNull();
|
|
43
|
+
});
|
|
44
|
+
});
|
|
45
|
+
describe("DataTable · linha selecionada", () => {
|
|
46
|
+
it("a classe --selected vai limpa, só na linha selecionada", () => {
|
|
47
|
+
const { container } = render(_jsx(DataTable, { columns: [{ key: "nome", label: "Nome" }], data: [{ nome: "Cris Lima" }, { nome: "Ana Paula" }], selectable: true, selectedRows: [0] }));
|
|
48
|
+
const marcadas = container.querySelectorAll(".umds-datatable__row--selected");
|
|
49
|
+
expect(marcadas).toHaveLength(1);
|
|
50
|
+
expect(container.innerHTML).not.toContain(".value");
|
|
51
|
+
});
|
|
52
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { beforeAll, describe, expect, it, vi } from "vitest";
|
|
3
|
+
import { render, screen, waitFor } from "@testing-library/react";
|
|
4
|
+
import userEvent from "@testing-library/user-event";
|
|
5
|
+
import AttachmentCard from "../components/AttachmentCard/AttachmentCard";
|
|
6
|
+
beforeAll(() => {
|
|
7
|
+
if (!globalThis.ResizeObserver) {
|
|
8
|
+
globalThis.ResizeObserver = class {
|
|
9
|
+
observe() { }
|
|
10
|
+
unobserve() { }
|
|
11
|
+
disconnect() { }
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
});
|
|
15
|
+
function cartaoDeIA(extra = {}) {
|
|
16
|
+
const aoAplicar = vi.fn();
|
|
17
|
+
const ui = (_jsx(AttachmentCard, { fileName: "protocolo.pdf", documentType: "Protocolo", status: "ai", statusLabel: "Recursos IA", onOpen: () => { }, panel: _jsxs("div", { children: [_jsx("p", { children: "A IA sugere um assunto." }), _jsx("button", { type: "button", onClick: aoAplicar, children: "Aplicar sugest\u00E3o" })] }), ...extra }));
|
|
18
|
+
return { aoAplicar, ...render(ui) };
|
|
19
|
+
}
|
|
20
|
+
describe("AttachmentCard · status ai", () => {
|
|
21
|
+
it("escreve a classe do selo de IA e usa a varinha por padrão", () => {
|
|
22
|
+
const { container } = render(_jsx(AttachmentCard, { fileName: "x.pdf", status: "ai", statusLabel: "Recursos IA" }));
|
|
23
|
+
const selo = container.querySelector(".umds-attachment-card__status");
|
|
24
|
+
expect(selo).toHaveClass("umds-attachment-card__status--ai");
|
|
25
|
+
expect(selo.querySelector("svg")).not.toBeNull();
|
|
26
|
+
});
|
|
27
|
+
it("só o selo de IA ganha ícone por padrão", () => {
|
|
28
|
+
const { container } = render(_jsx(AttachmentCard, { fileName: "x.pdf", status: "positive", statusLabel: "Ok" }));
|
|
29
|
+
expect(container.querySelector(".umds-attachment-card__status svg")).toBeNull();
|
|
30
|
+
});
|
|
31
|
+
});
|
|
32
|
+
describe("AttachmentCard · slot panel", () => {
|
|
33
|
+
it("o painel livre substitui o resultado da conferência, e o selo vira botão sem statusDetails", async () => {
|
|
34
|
+
const usuario = userEvent.setup();
|
|
35
|
+
cartaoDeIA();
|
|
36
|
+
const selo = screen.getByRole("button", { name: /^Recursos IA/ });
|
|
37
|
+
expect(selo).toHaveAttribute("aria-haspopup", "dialog");
|
|
38
|
+
await usuario.click(selo);
|
|
39
|
+
const painel = await screen.findByRole("dialog");
|
|
40
|
+
expect(painel).toHaveTextContent("A IA sugere um assunto.");
|
|
41
|
+
expect(screen.getByRole("button", { name: "Aplicar sugestão" })).toBeInTheDocument();
|
|
42
|
+
// sem título interno: o painel é nomeado pelo selo
|
|
43
|
+
expect(painel).not.toHaveAttribute("aria-labelledby");
|
|
44
|
+
expect(painel).toHaveAccessibleName(/Recursos IA/);
|
|
45
|
+
});
|
|
46
|
+
it("sem panel nem statusDetails o selo não é botão", () => {
|
|
47
|
+
render(_jsx(AttachmentCard, { fileName: "x.pdf", status: "ai", statusLabel: "Recursos IA" }));
|
|
48
|
+
expect(screen.queryByRole("button")).toBeNull();
|
|
49
|
+
});
|
|
50
|
+
it("panelWidth escreve a largura do painel; sem ela não há style", async () => {
|
|
51
|
+
const usuario = userEvent.setup();
|
|
52
|
+
cartaoDeIA({ panelWidth: 280 });
|
|
53
|
+
await usuario.click(screen.getByRole("button", { name: /^Recursos IA/ }));
|
|
54
|
+
expect((await screen.findByRole("dialog")).style.width).toBe("280px");
|
|
55
|
+
});
|
|
56
|
+
it("sem panelWidth o painel não leva style", async () => {
|
|
57
|
+
const usuario = userEvent.setup();
|
|
58
|
+
cartaoDeIA();
|
|
59
|
+
await usuario.click(screen.getByRole("button", { name: /^Recursos IA/ }));
|
|
60
|
+
expect((await screen.findByRole("dialog")).getAttribute("style")).toBeNull();
|
|
61
|
+
});
|
|
62
|
+
});
|
|
63
|
+
describe("AttachmentCard · closePanelOnAction", () => {
|
|
64
|
+
it("acionar um botão do painel fecha, devolve o foco ao selo e a ação chega ao app", async () => {
|
|
65
|
+
const usuario = userEvent.setup();
|
|
66
|
+
const { aoAplicar } = cartaoDeIA({ closePanelOnAction: true });
|
|
67
|
+
const selo = screen.getByRole("button", { name: /^Recursos IA/ });
|
|
68
|
+
await usuario.click(selo);
|
|
69
|
+
await usuario.click(await screen.findByRole("button", { name: "Aplicar sugestão" }));
|
|
70
|
+
expect(aoAplicar).toHaveBeenCalledTimes(1);
|
|
71
|
+
await waitFor(() => expect(screen.queryByRole("dialog")).toBeNull());
|
|
72
|
+
expect(selo).toHaveFocus();
|
|
73
|
+
});
|
|
74
|
+
it("sem a prop o painel continua aberto depois da ação", async () => {
|
|
75
|
+
const usuario = userEvent.setup();
|
|
76
|
+
const { aoAplicar } = cartaoDeIA();
|
|
77
|
+
await usuario.click(screen.getByRole("button", { name: /^Recursos IA/ }));
|
|
78
|
+
await usuario.click(await screen.findByRole("button", { name: "Aplicar sugestão" }));
|
|
79
|
+
expect(aoAplicar).toHaveBeenCalledTimes(1);
|
|
80
|
+
expect(screen.getByRole("dialog")).toBeInTheDocument();
|
|
81
|
+
});
|
|
82
|
+
it("o botão de copiar um campo não fecha o painel", async () => {
|
|
83
|
+
const usuario = userEvent.setup();
|
|
84
|
+
render(_jsx(AttachmentCard, { fileName: "cpf.pdf", status: "positive", statusLabel: "Pr\u00E9-aprovado", closePanelOnAction: true, statusDetails: { fields: [{ label: "CPF", value: "384.221.760-05", copyable: true }] } }));
|
|
85
|
+
await usuario.click(screen.getByRole("button", { name: /^Pré-aprovado/ }));
|
|
86
|
+
await usuario.click(await screen.findByRole("button", { name: "Copiar CPF" }));
|
|
87
|
+
expect(screen.getByRole("dialog")).toBeInTheDocument();
|
|
88
|
+
});
|
|
89
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,56 @@
|
|
|
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 AvatarGroup from "../components/Avatar/AvatarGroup";
|
|
5
|
+
const PESSOAS = [
|
|
6
|
+
{ name: "Ana Souza" },
|
|
7
|
+
{ name: "Bruno Lima" },
|
|
8
|
+
{ name: "Carla Dias" },
|
|
9
|
+
{ name: "Diego Ferraz" },
|
|
10
|
+
{ name: "Eduarda Neves" },
|
|
11
|
+
];
|
|
12
|
+
const grupo = (c) => c.firstElementChild;
|
|
13
|
+
describe("AvatarGroup · overflowCount", () => {
|
|
14
|
+
it("sem a prop, o +N é o que passou de max (como antes)", () => {
|
|
15
|
+
render(_jsx(AvatarGroup, { avatars: PESSOAS, max: 3 }));
|
|
16
|
+
expect(screen.getByText("+2")).toBeInTheDocument();
|
|
17
|
+
});
|
|
18
|
+
it("overflowCount vira o +N sem itens-fantasma", () => {
|
|
19
|
+
render(_jsx(AvatarGroup, { avatars: PESSOAS.slice(0, 3), max: 3, overflowCount: 12 }));
|
|
20
|
+
expect(screen.getByText("+12")).toBeInTheDocument();
|
|
21
|
+
});
|
|
22
|
+
it("soma com o que passou de max dentro de avatars", () => {
|
|
23
|
+
render(_jsx(AvatarGroup, { avatars: PESSOAS, max: 3, overflowCount: 10 }));
|
|
24
|
+
expect(screen.getByText("+12")).toBeInTheDocument();
|
|
25
|
+
});
|
|
26
|
+
it("o rótulo traduzido recebe o total escondido", () => {
|
|
27
|
+
render(_jsx(AvatarGroup, { avatars: PESSOAS.slice(0, 2), max: 2, overflowCount: 7, overflowTitle: (n) => n + " others", overflowAriaLabel: (n) => n + " more avatars" }));
|
|
28
|
+
expect(screen.getByTitle("7 others")).toBeInTheDocument();
|
|
29
|
+
});
|
|
30
|
+
it("sem excedente nenhum, não há +N", () => {
|
|
31
|
+
render(_jsx(AvatarGroup, { avatars: PESSOAS.slice(0, 2), max: 4 }));
|
|
32
|
+
expect(screen.queryByText(/^\+/)).toBeNull();
|
|
33
|
+
});
|
|
34
|
+
it("overflowCount 0 não cria +0", () => {
|
|
35
|
+
render(_jsx(AvatarGroup, { avatars: PESSOAS.slice(0, 2), max: 4, overflowCount: 0 }));
|
|
36
|
+
expect(screen.queryByText(/^\+/)).toBeNull();
|
|
37
|
+
});
|
|
38
|
+
});
|
|
39
|
+
describe("AvatarGroup · overlap e ring", () => {
|
|
40
|
+
it("escrevem as variáveis do grupo em px", () => {
|
|
41
|
+
const { container } = render(_jsx(AvatarGroup, { avatars: PESSOAS, overlap: 6, ring: 1 }));
|
|
42
|
+
const el = grupo(container);
|
|
43
|
+
expect(el.style.getPropertyValue("--umds-avatar-group-overlap")).toBe("6px");
|
|
44
|
+
expect(el.style.getPropertyValue("--umds-avatar-group-ring")).toBe("1px");
|
|
45
|
+
});
|
|
46
|
+
it("só overlap não mexe no anel", () => {
|
|
47
|
+
const { container } = render(_jsx(AvatarGroup, { avatars: PESSOAS, overlap: 4 }));
|
|
48
|
+
const el = grupo(container);
|
|
49
|
+
expect(el.style.getPropertyValue("--umds-avatar-group-overlap")).toBe("4px");
|
|
50
|
+
expect(el.style.getPropertyValue("--umds-avatar-group-ring")).toBe("");
|
|
51
|
+
});
|
|
52
|
+
it("sem as props, nenhum style: valem os padrões do CSS", () => {
|
|
53
|
+
const { container } = render(_jsx(AvatarGroup, { avatars: PESSOAS }));
|
|
54
|
+
expect(grupo(container).getAttribute("style")).toBeNull();
|
|
55
|
+
});
|
|
56
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,42 @@
|
|
|
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 } from "@testing-library/react";
|
|
4
|
+
import Badge from "../components/Badge/Badge";
|
|
5
|
+
import Tag from "../components/Tag/Tag";
|
|
6
|
+
const raiz = (c) => c.firstElementChild;
|
|
7
|
+
describe("Badge compacto, novidade e colado", () => {
|
|
8
|
+
it("size 2xs escreve a classe; sem size continua md", () => {
|
|
9
|
+
const { container } = render(_jsxs(_Fragment, { children: [_jsx(Badge, { size: "2xs", children: "A" }), _jsx(Badge, { children: "B" })] }));
|
|
10
|
+
expect(container.children[0]).toHaveClass("umds-badge--2xs");
|
|
11
|
+
expect(container.children[1]).toHaveClass("umds-badge--md");
|
|
12
|
+
});
|
|
13
|
+
it("variant new escreve a classe da variante", () => {
|
|
14
|
+
const { container } = render(_jsx(Badge, { variant: "new", children: "Novidade" }));
|
|
15
|
+
expect(raiz(container)).toHaveClass("umds-badge--new");
|
|
16
|
+
});
|
|
17
|
+
it("attached escreve o modificador; sem ele não há", () => {
|
|
18
|
+
const { container } = render(_jsxs(_Fragment, { children: [_jsx(Badge, { attached: true, children: "A" }), _jsx(Badge, { children: "B" })] }));
|
|
19
|
+
expect(container.children[0]).toHaveClass("umds-badge--attached");
|
|
20
|
+
expect(container.children[1]).not.toHaveClass("umds-badge--attached");
|
|
21
|
+
});
|
|
22
|
+
});
|
|
23
|
+
describe("Tag compacta, soft, pílula e novidade", () => {
|
|
24
|
+
it("size xs escreve a classe e sm continua", () => {
|
|
25
|
+
const { container } = render(_jsxs(_Fragment, { children: [_jsx(Tag, { label: "a", size: "xs" }), _jsx(Tag, { label: "b", size: "sm" })] }));
|
|
26
|
+
expect(container.children[0]).toHaveClass("umds-tag--xs");
|
|
27
|
+
expect(container.children[1]).toHaveClass("umds-tag--sm");
|
|
28
|
+
});
|
|
29
|
+
it("appearance soft e pill escrevem as classes", () => {
|
|
30
|
+
const { container } = render(_jsx(Tag, { label: "SOBR", appearance: "soft", variant: "primary", pill: true }));
|
|
31
|
+
expect(raiz(container)).toHaveClass("umds-tag--soft", "umds-tag--primary", "umds-tag--pill");
|
|
32
|
+
});
|
|
33
|
+
it("sem pill não há a classe; padrão segue outlined", () => {
|
|
34
|
+
const { container } = render(_jsx(Tag, { label: "x" }));
|
|
35
|
+
expect(raiz(container)).toHaveClass("umds-tag--outlined");
|
|
36
|
+
expect(raiz(container)).not.toHaveClass("umds-tag--pill");
|
|
37
|
+
});
|
|
38
|
+
it("variant new escreve a classe", () => {
|
|
39
|
+
const { container } = render(_jsx(Tag, { label: "Dado simulado", variant: "new", appearance: "soft" }));
|
|
40
|
+
expect(raiz(container)).toHaveClass("umds-tag--new", "umds-tag--soft");
|
|
41
|
+
});
|
|
42
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,23 @@
|
|
|
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 BottomSheet from "../components/BottomSheet/BottomSheet";
|
|
5
|
+
/**
|
|
6
|
+
* BottomSheet sem `title`, sem `ariaLabel` e sem `ariaLabelledby` saía com
|
|
7
|
+
* `role="dialog"` anônimo. Agora cai no genérico "Painel", como o Drawer.
|
|
8
|
+
*/
|
|
9
|
+
describe("BottomSheet · nome acessível", () => {
|
|
10
|
+
it("com title, é nomeado pelo título", () => {
|
|
11
|
+
render(_jsx(BottomSheet, { open: true, title: "Detalhes do processo" }));
|
|
12
|
+
const painel = screen.getByRole("dialog", { name: "Detalhes do processo" });
|
|
13
|
+
expect(painel).not.toHaveAttribute("aria-label");
|
|
14
|
+
});
|
|
15
|
+
it("sem title, usa ariaLabel", () => {
|
|
16
|
+
render(_jsx(BottomSheet, { open: true, ariaLabel: "Filtros" }));
|
|
17
|
+
expect(screen.getByRole("dialog", { name: "Filtros" })).toBeInTheDocument();
|
|
18
|
+
});
|
|
19
|
+
it("sem nome nenhum, nunca sai anônimo", () => {
|
|
20
|
+
render(_jsx(BottomSheet, { open: true }));
|
|
21
|
+
expect(screen.getByRole("dialog", { name: "Painel" })).toBeInTheDocument();
|
|
22
|
+
});
|
|
23
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { jsx as _jsx, Fragment as _Fragment, 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 Box from "../components/Box/Box";
|
|
5
|
+
describe("Box como item flex e com `as`", () => {
|
|
6
|
+
it("sem `as` continua um div", () => {
|
|
7
|
+
const { container } = render(_jsx(Box, { padding: "md", children: "x" }));
|
|
8
|
+
expect(container.firstElementChild?.tagName).toBe("DIV");
|
|
9
|
+
});
|
|
10
|
+
for (const tag of ["div", "span", "ul", "ol", "li", "section", "nav", "header", "footer", "form"]) {
|
|
11
|
+
it(`as="${tag}" renderiza <${tag}> e só ele`, () => {
|
|
12
|
+
const { container } = render(_jsx(Box, { as: tag, children: "x" }));
|
|
13
|
+
expect(container.firstElementChild?.tagName).toBe(tag.toUpperCase());
|
|
14
|
+
expect(container.children).toHaveLength(1);
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
it("ul e ol mantêm a semântica de lista (role=list)", () => {
|
|
18
|
+
render(_jsxs(_Fragment, { children: [_jsx(Box, { as: "ul", "aria-label": "Itens", children: _jsx(Box, { as: "li", children: "a" }) }), _jsx(Box, { as: "ol", "aria-label": "Passos", children: _jsx(Box, { as: "li", children: "b" }) })] }));
|
|
19
|
+
expect(screen.getByRole("list", { name: "Itens" }).tagName).toBe("UL");
|
|
20
|
+
expect(screen.getByRole("list", { name: "Passos" }).tagName).toBe("OL");
|
|
21
|
+
});
|
|
22
|
+
it("nav com aria-label vira região de navegação nomeada", () => {
|
|
23
|
+
render(_jsx(Box, { as: "nav", "aria-label": "Atalhos", children: "x" }));
|
|
24
|
+
expect(screen.getByRole("navigation", { name: "Atalhos" })).toBeInTheDocument();
|
|
25
|
+
});
|
|
26
|
+
it("as=form chama onSubmit", () => {
|
|
27
|
+
const aoEnviar = vi.fn((e) => e.preventDefault());
|
|
28
|
+
const { container } = render(_jsx(Box, { as: "form", onSubmit: aoEnviar, children: _jsx("button", { type: "submit", children: "Enviar" }) }));
|
|
29
|
+
fireEvent.submit(container.querySelector("form"));
|
|
30
|
+
expect(aoEnviar).toHaveBeenCalledTimes(1);
|
|
31
|
+
});
|
|
32
|
+
it("escreve as classes de item flex", () => {
|
|
33
|
+
const { container } = render(_jsx(Box, { grow: true, shrink: "0", basis: "50", minWidth: "auto", overflow: "hidden", overflowX: "auto", overflowY: "scroll", fullHeight: true, fullWidth: true, children: "x" }));
|
|
34
|
+
const el = container.firstElementChild;
|
|
35
|
+
for (const c of [
|
|
36
|
+
"umds-box--grow",
|
|
37
|
+
"umds-box--shrink-0",
|
|
38
|
+
"umds-box--basis-50",
|
|
39
|
+
"umds-box--min-w-auto",
|
|
40
|
+
"umds-box--overflow-hidden",
|
|
41
|
+
"umds-box--overflow-x-auto",
|
|
42
|
+
"umds-box--overflow-y-scroll",
|
|
43
|
+
"umds-box--full-height",
|
|
44
|
+
"umds-box--full",
|
|
45
|
+
]) {
|
|
46
|
+
expect(el).toHaveClass(c);
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
it("sem as props de item não escreve nenhuma classe delas", () => {
|
|
50
|
+
const { container } = render(_jsx(Box, { padding: "md", children: "x" }));
|
|
51
|
+
const classes = container.firstElementChild.className;
|
|
52
|
+
expect(classes).not.toMatch(/grow|shrink|basis|min-w|overflow|full-height/);
|
|
53
|
+
});
|
|
54
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,35 @@
|
|
|
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 Box from "../components/Box/Box";
|
|
5
|
+
describe("Box de layout", () => {
|
|
6
|
+
it("sem props de layout não vira flex", () => {
|
|
7
|
+
const { container } = render(_jsx(Box, { padding: "md", bordered: true, children: "x" }));
|
|
8
|
+
expect(container.firstElementChild).not.toHaveClass("umds-box--flex");
|
|
9
|
+
});
|
|
10
|
+
it("com direction, gap, align, justify e wrap vira flex", () => {
|
|
11
|
+
const { container } = render(_jsx(Box, { direction: "horizontal", gap: "xxxs", align: "center", justify: "between", wrap: true, padding: "md", children: "x" }));
|
|
12
|
+
const el = container.firstElementChild;
|
|
13
|
+
for (const c of [
|
|
14
|
+
"umds-box--flex",
|
|
15
|
+
"umds-box--horizontal",
|
|
16
|
+
"umds-box--gap-xxxs",
|
|
17
|
+
"umds-box--align-center",
|
|
18
|
+
"umds-box--justify-between",
|
|
19
|
+
"umds-box--wrap",
|
|
20
|
+
"umds-box--p-md",
|
|
21
|
+
]) {
|
|
22
|
+
expect(el).toHaveClass(c);
|
|
23
|
+
}
|
|
24
|
+
});
|
|
25
|
+
it("só com gap vira flex vertical", () => {
|
|
26
|
+
const { container } = render(_jsx(Box, { gap: "xs", children: "x" }));
|
|
27
|
+
expect(container.firstElementChild).toHaveClass("umds-box--flex", "umds-box--vertical");
|
|
28
|
+
});
|
|
29
|
+
it("repassa id, role, aria-label e style", () => {
|
|
30
|
+
render(_jsx(Box, { id: "r", role: "region", "aria-label": "Resumo", style: { marginTop: 4 }, children: "x" }));
|
|
31
|
+
const el = screen.getByRole("region", { name: "Resumo" });
|
|
32
|
+
expect(el.id).toBe("r");
|
|
33
|
+
expect(el.style.marginTop).toBe("4px");
|
|
34
|
+
});
|
|
35
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,27 @@
|
|
|
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 { faPlus } from "@fortawesome/free-solid-svg-icons";
|
|
5
|
+
import Button from "../components/Button/Button";
|
|
6
|
+
describe("Button: variante neutral-text e tamanho xs", () => {
|
|
7
|
+
it("neutral-text escreve a classe da variante", () => {
|
|
8
|
+
render(_jsx(Button, { variant: "neutral-text", children: "Simular" }));
|
|
9
|
+
expect(screen.getByRole("button", { name: "Simular" })).toHaveClass("umds-button--neutral-text");
|
|
10
|
+
});
|
|
11
|
+
it("neutral continua sendo o contornado cinza", () => {
|
|
12
|
+
render(_jsx(Button, { variant: "neutral", children: "Ordenar" }));
|
|
13
|
+
const botao = screen.getByRole("button", { name: "Ordenar" });
|
|
14
|
+
expect(botao).toHaveClass("umds-button--neutral");
|
|
15
|
+
expect(botao).not.toHaveClass("umds-button--neutral-text");
|
|
16
|
+
});
|
|
17
|
+
it("size xs escreve a classe e o botão sem size continua md", () => {
|
|
18
|
+
render(_jsxs(_Fragment, { children: [_jsx(Button, { size: "xs", children: "Resolver" }), _jsx(Button, { children: "Padr\u00E3o" })] }));
|
|
19
|
+
expect(screen.getByRole("button", { name: "Resolver" })).toHaveClass("umds-button--xs");
|
|
20
|
+
expect(screen.getByRole("button", { name: "Padrão" })).toHaveClass("umds-button--md");
|
|
21
|
+
});
|
|
22
|
+
it("no xs o ícone usa o tamanho sm do Icon (o CSS do botão o reduz)", () => {
|
|
23
|
+
const { container } = render(_jsx(Button, { size: "xs", startIcon: faPlus, children: "Novo" }));
|
|
24
|
+
expect(container.querySelector(".umds-icon")).toHaveClass("umds-icon--sm");
|
|
25
|
+
expect(container.querySelector(".umds-icon--xs")).toBeNull();
|
|
26
|
+
});
|
|
27
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { describe, expect, it, vi } from "vitest";
|
|
3
|
+
import { useState } from "react";
|
|
4
|
+
import { render, screen, within } from "@testing-library/react";
|
|
5
|
+
import userEvent from "@testing-library/user-event";
|
|
6
|
+
import Calendar from "../components/Calendar/Calendar";
|
|
7
|
+
const HOJE = "2026-05-15";
|
|
8
|
+
const EVENTOS = [
|
|
9
|
+
{ id: "a", date: "2026-05-04", title: "Proc. Administrativo 002/2020", color: "--umds-primitive-blue-pure" },
|
|
10
|
+
{ id: "b", date: "2026-05-11", title: "Protocolo 005/2020", color: "--umds-primitive-green-pure", time: "09:00" },
|
|
11
|
+
{ id: "c", date: "2026-05-11", title: "Ofício 001/2020", color: "--umds-primitive-red-pure", time: "08:00" },
|
|
12
|
+
{ id: "d1", date: "2026-05-20", title: "Reunião 1" },
|
|
13
|
+
{ id: "d2", date: "2026-05-20", title: "Reunião 2" },
|
|
14
|
+
{ id: "d3", date: "2026-05-20", title: "Reunião 3" },
|
|
15
|
+
{ id: "d4", date: "2026-05-20", title: "Reunião 4" },
|
|
16
|
+
{ id: "d5", date: "2026-05-20", title: "Reunião 5" },
|
|
17
|
+
];
|
|
18
|
+
const celula = (container, iso) => container.querySelector(`[data-date="${iso}"]`);
|
|
19
|
+
describe("Calendar", () => {
|
|
20
|
+
it("é uma grade nomeada pelo mês, com sete cabeçalhos de dia", () => {
|
|
21
|
+
render(_jsx(Calendar, { today: HOJE, defaultDate: HOJE }));
|
|
22
|
+
expect(screen.getByRole("grid", { name: "Maio 2026" })).toBeInTheDocument();
|
|
23
|
+
const cabecalhos = screen.getAllByRole("columnheader");
|
|
24
|
+
expect(cabecalhos).toHaveLength(7);
|
|
25
|
+
expect(cabecalhos[0]).toHaveAccessibleName("Domingo");
|
|
26
|
+
expect(screen.getByText("Maio 2026")).toBeInTheDocument();
|
|
27
|
+
});
|
|
28
|
+
it("o mês de maio de 2026 ocupa seis semanas inteiras; dias de fora ganham a classe", () => {
|
|
29
|
+
const { container } = render(_jsx(Calendar, { today: HOJE, defaultDate: HOJE }));
|
|
30
|
+
expect(container.querySelectorAll('[role="gridcell"]')).toHaveLength(42);
|
|
31
|
+
expect(celula(container, "2026-04-26")).toHaveClass("umds-calendar__cell--outside");
|
|
32
|
+
expect(celula(container, "2026-05-15")).not.toHaveClass("umds-calendar__cell--outside");
|
|
33
|
+
});
|
|
34
|
+
it("hoje é marcado com aria-current", () => {
|
|
35
|
+
const { container } = render(_jsx(Calendar, { today: HOJE, defaultDate: HOJE }));
|
|
36
|
+
expect(celula(container, HOJE)).toHaveAttribute("aria-current", "date");
|
|
37
|
+
expect(celula(container, "2026-05-16")).not.toHaveAttribute("aria-current");
|
|
38
|
+
});
|
|
39
|
+
it("cada dia tem nome acessível com a data e a contagem de eventos", () => {
|
|
40
|
+
const { container } = render(_jsx(Calendar, { today: HOJE, defaultDate: HOJE, events: EVENTOS }));
|
|
41
|
+
expect(celula(container, "2026-05-11")).toHaveAttribute("aria-label", "segunda-feira, 11 de maio de 2026, 2 eventos");
|
|
42
|
+
expect(celula(container, "2026-05-04")).toHaveAttribute("aria-label", "segunda-feira, 4 de maio de 2026, 1 evento");
|
|
43
|
+
expect(celula(container, "2026-05-12")).toHaveAttribute("aria-label", "terça-feira, 12 de maio de 2026, sem eventos");
|
|
44
|
+
});
|
|
45
|
+
it("dayLabel troca o nome do dia", () => {
|
|
46
|
+
const { container } = render(_jsx(Calendar, { today: HOJE, defaultDate: HOJE, dayLabel: (iso, n) => `${iso}:${n}`, events: EVENTOS }));
|
|
47
|
+
expect(celula(container, "2026-05-11")).toHaveAttribute("aria-label", "2026-05-11:2");
|
|
48
|
+
});
|
|
49
|
+
it("os eventos caem no dia certo, em ordem de horário, com a cor do dado", () => {
|
|
50
|
+
const { container } = render(_jsx(Calendar, { today: HOJE, defaultDate: HOJE, events: EVENTOS }));
|
|
51
|
+
const dia = celula(container, "2026-05-11");
|
|
52
|
+
const chips = within(dia).getAllByRole("button");
|
|
53
|
+
expect(chips).toHaveLength(2);
|
|
54
|
+
expect(chips[0]).toHaveTextContent("08:00");
|
|
55
|
+
expect(chips[0]).toHaveTextContent("Ofício 001/2020");
|
|
56
|
+
expect(chips[0].style.borderLeftColor).toBe("var(--umds-primitive-red-pure)");
|
|
57
|
+
});
|
|
58
|
+
it("evento sem cor usa o primário", () => {
|
|
59
|
+
const { container } = render(_jsx(Calendar, { today: HOJE, defaultDate: HOJE, events: EVENTOS }));
|
|
60
|
+
const chip = within(celula(container, "2026-05-20")).getAllByRole("button")[0];
|
|
61
|
+
expect(chip.style.borderLeftColor).toBe("var(--umds-semantic-color-primary-pure)");
|
|
62
|
+
});
|
|
63
|
+
it("passou de maxVisible: mostra três e um +N, que avisa com os escondidos", async () => {
|
|
64
|
+
const usuario = userEvent.setup();
|
|
65
|
+
const aoVerMais = vi.fn();
|
|
66
|
+
const { container } = render(_jsx(Calendar, { today: HOJE, defaultDate: HOJE, events: EVENTOS, onMoreClick: aoVerMais }));
|
|
67
|
+
const dia = celula(container, "2026-05-20");
|
|
68
|
+
expect(within(dia).getAllByText(/Reunião/)).toHaveLength(3);
|
|
69
|
+
const mais = within(dia).getByRole("button", { name: "2 eventos a mais em 20 de maio" });
|
|
70
|
+
expect(mais).toHaveTextContent("+2");
|
|
71
|
+
await usuario.click(mais);
|
|
72
|
+
expect(aoVerMais).toHaveBeenCalledTimes(1);
|
|
73
|
+
expect(aoVerMais.mock.calls[0][0]).toBe("2026-05-20");
|
|
74
|
+
expect(aoVerMais.mock.calls[0][1].map((e) => e.id)).toEqual(["d4", "d5"]);
|
|
75
|
+
});
|
|
76
|
+
it("maxVisible muda o corte", () => {
|
|
77
|
+
const { container } = render(_jsx(Calendar, { today: HOJE, defaultDate: HOJE, events: EVENTOS, maxVisible: 1 }));
|
|
78
|
+
expect(within(celula(container, "2026-05-20")).getAllByText(/Reunião/)).toHaveLength(1);
|
|
79
|
+
expect(within(celula(container, "2026-05-20")).getByText("+4")).toBeInTheDocument();
|
|
80
|
+
});
|
|
81
|
+
it("clicar no evento avisa com o evento e não clica no dia", async () => {
|
|
82
|
+
const usuario = userEvent.setup();
|
|
83
|
+
const aoEvento = vi.fn();
|
|
84
|
+
const aoDia = vi.fn();
|
|
85
|
+
render(_jsx(Calendar, { today: HOJE, defaultDate: HOJE, events: EVENTOS, onEventClick: aoEvento, onDayClick: aoDia }));
|
|
86
|
+
await usuario.click(screen.getByRole("button", { name: /Proc\. Administrativo 002\/2020/ }));
|
|
87
|
+
expect(aoEvento).toHaveBeenCalledWith(expect.objectContaining({ id: "a" }));
|
|
88
|
+
expect(aoDia).not.toHaveBeenCalled();
|
|
89
|
+
});
|
|
90
|
+
it("clicar no dia avisa com o ISO", async () => {
|
|
91
|
+
const usuario = userEvent.setup();
|
|
92
|
+
const aoDia = vi.fn();
|
|
93
|
+
const { container } = render(_jsx(Calendar, { today: HOJE, defaultDate: HOJE, onDayClick: aoDia }));
|
|
94
|
+
await usuario.click(celula(container, "2026-05-12"));
|
|
95
|
+
expect(aoDia).toHaveBeenCalledWith("2026-05-12");
|
|
96
|
+
});
|
|
97
|
+
it("anterior, próximo e hoje navegam e avisam em onDateChange", async () => {
|
|
98
|
+
const usuario = userEvent.setup();
|
|
99
|
+
const aoMudar = vi.fn();
|
|
100
|
+
render(_jsx(Calendar, { today: HOJE, defaultDate: HOJE, onDateChange: aoMudar }));
|
|
101
|
+
await usuario.click(screen.getByRole("button", { name: "Próximo" }));
|
|
102
|
+
expect(screen.getByText("Junho 2026")).toBeInTheDocument();
|
|
103
|
+
expect(aoMudar).toHaveBeenLastCalledWith("2026-06-15");
|
|
104
|
+
await usuario.click(screen.getByRole("button", { name: "Anterior" }));
|
|
105
|
+
await usuario.click(screen.getByRole("button", { name: "Anterior" }));
|
|
106
|
+
expect(screen.getByText("Abril 2026")).toBeInTheDocument();
|
|
107
|
+
await usuario.click(screen.getByRole("button", { name: "Hoje" }));
|
|
108
|
+
expect(screen.getByText("Maio 2026")).toBeInTheDocument();
|
|
109
|
+
expect(aoMudar).toHaveBeenLastCalledWith(HOJE);
|
|
110
|
+
});
|
|
111
|
+
it("só um dia entra na ordem de Tab (hoje), com os eventos dele", () => {
|
|
112
|
+
const { container } = render(_jsx(Calendar, { today: "2026-05-11", defaultDate: "2026-05-11", events: EVENTOS }));
|
|
113
|
+
const comTab = [...container.querySelectorAll('[role="gridcell"]')].filter((c) => c.getAttribute("tabindex") === "0");
|
|
114
|
+
expect(comTab).toHaveLength(1);
|
|
115
|
+
expect(comTab[0]).toHaveAttribute("data-date", "2026-05-11");
|
|
116
|
+
const chipsComTab = [...container.querySelectorAll(".umds-calendar__event")].filter((c) => c.getAttribute("tabindex") === "0");
|
|
117
|
+
expect(chipsComTab).toHaveLength(2);
|
|
118
|
+
});
|
|
119
|
+
it("setas movem o foco entre os dias; Home, End e Enter", async () => {
|
|
120
|
+
const usuario = userEvent.setup();
|
|
121
|
+
const aoDia = vi.fn();
|
|
122
|
+
const { container } = render(_jsx(Calendar, { today: HOJE, defaultDate: HOJE, onDayClick: aoDia }));
|
|
123
|
+
celula(container, HOJE).focus();
|
|
124
|
+
await usuario.keyboard("{ArrowRight}");
|
|
125
|
+
expect(celula(container, "2026-05-16")).toHaveFocus();
|
|
126
|
+
await usuario.keyboard("{ArrowDown}");
|
|
127
|
+
expect(celula(container, "2026-05-23")).toHaveFocus();
|
|
128
|
+
await usuario.keyboard("{ArrowLeft}{ArrowUp}");
|
|
129
|
+
expect(celula(container, "2026-05-15")).toHaveFocus();
|
|
130
|
+
await usuario.keyboard("{Home}");
|
|
131
|
+
expect(celula(container, "2026-05-10")).toHaveFocus();
|
|
132
|
+
await usuario.keyboard("{End}");
|
|
133
|
+
expect(celula(container, "2026-05-16")).toHaveFocus();
|
|
134
|
+
await usuario.keyboard("{Enter}");
|
|
135
|
+
expect(aoDia).toHaveBeenCalledWith("2026-05-16");
|
|
136
|
+
});
|
|
137
|
+
it("a seta que sai do mês troca de mês e leva o foco", async () => {
|
|
138
|
+
const usuario = userEvent.setup();
|
|
139
|
+
const { container } = render(_jsx(Calendar, { today: HOJE, defaultDate: "2026-05-30" }));
|
|
140
|
+
celula(container, "2026-05-30").focus();
|
|
141
|
+
await usuario.keyboard("{ArrowRight}{ArrowRight}");
|
|
142
|
+
expect(screen.getByText("Junho 2026")).toBeInTheDocument();
|
|
143
|
+
expect(celula(container, "2026-06-01")).toHaveFocus();
|
|
144
|
+
});
|
|
145
|
+
it("PageDown e PageUp trocam de mês", async () => {
|
|
146
|
+
const usuario = userEvent.setup();
|
|
147
|
+
const { container } = render(_jsx(Calendar, { today: HOJE, defaultDate: HOJE }));
|
|
148
|
+
celula(container, HOJE).focus();
|
|
149
|
+
await usuario.keyboard("{PageDown}");
|
|
150
|
+
expect(screen.getByText("Junho 2026")).toBeInTheDocument();
|
|
151
|
+
expect(celula(container, "2026-06-15")).toHaveFocus();
|
|
152
|
+
await usuario.keyboard("{PageUp}{PageUp}");
|
|
153
|
+
expect(screen.getByText("Abril 2026")).toBeInTheDocument();
|
|
154
|
+
});
|
|
155
|
+
it("a visão de semana mostra sete dias, todos os eventos, e avisa em onViewChange", async () => {
|
|
156
|
+
const usuario = userEvent.setup();
|
|
157
|
+
const aoVisao = vi.fn();
|
|
158
|
+
const { container } = render(_jsx(Calendar, { today: "2026-05-20", defaultDate: "2026-05-20", events: EVENTOS, onViewChange: aoVisao }));
|
|
159
|
+
await usuario.click(screen.getByRole("radio", { name: "Semana" }));
|
|
160
|
+
expect(aoVisao).toHaveBeenCalledWith("week");
|
|
161
|
+
expect(container.querySelectorAll('[role="gridcell"]')).toHaveLength(7);
|
|
162
|
+
expect(within(celula(container, "2026-05-20")).getAllByText(/Reunião/)).toHaveLength(5);
|
|
163
|
+
expect(screen.queryByText("+2")).toBeNull();
|
|
164
|
+
expect(container.querySelector(".umds-calendar--week")).not.toBeNull();
|
|
165
|
+
});
|
|
166
|
+
it("na semana, anterior e próximo andam sete dias", async () => {
|
|
167
|
+
const usuario = userEvent.setup();
|
|
168
|
+
const aoMudar = vi.fn();
|
|
169
|
+
render(_jsx(Calendar, { today: "2026-05-20", defaultDate: "2026-05-20", defaultView: "week", onDateChange: aoMudar }));
|
|
170
|
+
await usuario.click(screen.getByRole("button", { name: "Próximo" }));
|
|
171
|
+
expect(aoMudar).toHaveBeenLastCalledWith("2026-05-27");
|
|
172
|
+
await usuario.click(screen.getByRole("button", { name: "Anterior" }));
|
|
173
|
+
await usuario.click(screen.getByRole("button", { name: "Anterior" }));
|
|
174
|
+
expect(aoMudar).toHaveBeenLastCalledWith("2026-05-13");
|
|
175
|
+
});
|
|
176
|
+
it("weekStartsOn=1 começa a semana na segunda", () => {
|
|
177
|
+
render(_jsx(Calendar, { today: HOJE, defaultDate: HOJE, weekStartsOn: 1 }));
|
|
178
|
+
expect(screen.getAllByRole("columnheader")[0]).toHaveAccessibleName("Segunda-feira");
|
|
179
|
+
});
|
|
180
|
+
it("controlado: date e view mandam", () => {
|
|
181
|
+
function Pai() {
|
|
182
|
+
const [data, setData] = useState("2026-08-10");
|
|
183
|
+
return _jsx(Calendar, { today: HOJE, date: data, onDateChange: setData, view: "month" });
|
|
184
|
+
}
|
|
185
|
+
render(_jsx(Pai, {}));
|
|
186
|
+
expect(screen.getByText("Agosto 2026")).toBeInTheDocument();
|
|
187
|
+
});
|
|
188
|
+
it("locale e textos por prop (inglês)", () => {
|
|
189
|
+
render(_jsx(Calendar, { today: HOJE, defaultDate: HOJE, locale: "en-US", previousLabel: "Previous", nextLabel: "Next", todayLabel: "Today", monthLabel: "Month", weekLabel: "Week", viewLabel: "View" }));
|
|
190
|
+
expect(screen.getByText("May 2026")).toBeInTheDocument();
|
|
191
|
+
expect(screen.getByRole("button", { name: "Previous" })).toBeInTheDocument();
|
|
192
|
+
expect(screen.getByRole("button", { name: "Next" })).toBeInTheDocument();
|
|
193
|
+
expect(screen.getByRole("button", { name: "Today" })).toBeInTheDocument();
|
|
194
|
+
expect(screen.getByRole("radio", { name: "Week" })).toBeInTheDocument();
|
|
195
|
+
expect(screen.getByRole("group", { name: "View" })).toBeInTheDocument();
|
|
196
|
+
expect(screen.getAllByRole("columnheader")[0]).toHaveAccessibleName("Sunday");
|
|
197
|
+
});
|
|
198
|
+
it("moreLabel e moreAriaLabel traduzem o +N", () => {
|
|
199
|
+
render(_jsx(Calendar, { today: HOJE, defaultDate: HOJE, events: EVENTOS, locale: "en-US", moreLabel: "{count} more", moreAriaLabel: "{count} more events on {date}" }));
|
|
200
|
+
expect(screen.getByRole("button", { name: "2 more events on May 20" })).toHaveTextContent("2 more");
|
|
201
|
+
});
|
|
202
|
+
it("hideViewSwitcher esconde o seletor; os slots do cabeçalho aparecem", () => {
|
|
203
|
+
render(_jsx(Calendar, { today: HOJE, defaultDate: HOJE, hideViewSwitcher: true, headerStart: _jsx("span", { "data-testid": "filtro", children: "Todos os documentos" }), headerEnd: _jsx("span", { "data-testid": "legenda", children: "Legenda" }) }));
|
|
204
|
+
expect(screen.queryByRole("radio")).toBeNull();
|
|
205
|
+
expect(screen.getByTestId("filtro")).toBeInTheDocument();
|
|
206
|
+
expect(screen.getByTestId("legenda")).toBeInTheDocument();
|
|
207
|
+
});
|
|
208
|
+
it("selectedDate marca o dia", () => {
|
|
209
|
+
const { container } = render(_jsx(Calendar, { today: HOJE, defaultDate: HOJE, selectedDate: "2026-05-12" }));
|
|
210
|
+
expect(celula(container, "2026-05-12")).toHaveAttribute("aria-selected", "true");
|
|
211
|
+
expect(celula(container, "2026-05-12")).toHaveClass("umds-calendar__cell--selected");
|
|
212
|
+
});
|
|
213
|
+
it("evento com Date e com data-hora entra no dia", () => {
|
|
214
|
+
const { container } = render(_jsx(Calendar, { today: HOJE, defaultDate: HOJE, events: [
|
|
215
|
+
{ date: new Date(2026, 4, 12), title: "Com Date" },
|
|
216
|
+
{ date: "2026-05-13T10:30:00", title: "Com hora" },
|
|
217
|
+
] }));
|
|
218
|
+
expect(within(celula(container, "2026-05-12")).getByText("Com Date")).toBeInTheDocument();
|
|
219
|
+
expect(within(celula(container, "2026-05-13")).getByText("Com hora")).toBeInTheDocument();
|
|
220
|
+
});
|
|
221
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|