@1doc/1ds-react 2.8.0 → 2.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +1540 -0
- package/dist/components/AILabel/AILabel.js +1 -1
- package/dist/components/Accordion/Accordion.css +13 -0
- package/dist/components/Accordion/Accordion.d.ts +9 -2
- package/dist/components/Accordion/Accordion.js +1 -0
- package/dist/components/AppSubheader/AppSubheader.css +10 -1
- package/dist/components/AttachmentCard/AttachmentCard.css +26 -8
- package/dist/components/AttachmentCard/AttachmentCard.d.ts +22 -2
- package/dist/components/AttachmentCard/AttachmentCard.js +47 -3
- package/dist/components/Avatar/Avatar.css +7 -2
- package/dist/components/Avatar/AvatarGroup.d.ts +17 -0
- package/dist/components/Avatar/AvatarGroup.js +22 -8
- package/dist/components/Badge/Badge.css +67 -2
- package/dist/components/Badge/Badge.d.ts +23 -4
- package/dist/components/Badge/Badge.js +4 -0
- 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 +126 -0
- package/dist/components/Calendar/Calendar.js +320 -0
- package/dist/components/Chips/Chips.css +38 -0
- package/dist/components/Chips/Chips.d.ts +5 -2
- package/dist/components/Chips/Chips.js +2 -1
- package/dist/components/Coachmark/Coachmark.css +128 -0
- package/dist/components/Coachmark/Coachmark.d.ts +87 -0
- package/dist/components/Coachmark/Coachmark.js +362 -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 +140 -0
- package/dist/components/ColorPicker/ColorPicker.d.ts +73 -0
- package/dist/components/ColorPicker/ColorPicker.js +219 -0
- package/dist/components/Combobox/Combobox.css +8 -0
- package/dist/components/DataTable/DataTable.css +254 -0
- package/dist/components/DataTable/DataTable.d.ts +81 -5
- package/dist/components/DataTable/DataTable.js +335 -19
- package/dist/components/DatePicker/DatePicker.css +8 -0
- package/dist/components/DatePicker/DatePicker.js +10 -1
- package/dist/components/DescriptionList/DescriptionList.css +127 -0
- package/dist/components/DescriptionList/DescriptionList.d.ts +62 -0
- package/dist/components/DescriptionList/DescriptionList.js +52 -0
- package/dist/components/EmptyState/EmptyState.d.ts +4 -2
- package/dist/components/EmptyState/EmptyState.js +2 -2
- package/dist/components/FileInput/FileInput.css +16 -0
- package/dist/components/FileInput/FileInput.d.ts +4 -2
- package/dist/components/FileInput/FileInput.js +8 -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 +59 -0
- package/dist/components/Input/Input.d.ts +17 -1
- package/dist/components/Input/Input.js +67 -5
- package/dist/components/Kanban/Kanban.css +4 -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/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 +97 -0
- package/dist/components/List/ListItem.js +82 -0
- package/dist/components/Modal/Modal.css +80 -0
- package/dist/components/Modal/Modal.d.ts +33 -6
- package/dist/components/Modal/Modal.js +101 -6
- package/dist/components/MultiSelect/MultiSelect.css +8 -0
- package/dist/components/MultiSelect/MultiSelect.js +10 -1
- 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/PhoneInput/PhoneInput.css +8 -0
- package/dist/components/Popover/Popover.d.ts +7 -0
- package/dist/components/Popover/Popover.js +11 -1
- package/dist/components/RichTextEditor/RichTextEditor.css +250 -0
- package/dist/components/RichTextEditor/RichTextEditor.d.ts +97 -0
- package/dist/components/RichTextEditor/RichTextEditor.js +951 -0
- package/dist/components/SegmentedControl/SegmentedControl.css +24 -0
- package/dist/components/SegmentedControl/SegmentedControl.d.ts +2 -0
- package/dist/components/SegmentedControl/SegmentedControl.js +10 -2
- package/dist/components/Select/Select.css +164 -0
- package/dist/components/Select/Select.d.ts +34 -0
- package/dist/components/Select/Select.js +258 -28
- 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 +138 -0
- package/dist/components/StatCard/StatCard.d.ts +26 -0
- package/dist/components/StatCard/StatCard.js +13 -1
- 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.js +2 -2
- package/dist/components/Textarea/Textarea.css +8 -0
- package/dist/components/TimePicker/TimePicker.css +8 -0
- package/dist/components/Toast/Toast.css +32 -0
- package/dist/components/Toast/Toast.d.ts +18 -0
- package/dist/components/Toast/Toast.js +14 -1
- package/dist/components/Toast/ToastStack.js +8 -1
- package/dist/components/Tooltip/Tooltip.css +25 -0
- package/dist/components/Tooltip/Tooltip.d.ts +11 -0
- package/dist/components/Tooltip/Tooltip.js +18 -3
- 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/AccordionTituloNeutro.test.d.ts +1 -0
- package/dist/teste/AccordionTituloNeutro.test.js +23 -0
- package/dist/teste/AppSubheaderRegiao.test.d.ts +1 -0
- package/dist/teste/AppSubheaderRegiao.test.js +13 -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/AttachmentCardLista.test.d.ts +1 -0
- package/dist/teste/AttachmentCardLista.test.js +49 -0
- package/dist/teste/AttachmentCardSm.test.d.ts +1 -0
- package/dist/teste/AttachmentCardSm.test.js +26 -0
- package/dist/teste/AvatarGroupOverlap.test.d.ts +1 -0
- package/dist/teste/AvatarGroupOverlap.test.js +56 -0
- package/dist/teste/BadgeNeutroColado.test.d.ts +1 -0
- package/dist/teste/BadgeNeutroColado.test.js +11 -0
- package/dist/teste/BadgeTag.test.d.ts +1 -0
- package/dist/teste/BadgeTag.test.js +55 -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/CalendarCabecalho.test.d.ts +1 -0
- package/dist/teste/CalendarCabecalho.test.js +11 -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/CoachmarkSemVeu.test.d.ts +1 -0
- package/dist/teste/CoachmarkSemVeu.test.js +85 -0
- package/dist/teste/ColorPicker.test.d.ts +1 -0
- package/dist/teste/ColorPicker.test.js +132 -0
- package/dist/teste/ColorPickerXs.test.d.ts +1 -0
- package/dist/teste/ColorPickerXs.test.js +21 -0
- package/dist/teste/DataTableArvoreEVariantes.test.d.ts +1 -0
- package/dist/teste/DataTableArvoreEVariantes.test.js +190 -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/DescriptionListCompacta.test.d.ts +1 -0
- package/dist/teste/DescriptionListCompacta.test.js +22 -0
- package/dist/teste/EmptyStateTituloRico.test.d.ts +1 -0
- package/dist/teste/EmptyStateTituloRico.test.js +23 -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/InputAgrupado.test.d.ts +1 -0
- package/dist/teste/InputAgrupado.test.js +24 -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/ListItemTooltipStandalone.test.d.ts +1 -0
- package/dist/teste/ListItemTooltipStandalone.test.js +39 -0
- package/dist/teste/ModalVariantes.test.d.ts +1 -0
- package/dist/teste/ModalVariantes.test.js +151 -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/RichTextEditorAlinhaImagemTabela.test.d.ts +1 -0
- package/dist/teste/RichTextEditorAlinhaImagemTabela.test.js +212 -0
- package/dist/teste/RichTextEditorEstiloDeTexto.test.d.ts +1 -0
- package/dist/teste/RichTextEditorEstiloDeTexto.test.js +120 -0
- package/dist/teste/SegmentedControlContador.test.d.ts +1 -0
- package/dist/teste/SegmentedControlContador.test.js +39 -0
- package/dist/teste/SelectAbertoControladoEFlutuante.test.d.ts +1 -0
- package/dist/teste/SelectAbertoControladoEFlutuante.test.js +145 -0
- package/dist/teste/SelectFiltroCorETamanho.test.d.ts +1 -0
- package/dist/teste/SelectFiltroCorETamanho.test.js +77 -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/StatCardSecundariaETom.test.d.ts +1 -0
- package/dist/teste/StatCardSecundariaETom.test.js +45 -0
- package/dist/teste/TabsContadorFechavel.test.d.ts +1 -0
- package/dist/teste/TabsContadorFechavel.test.js +79 -0
- package/dist/teste/ToastAcaoEDetalhes.test.d.ts +1 -0
- package/dist/teste/ToastAcaoEDetalhes.test.js +94 -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/html-seguro.d.ts +45 -0
- package/dist/utils/html-seguro.js +208 -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/dist/utils/toast.d.ts +10 -1
- package/dist/utils/toast.js +2 -1
- 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/AccordionTituloNeutro.test.tsx +25 -0
- package/src/teste/AppSubheaderRegiao.test.tsx +17 -0
- package/src/teste/AtributosRepassados.test.tsx +73 -0
- package/src/teste/AttachmentCardIA.test.tsx +126 -0
- package/src/teste/AttachmentCardLista.test.tsx +53 -0
- package/src/teste/AttachmentCardSm.test.tsx +29 -0
- package/src/teste/AvatarGroupOverlap.test.tsx +74 -0
- package/src/teste/BadgeNeutroColado.test.tsx +15 -0
- package/src/teste/BadgeTag.test.tsx +85 -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/CalendarCabecalho.test.tsx +11 -0
- package/src/teste/ChipsXs.test.tsx +41 -0
- package/src/teste/Coachmark.test.tsx +198 -0
- package/src/teste/CoachmarkSemVeu.test.tsx +101 -0
- package/src/teste/ColorPicker.test.tsx +153 -0
- package/src/teste/ColorPickerXs.test.tsx +22 -0
- package/src/teste/DataTableArvoreEVariantes.test.tsx +240 -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/DescriptionListCompacta.test.tsx +24 -0
- package/src/teste/EmptyStateTituloRico.test.tsx +34 -0
- package/src/teste/FileInputTrigger.test.tsx +89 -0
- package/src/teste/IconPicker.test.tsx +145 -0
- package/src/teste/InputAgrupado.test.tsx +26 -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/ListItemTooltipStandalone.test.tsx +64 -0
- package/src/teste/ModalVariantes.test.tsx +173 -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/RichTextEditorAlinhaImagemTabela.test.tsx +238 -0
- package/src/teste/RichTextEditorEstiloDeTexto.test.tsx +137 -0
- package/src/teste/SegmentedControlContador.test.tsx +43 -0
- package/src/teste/SelectAbertoControladoEFlutuante.test.tsx +180 -0
- package/src/teste/SelectFiltroCorETamanho.test.tsx +90 -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/StatCardSecundariaETom.test.tsx +51 -0
- package/src/teste/TabsContadorFechavel.test.tsx +144 -0
- package/src/teste/ToastAcaoEDetalhes.test.tsx +109 -0
- package/src/teste/TooltipDark.test.tsx +51 -0
- package/src/utils/calendario.ts +78 -0
- package/src/utils/html-seguro.ts +197 -0
- package/src/utils/paleta-de-cores.ts +34 -0
- package/src/utils/texto.ts +5 -0
- package/src/utils/toast.ts +12 -2
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { describe, expect, it, vi } from "vitest";
|
|
2
|
+
import { render, screen, fireEvent } from "@testing-library/react";
|
|
3
|
+
import ListItem from "../components/List/ListItem";
|
|
4
|
+
|
|
5
|
+
describe("ListItem: tooltip, standalone e atributos só no elemento interativo", () => {
|
|
6
|
+
it("tooltip vira o atributo title do elemento interativo, e o li fica limpo", () => {
|
|
7
|
+
const { container } = render(
|
|
8
|
+
<ul>
|
|
9
|
+
<ListItem title="Memorando 114/2025" tooltip="Abrir o memorando" aria-label="Memorando" role="menuitem" data-origem="home" />
|
|
10
|
+
</ul>,
|
|
11
|
+
);
|
|
12
|
+
const li = container.querySelector("li") as HTMLElement;
|
|
13
|
+
const botao = screen.getByRole("menuitem");
|
|
14
|
+
expect(botao).toHaveAttribute("title", "Abrir o memorando");
|
|
15
|
+
expect(botao).toHaveAttribute("aria-label", "Memorando");
|
|
16
|
+
expect(botao).toHaveAttribute("data-origem", "home");
|
|
17
|
+
for (const atributo of ["title", "aria-label", "role", "data-origem"]) expect(li).not.toHaveAttribute(atributo);
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
it("tooltip funciona no link e na linha div; sem tooltip não há title", () => {
|
|
21
|
+
const { container } = render(
|
|
22
|
+
<ul>
|
|
23
|
+
<ListItem title="Link" href="/x" tooltip="Dica do link" />
|
|
24
|
+
<ListItem as="div" title="Div" tooltip="Dica da div" />
|
|
25
|
+
<ListItem title="Sem dica" />
|
|
26
|
+
</ul>,
|
|
27
|
+
);
|
|
28
|
+
const titulos = [...container.querySelectorAll(".umds-list-item")].map((e) => e.getAttribute("title"));
|
|
29
|
+
expect(titulos).toEqual(["Dica do link", "Dica da div", null]);
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
it("o título da linha continua sendo texto, não o atributo", () => {
|
|
33
|
+
const { container } = render(
|
|
34
|
+
<ul>
|
|
35
|
+
<ListItem title="Só o título" />
|
|
36
|
+
</ul>,
|
|
37
|
+
);
|
|
38
|
+
expect(container.querySelector("[title]")).toBeNull();
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
it("standalone renderiza sem li, só o elemento interativo", () => {
|
|
42
|
+
const aoClicar = vi.fn();
|
|
43
|
+
const { container } = render(
|
|
44
|
+
<div>
|
|
45
|
+
<ListItem standalone title="12" tooltip="Página 12" onClick={aoClicar} />
|
|
46
|
+
</div>,
|
|
47
|
+
);
|
|
48
|
+
expect(container.querySelector("li")).toBeNull();
|
|
49
|
+
const botao = screen.getByRole("button", { name: /12/ });
|
|
50
|
+
expect(botao.parentElement?.tagName).toBe("DIV");
|
|
51
|
+
expect(botao).toHaveAttribute("title", "Página 12");
|
|
52
|
+
fireEvent.click(botao);
|
|
53
|
+
expect(aoClicar).toHaveBeenCalledTimes(1);
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
it("sem standalone o li continua lá", () => {
|
|
57
|
+
const { container } = render(
|
|
58
|
+
<ul>
|
|
59
|
+
<ListItem title="Normal" />
|
|
60
|
+
</ul>,
|
|
61
|
+
);
|
|
62
|
+
expect(container.querySelectorAll("li")).toHaveLength(1);
|
|
63
|
+
});
|
|
64
|
+
});
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
import { afterEach, describe, expect, it, vi } from "vitest";
|
|
2
|
+
import { act, fireEvent, render, screen } from "@testing-library/react";
|
|
3
|
+
import Modal from "../components/Modal/Modal";
|
|
4
|
+
import Select from "../components/Select/Select";
|
|
5
|
+
|
|
6
|
+
afterEach(() => {
|
|
7
|
+
vi.unstubAllGlobals();
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
/** Troca `window.matchMedia` por um que responde `matches` e deixa disparar `change`. */
|
|
11
|
+
function simularTela(matches: boolean) {
|
|
12
|
+
const ouvintes = new Set<(e: { matches: boolean }) => void>();
|
|
13
|
+
vi.stubGlobal("matchMedia", (consulta: string) => ({
|
|
14
|
+
matches,
|
|
15
|
+
media: consulta,
|
|
16
|
+
addEventListener: (_: string, fn: any) => ouvintes.add(fn),
|
|
17
|
+
removeEventListener: (_: string, fn: any) => ouvintes.delete(fn),
|
|
18
|
+
}));
|
|
19
|
+
return (novo: boolean) => ouvintes.forEach((fn) => fn({ matches: novo }));
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
describe("Modal · variant primary", () => {
|
|
23
|
+
it("fica no modal base (três faixas), com a classe do cabeçalho cheio", () => {
|
|
24
|
+
render(<Modal open inline variant="primary" title="Resolver tarefa" />);
|
|
25
|
+
const dialogo = screen.getByRole("dialog", { name: "Resolver tarefa" });
|
|
26
|
+
expect(dialogo).toHaveClass("umds-modal--primary", "umds-modal--base");
|
|
27
|
+
expect(dialogo).not.toHaveClass("umds-modal--feedback");
|
|
28
|
+
expect(dialogo.querySelector(".umds-modal__header")).not.toBeNull();
|
|
29
|
+
expect(dialogo.querySelector(".umds-modal__icon")).toBeNull();
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
it("positive continua sendo diálogo de feedback", () => {
|
|
33
|
+
render(<Modal open inline variant="positive" title="Pronto" />);
|
|
34
|
+
expect(screen.getByRole("dialog")).toHaveClass("umds-modal--feedback");
|
|
35
|
+
});
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
describe("Modal · width e maxWidth", () => {
|
|
39
|
+
it("escreve a largura e, sem maxWidth, solta o teto do size", () => {
|
|
40
|
+
render(<Modal open inline title="x" width="600px" />);
|
|
41
|
+
const dialogo = screen.getByRole("dialog");
|
|
42
|
+
expect(dialogo.style.width).toBe("600px");
|
|
43
|
+
expect(dialogo.style.maxWidth).toBe("100%");
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
it("maxWidth explícito vale", () => {
|
|
47
|
+
render(<Modal open inline title="x" width="90%" maxWidth="720px" />);
|
|
48
|
+
expect(screen.getByRole("dialog").style.maxWidth).toBe("720px");
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
it("sem width nem maxWidth não escreve style", () => {
|
|
52
|
+
render(<Modal open inline title="x" />);
|
|
53
|
+
expect(screen.getByRole("dialog").getAttribute("style")).toBeNull();
|
|
54
|
+
});
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
describe("Modal · Escape", () => {
|
|
58
|
+
it("fecha com Escape no borbulho", () => {
|
|
59
|
+
const aoFechar = vi.fn();
|
|
60
|
+
render(<Modal open inline title="x" onClose={aoFechar} />);
|
|
61
|
+
fireEvent.keyDown(document.body, { key: "Escape" });
|
|
62
|
+
expect(aoFechar).toHaveBeenCalledTimes(1);
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
it("não fecha quando outro componente já consumiu a tecla (defaultPrevented)", () => {
|
|
66
|
+
const aoFechar = vi.fn();
|
|
67
|
+
render(<Modal open inline title="x" onClose={aoFechar} />);
|
|
68
|
+
const consumidor = document.createElement("div");
|
|
69
|
+
consumidor.addEventListener("keydown", (e) => e.preventDefault());
|
|
70
|
+
document.body.appendChild(consumidor);
|
|
71
|
+
fireEvent.keyDown(consumidor, { key: "Escape" });
|
|
72
|
+
expect(aoFechar).not.toHaveBeenCalled();
|
|
73
|
+
consumidor.remove();
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
it("Select aberto dentro do modal fecha só a lista, e o modal fica", () => {
|
|
77
|
+
const aoFechar = vi.fn();
|
|
78
|
+
render(
|
|
79
|
+
<Modal open inline title="x" onClose={aoFechar}>
|
|
80
|
+
<Select label="Categoria" options={[{ label: "Administrativa", value: "adm" }]} />
|
|
81
|
+
</Modal>,
|
|
82
|
+
);
|
|
83
|
+
const gatilho = screen.getByRole("combobox");
|
|
84
|
+
fireEvent.click(gatilho);
|
|
85
|
+
expect(gatilho).toHaveAttribute("aria-expanded", "true");
|
|
86
|
+
fireEvent.keyDown(gatilho, { key: "Escape" });
|
|
87
|
+
expect(gatilho).toHaveAttribute("aria-expanded", "false");
|
|
88
|
+
expect(aoFechar).not.toHaveBeenCalled();
|
|
89
|
+
// Com o Select fechado, o Esc seguinte é do modal.
|
|
90
|
+
fireEvent.keyDown(gatilho, { key: "Escape" });
|
|
91
|
+
expect(aoFechar).toHaveBeenCalledTimes(1);
|
|
92
|
+
});
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
describe("Modal · controles de janela escolhidos um a um", () => {
|
|
96
|
+
it("true liga os quatro, como antes", () => {
|
|
97
|
+
render(<Modal open inline title="x" windowControls />);
|
|
98
|
+
for (const nome of ["Modo normal", "Expandir", "Tela cheia", "Minimizar"]) {
|
|
99
|
+
expect(screen.getByRole("button", { name: nome })).toBeInTheDocument();
|
|
100
|
+
}
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
it("lista escolhe só os pedidos, sem minimizar", () => {
|
|
104
|
+
render(<Modal open inline title="x" windowControls={["expand", "fullscreen"]} />);
|
|
105
|
+
expect(screen.getByRole("button", { name: "Expandir" })).toBeInTheDocument();
|
|
106
|
+
expect(screen.getByRole("button", { name: "Tela cheia" })).toBeInTheDocument();
|
|
107
|
+
expect(screen.queryByRole("button", { name: "Minimizar" })).toBeNull();
|
|
108
|
+
expect(screen.queryByRole("button", { name: "Modo normal" })).toBeNull();
|
|
109
|
+
expect(screen.getByRole("button", { name: "Fechar" })).toBeInTheDocument();
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
it("sem windowControls só há o ×", () => {
|
|
113
|
+
render(<Modal open inline title="x" />);
|
|
114
|
+
expect(screen.queryByRole("button", { name: "Expandir" })).toBeNull();
|
|
115
|
+
expect(screen.getByRole("button", { name: "Fechar" })).toBeInTheDocument();
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
it("sem o botão normal, clicar de novo no modo ativo volta ao normal; e o normal usa o tamanho do modal", () => {
|
|
119
|
+
render(<Modal open inline title="x" width="600px" windowControls={["expand"]} />);
|
|
120
|
+
const dialogo = screen.getByRole("dialog");
|
|
121
|
+
const expandir = screen.getByRole("button", { name: "Expandir" });
|
|
122
|
+
expect(dialogo).not.toHaveClass("umds-modal--janela-normal");
|
|
123
|
+
expect(dialogo.style.width).toBe("600px");
|
|
124
|
+
fireEvent.click(expandir);
|
|
125
|
+
expect(dialogo).toHaveClass("umds-modal--janela-expanded");
|
|
126
|
+
expect(dialogo.style.width).toBe("");
|
|
127
|
+
fireEvent.click(expandir);
|
|
128
|
+
expect(dialogo).not.toHaveClass("umds-modal--janela-expanded");
|
|
129
|
+
expect(dialogo.style.width).toBe("600px");
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
it("minimizar chama onMinimize", () => {
|
|
133
|
+
const aoMinimizar = vi.fn();
|
|
134
|
+
render(<Modal open inline title="x" windowControls={["minimize"]} onMinimize={aoMinimizar} />);
|
|
135
|
+
fireEvent.click(screen.getByRole("button", { name: "Minimizar" }));
|
|
136
|
+
expect(aoMinimizar).toHaveBeenCalledTimes(1);
|
|
137
|
+
});
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
describe("Modal · responsive", () => {
|
|
141
|
+
it("em tela larga continua centralizado", () => {
|
|
142
|
+
simularTela(false);
|
|
143
|
+
render(<Modal open inline title="x" responsive />);
|
|
144
|
+
expect(screen.getByRole("dialog")).not.toHaveClass("umds-modal--sheet");
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
it("em tela estreita vira painel de baixo, sem controles de janela e sem a largura livre", () => {
|
|
148
|
+
simularTela(true);
|
|
149
|
+
render(<Modal open inline title="x" responsive width="600px" windowControls />);
|
|
150
|
+
const dialogo = screen.getByRole("dialog");
|
|
151
|
+
expect(dialogo).toHaveClass("umds-modal--sheet");
|
|
152
|
+
expect(dialogo.style.width).toBe("");
|
|
153
|
+
expect(screen.queryByRole("button", { name: "Expandir" })).toBeNull();
|
|
154
|
+
expect(dialogo.querySelector(".umds-modal__grabber")).not.toBeNull();
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
it("acompanha a mudança de tamanho da tela", () => {
|
|
158
|
+
const mudar = simularTela(false);
|
|
159
|
+
render(<Modal open inline title="x" responsive />);
|
|
160
|
+
const dialogo = screen.getByRole("dialog");
|
|
161
|
+
expect(dialogo).not.toHaveClass("umds-modal--sheet");
|
|
162
|
+
act(() => mudar(true));
|
|
163
|
+
expect(screen.getByRole("dialog")).toHaveClass("umds-modal--sheet");
|
|
164
|
+
act(() => mudar(false));
|
|
165
|
+
expect(screen.getByRole("dialog")).not.toHaveClass("umds-modal--sheet");
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
it("sem responsive nunca vira painel", () => {
|
|
169
|
+
simularTela(true);
|
|
170
|
+
render(<Modal open inline title="x" />);
|
|
171
|
+
expect(screen.getByRole("dialog")).not.toHaveClass("umds-modal--sheet");
|
|
172
|
+
});
|
|
173
|
+
});
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import { afterEach, describe, expect, it, vi } from "vitest";
|
|
2
|
+
import { act, screen } from "@testing-library/react";
|
|
3
|
+
import { renderToString } from "react-dom/server";
|
|
4
|
+
import { hydrateRoot } from "react-dom/client";
|
|
5
|
+
import Select from "../components/Select/Select";
|
|
6
|
+
import MultiSelect from "../components/MultiSelect/MultiSelect";
|
|
7
|
+
import SegmentedControl from "../components/SegmentedControl/SegmentedControl";
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Select, MultiSelect e SegmentedControl nascem SEM id automático (utils/id):
|
|
11
|
+
* o id só é gerado no onMount, para o servidor e a primeira renderização do
|
|
12
|
+
* cliente saírem idênticos. Só que o nome acessível deles vinha de
|
|
13
|
+
* `aria-labelledby` apontando para esse id — no HTML do servidor, e até a
|
|
14
|
+
* hidratação, o combobox ficava sem nome (axe `aria-input-field-name`, visto
|
|
15
|
+
* no portal Astro com `client:visible`).
|
|
16
|
+
*
|
|
17
|
+
* Aqui o HTML sai do `renderToString`, que não dispara o onMount, e vai para
|
|
18
|
+
* o DOM do jsdom como o navegador receberia. O nome é conferido pelo cálculo
|
|
19
|
+
* do Testing Library, o mesmo algoritmo de nome acessível que o axe usa.
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
const OPCOES = [
|
|
23
|
+
{ label: "Recursos Humanos", value: "rh" },
|
|
24
|
+
{ label: "Financeiro", value: "fin" },
|
|
25
|
+
];
|
|
26
|
+
const POR_PAGINA = [
|
|
27
|
+
{ label: "10", value: "10" },
|
|
28
|
+
{ label: "25", value: "25" },
|
|
29
|
+
];
|
|
30
|
+
|
|
31
|
+
function comoDoServidor(html: string) {
|
|
32
|
+
const raiz = document.createElement("div");
|
|
33
|
+
raiz.innerHTML = html;
|
|
34
|
+
document.body.appendChild(raiz);
|
|
35
|
+
return raiz;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
describe("Nome acessível no HTML do servidor", () => {
|
|
39
|
+
// As raízes são montadas à mão (fora do render), e o cleanup global não as vê.
|
|
40
|
+
afterEach(() => {
|
|
41
|
+
document.body.innerHTML = "";
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
it("Select: o combobox tem o nome do label antes do mount", () => {
|
|
45
|
+
comoDoServidor(renderToString(<Select label="Setor" options={OPCOES} />));
|
|
46
|
+
const campo = screen.getByRole("combobox", { name: "Setor" });
|
|
47
|
+
expect(campo).not.toHaveAttribute("aria-labelledby");
|
|
48
|
+
expect(campo).toHaveAttribute("aria-label", "Setor");
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
it("Select: `ariaLabel` continua valendo sobre o label", () => {
|
|
52
|
+
comoDoServidor(
|
|
53
|
+
renderToString(<Select label="Setor" ariaLabel="Setor do servidor" options={OPCOES} />),
|
|
54
|
+
);
|
|
55
|
+
expect(
|
|
56
|
+
screen.getByRole("combobox", { name: "Setor do servidor" }),
|
|
57
|
+
).toBeInTheDocument();
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
it("Select com `id`: o servidor já liga pelo aria-labelledby", () => {
|
|
61
|
+
const html = renderToString(<Select id="setor" label="Setor" options={OPCOES} />);
|
|
62
|
+
expect(html).toContain('aria-labelledby="setor-label"');
|
|
63
|
+
expect(html).not.toContain('aria-label="Setor"');
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
it("MultiSelect: o combobox tem o nome do label antes do mount", () => {
|
|
67
|
+
comoDoServidor(renderToString(<MultiSelect label="Setores" options={OPCOES} />));
|
|
68
|
+
expect(screen.getByRole("combobox", { name: "Setores" })).toBeInTheDocument();
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
it("SegmentedControl: grupo e segmentos têm nome antes do mount", () => {
|
|
72
|
+
comoDoServidor(
|
|
73
|
+
renderToString(<SegmentedControl label="Itens" options={POR_PAGINA} />),
|
|
74
|
+
);
|
|
75
|
+
expect(screen.getByRole("radiogroup", { name: "Itens" })).toBeInTheDocument();
|
|
76
|
+
expect(screen.getByRole("radio", { name: "10" })).toBeInTheDocument();
|
|
77
|
+
expect(screen.getByRole("radio", { name: "25" })).toBeInTheDocument();
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
it("hidrata sem divergência e, montado, volta ao aria-labelledby", async () => {
|
|
81
|
+
const arvore = (
|
|
82
|
+
<div>
|
|
83
|
+
<Select label="Setor" options={OPCOES} />
|
|
84
|
+
<MultiSelect label="Setores" options={OPCOES} />
|
|
85
|
+
<SegmentedControl label="Itens" options={POR_PAGINA} />
|
|
86
|
+
</div>
|
|
87
|
+
);
|
|
88
|
+
const raiz = comoDoServidor(renderToString(arvore));
|
|
89
|
+
const erro = vi.spyOn(console, "error").mockImplementation(() => {});
|
|
90
|
+
const avisosDeHidratacao: unknown[] = [];
|
|
91
|
+
await act(async () => {
|
|
92
|
+
hydrateRoot(raiz, arvore, {
|
|
93
|
+
onRecoverableError: (e) => avisosDeHidratacao.push(e),
|
|
94
|
+
});
|
|
95
|
+
});
|
|
96
|
+
const chamadas = erro.mock.calls.map((c) => String(c[0]));
|
|
97
|
+
erro.mockRestore();
|
|
98
|
+
expect(avisosDeHidratacao).toEqual([]);
|
|
99
|
+
expect(chamadas.filter((c) => /hydrat|did not match/i.test(c))).toEqual([]);
|
|
100
|
+
|
|
101
|
+
const select = screen.getByRole("combobox", { name: "Setor" });
|
|
102
|
+
expect(select).toHaveAttribute("aria-labelledby");
|
|
103
|
+
expect(select).not.toHaveAttribute("aria-label");
|
|
104
|
+
const multi = screen.getByRole("combobox", { name: "Setores" });
|
|
105
|
+
expect(multi).toHaveAttribute("aria-labelledby");
|
|
106
|
+
const grupo = screen.getByRole("radiogroup", { name: "Itens" });
|
|
107
|
+
expect(grupo).toHaveAttribute("aria-labelledby");
|
|
108
|
+
expect(screen.getByRole("radio", { name: "10" })).not.toHaveAttribute("aria-label");
|
|
109
|
+
});
|
|
110
|
+
});
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
import { describe, expect, it, vi } from "vitest";
|
|
2
|
+
import { useState } from "react";
|
|
3
|
+
import { fireEvent, render, screen, within } from "@testing-library/react";
|
|
4
|
+
import userEvent from "@testing-library/user-event";
|
|
5
|
+
import OrgChart from "../components/OrgChart/OrgChart";
|
|
6
|
+
|
|
7
|
+
const ARVORE = [
|
|
8
|
+
{
|
|
9
|
+
id: "copirn",
|
|
10
|
+
title: "COPIRN",
|
|
11
|
+
subtitle: "Companhia Potiguar de Infraestrutura",
|
|
12
|
+
children: [
|
|
13
|
+
{ id: "aj", title: "AJ", subtitle: "Assessoria Jurídica" },
|
|
14
|
+
{
|
|
15
|
+
id: "sadm",
|
|
16
|
+
title: "SADM",
|
|
17
|
+
subtitle: "Secretaria de Administração",
|
|
18
|
+
children: [
|
|
19
|
+
{ id: "al", title: "AL", subtitle: "Almoxarifado" },
|
|
20
|
+
{ id: "ssa", title: "SSA", subtitle: "Subsetor do Almoxarifado" },
|
|
21
|
+
],
|
|
22
|
+
},
|
|
23
|
+
{ id: "sfin", title: "SFIN", subtitle: "Secretaria de Finanças" },
|
|
24
|
+
],
|
|
25
|
+
},
|
|
26
|
+
];
|
|
27
|
+
|
|
28
|
+
const item = (id: string) => document.querySelector(`[data-node-id="${id}"]`) as HTMLElement;
|
|
29
|
+
const esquerda = (id: string) => parseFloat(item(id).style.left);
|
|
30
|
+
|
|
31
|
+
describe("OrgChart", () => {
|
|
32
|
+
it("é uma tree nomeada, com um treeitem por nó visível e níveis ARIA", () => {
|
|
33
|
+
render(<OrgChart nodes={ARVORE} ariaLabel="Setores" />);
|
|
34
|
+
expect(screen.getByRole("tree", { name: "Setores" })).toBeInTheDocument();
|
|
35
|
+
expect(screen.getAllByRole("treeitem")).toHaveLength(6);
|
|
36
|
+
expect(item("copirn")).toHaveAttribute("aria-level", "1");
|
|
37
|
+
expect(item("al")).toHaveAttribute("aria-level", "3");
|
|
38
|
+
expect(item("sadm")).toHaveAttribute("aria-posinset", "2");
|
|
39
|
+
expect(item("sadm")).toHaveAttribute("aria-setsize", "3");
|
|
40
|
+
expect(item("sadm")).toHaveAttribute("aria-expanded", "true");
|
|
41
|
+
expect(item("aj")).not.toHaveAttribute("aria-expanded");
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
it("o nome padrão é Organograma; título e subtítulo aparecem", () => {
|
|
45
|
+
render(<OrgChart nodes={ARVORE} />);
|
|
46
|
+
expect(screen.getByRole("tree", { name: "Organograma" })).toBeInTheDocument();
|
|
47
|
+
expect(within(item("aj")).getByText("AJ")).toBeInTheDocument();
|
|
48
|
+
expect(within(item("aj")).getByText("Assessoria Jurídica")).toBeInTheDocument();
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
it("o pai se centra sobre os filhos e os irmãos andam lado a lado", () => {
|
|
52
|
+
render(<OrgChart nodes={ARVORE} nodeWidth={100} gapX={20} />);
|
|
53
|
+
expect(esquerda("aj")).toBe(0);
|
|
54
|
+
expect(esquerda("al")).toBe(120);
|
|
55
|
+
expect(esquerda("ssa")).toBe(240);
|
|
56
|
+
expect(esquerda("sadm")).toBe(180);
|
|
57
|
+
expect(esquerda("sfin")).toBe(360);
|
|
58
|
+
expect(esquerda("copirn")).toBe((0 + 360) / 2);
|
|
59
|
+
expect(parseFloat(item("sadm").style.top)).toBeGreaterThan(parseFloat(item("copirn").style.top));
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
it("desenha um conector por pai expandido", () => {
|
|
63
|
+
const { container } = render(<OrgChart nodes={ARVORE} />);
|
|
64
|
+
expect(container.querySelectorAll(".umds-org-chart__line")).toHaveLength(2);
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
it("a raiz é cheia e o nó marcado leva aria-selected", () => {
|
|
68
|
+
render(<OrgChart nodes={ARVORE} selectedId="aj" />);
|
|
69
|
+
expect(item("copirn")).toHaveClass("umds-org-chart__node--root");
|
|
70
|
+
expect(item("aj")).toHaveAttribute("aria-selected", "true");
|
|
71
|
+
expect(item("sfin")).not.toHaveAttribute("aria-selected");
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
it("recolher esconde os filhos e avisa; expandir volta", async () => {
|
|
75
|
+
const usuario = userEvent.setup();
|
|
76
|
+
const aoMudar = vi.fn();
|
|
77
|
+
render(<OrgChart nodes={ARVORE} onCollapsedChange={aoMudar} />);
|
|
78
|
+
item("sadm").focus();
|
|
79
|
+
await usuario.keyboard(" ");
|
|
80
|
+
expect(aoMudar).toHaveBeenLastCalledWith(["sadm"]);
|
|
81
|
+
expect(screen.getAllByRole("treeitem")).toHaveLength(4);
|
|
82
|
+
expect(item("sadm")).toHaveAttribute("aria-expanded", "false");
|
|
83
|
+
await usuario.keyboard(" ");
|
|
84
|
+
expect(aoMudar).toHaveBeenLastCalledWith([]);
|
|
85
|
+
expect(screen.getAllByRole("treeitem")).toHaveLength(6);
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
it("o botão de expandir do mouse faz o mesmo e não aciona o nó", async () => {
|
|
89
|
+
const usuario = userEvent.setup();
|
|
90
|
+
const aoClicar = vi.fn();
|
|
91
|
+
const { container } = render(<OrgChart nodes={ARVORE} onNodeClick={aoClicar} />);
|
|
92
|
+
const botoes = container.querySelectorAll(".umds-org-chart__toggle");
|
|
93
|
+
expect(botoes).toHaveLength(2);
|
|
94
|
+
await usuario.click(botoes[1] as HTMLElement);
|
|
95
|
+
expect(screen.getAllByRole("treeitem")).toHaveLength(4);
|
|
96
|
+
expect(aoClicar).not.toHaveBeenCalled();
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
it("defaultCollapsedIds começa recolhido; collapsedIds controla", () => {
|
|
100
|
+
const { rerender } = render(<OrgChart nodes={ARVORE} defaultCollapsedIds={["sadm"]} />);
|
|
101
|
+
expect(screen.getAllByRole("treeitem")).toHaveLength(4);
|
|
102
|
+
rerender(<OrgChart nodes={ARVORE} collapsedIds={["copirn"]} />);
|
|
103
|
+
expect(screen.getAllByRole("treeitem")).toHaveLength(1);
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
it("clicar e Enter acionam o nó com o nó", async () => {
|
|
107
|
+
const usuario = userEvent.setup();
|
|
108
|
+
const aoClicar = vi.fn();
|
|
109
|
+
render(<OrgChart nodes={ARVORE} onNodeClick={aoClicar} />);
|
|
110
|
+
await usuario.click(item("aj"));
|
|
111
|
+
expect(aoClicar).toHaveBeenLastCalledWith(expect.objectContaining({ id: "aj" }));
|
|
112
|
+
item("sfin").focus();
|
|
113
|
+
await usuario.keyboard("{Enter}");
|
|
114
|
+
expect(aoClicar).toHaveBeenLastCalledWith(expect.objectContaining({ id: "sfin" }));
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
it("só um nó entra na ordem de Tab (o primeiro)", () => {
|
|
118
|
+
render(<OrgChart nodes={ARVORE} />);
|
|
119
|
+
const comTab = screen.getAllByRole("treeitem").filter((n) => n.getAttribute("tabindex") === "0");
|
|
120
|
+
expect(comTab).toHaveLength(1);
|
|
121
|
+
expect(comTab[0]).toHaveAttribute("data-node-id", "copirn");
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
it("setas: baixo desce ao primeiro filho, cima sobe ao pai, lados andam entre irmãos, Home e End", async () => {
|
|
125
|
+
const usuario = userEvent.setup();
|
|
126
|
+
render(<OrgChart nodes={ARVORE} />);
|
|
127
|
+
item("copirn").focus();
|
|
128
|
+
await usuario.keyboard("{ArrowDown}");
|
|
129
|
+
expect(item("aj")).toHaveFocus();
|
|
130
|
+
await usuario.keyboard("{ArrowRight}");
|
|
131
|
+
expect(item("sadm")).toHaveFocus();
|
|
132
|
+
await usuario.keyboard("{ArrowDown}");
|
|
133
|
+
expect(item("al")).toHaveFocus();
|
|
134
|
+
await usuario.keyboard("{ArrowRight}");
|
|
135
|
+
expect(item("ssa")).toHaveFocus();
|
|
136
|
+
await usuario.keyboard("{Home}");
|
|
137
|
+
expect(item("al")).toHaveFocus();
|
|
138
|
+
await usuario.keyboard("{ArrowUp}");
|
|
139
|
+
expect(item("sadm")).toHaveFocus();
|
|
140
|
+
await usuario.keyboard("{End}");
|
|
141
|
+
expect(item("sfin")).toHaveFocus();
|
|
142
|
+
await usuario.keyboard("{ArrowLeft}{ArrowLeft}");
|
|
143
|
+
expect(item("aj")).toHaveFocus();
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
it("baixo num nó recolhido abre; o foco desce no seguinte", async () => {
|
|
147
|
+
const usuario = userEvent.setup();
|
|
148
|
+
render(<OrgChart nodes={ARVORE} defaultCollapsedIds={["sadm"]} />);
|
|
149
|
+
item("sadm").focus();
|
|
150
|
+
await usuario.keyboard("{ArrowDown}");
|
|
151
|
+
expect(item("sadm")).toHaveAttribute("aria-expanded", "true");
|
|
152
|
+
await usuario.keyboard("{ArrowDown}");
|
|
153
|
+
expect(item("al")).toHaveFocus();
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
it("renderNode troca o conteúdo do nó", () => {
|
|
157
|
+
render(<OrgChart nodes={ARVORE} renderNode={(no, meta) => <b data-testid={"c-" + no.id}>{no.title + ":" + meta.level}</b>} />);
|
|
158
|
+
expect(screen.getByTestId("c-ssa")).toHaveTextContent("SSA:2");
|
|
159
|
+
expect(item("ssa").querySelector(".umds-org-chart__title")).toBeNull();
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
it("textos do botão por prop; sem nós, não desenha a árvore", () => {
|
|
163
|
+
const { container, rerender } = render(<OrgChart nodes={ARVORE} expandLabel="Expand" collapseLabel="Collapse" />);
|
|
164
|
+
expect(container.querySelector(".umds-org-chart__toggle")).toHaveAttribute("title", "Collapse");
|
|
165
|
+
rerender(<OrgChart nodes={[]} />);
|
|
166
|
+
expect(screen.queryByRole("tree")).toBeNull();
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
it("controlado por pai", () => {
|
|
170
|
+
function Pai() {
|
|
171
|
+
const [fechados, setFechados] = useState<string[]>([]);
|
|
172
|
+
return (
|
|
173
|
+
<>
|
|
174
|
+
<OrgChart nodes={ARVORE} collapsedIds={fechados} onCollapsedChange={setFechados} />
|
|
175
|
+
<button onClick={() => setFechados(["sadm"])}>fechar</button>
|
|
176
|
+
</>
|
|
177
|
+
);
|
|
178
|
+
}
|
|
179
|
+
render(<Pai />);
|
|
180
|
+
fireEvent.click(screen.getByText("fechar"));
|
|
181
|
+
expect(screen.getAllByRole("treeitem")).toHaveLength(4);
|
|
182
|
+
});
|
|
183
|
+
});
|