@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,39 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { describe, expect, it } from "vitest";
|
|
3
|
+
import { render, screen } from "@testing-library/react";
|
|
4
|
+
import userEvent from "@testing-library/user-event";
|
|
5
|
+
import SegmentedControl from "../components/SegmentedControl/SegmentedControl";
|
|
6
|
+
const FILA = [
|
|
7
|
+
{ label: "Todas", value: "todas", count: 31 },
|
|
8
|
+
{ label: "Minhas", value: "minhas", count: 0 },
|
|
9
|
+
{ label: "Arquivadas", value: "arquivadas" },
|
|
10
|
+
{ label: "Vazias", value: "vazias", count: "" },
|
|
11
|
+
];
|
|
12
|
+
describe("SegmentedControl · count", () => {
|
|
13
|
+
it("desenha a pílula do contador depois do texto; 0 aparece, vazio e ausente não", () => {
|
|
14
|
+
const { container } = render(_jsx(SegmentedControl, { label: "Fila", options: FILA }));
|
|
15
|
+
const itens = [...container.querySelectorAll(".umds-segmented__item")];
|
|
16
|
+
expect(itens[0].querySelector(".umds-segmented__count")).toHaveTextContent("31");
|
|
17
|
+
expect(itens[1].querySelector(".umds-segmented__count")).toHaveTextContent("0");
|
|
18
|
+
expect(itens[2].querySelector(".umds-segmented__count")).toBeNull();
|
|
19
|
+
expect(itens[3].querySelector(".umds-segmented__count")).toBeNull();
|
|
20
|
+
const conteudo = itens[0].querySelector(".umds-segmented__conteudo");
|
|
21
|
+
expect(conteudo.lastElementChild).toHaveClass("umds-segmented__count");
|
|
22
|
+
});
|
|
23
|
+
it("o contador entra no nome acessível do segmento (o texto visível manda)", () => {
|
|
24
|
+
render(_jsx(SegmentedControl, { label: "Fila", id: "fila", options: FILA }));
|
|
25
|
+
expect(screen.getByRole("radio", { name: /Todas\s*31/ })).toBeInTheDocument();
|
|
26
|
+
});
|
|
27
|
+
it("o contador acompanha a escolha e a escolha segue funcionando", async () => {
|
|
28
|
+
const usuario = userEvent.setup();
|
|
29
|
+
const { container } = render(_jsx(SegmentedControl, { label: "Fila", options: FILA, defaultValue: "todas" }));
|
|
30
|
+
expect(screen.getByRole("radio", { name: /Todas/ })).toBeChecked();
|
|
31
|
+
await usuario.click(screen.getByText("Minhas"));
|
|
32
|
+
expect(screen.getByRole("radio", { name: /Minhas/ })).toBeChecked();
|
|
33
|
+
expect(container.querySelectorAll(".umds-segmented__count")).toHaveLength(2);
|
|
34
|
+
});
|
|
35
|
+
it("sem count em nenhum segmento, nada muda", () => {
|
|
36
|
+
const { container } = render(_jsx(SegmentedControl, { label: "x", options: [{ label: "25", value: "25" }] }));
|
|
37
|
+
expect(container.querySelector(".umds-segmented__count")).toBeNull();
|
|
38
|
+
});
|
|
39
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { afterEach, describe, expect, it, vi } from "vitest";
|
|
3
|
+
import { fireEvent, render, screen, waitFor } from "@testing-library/react";
|
|
4
|
+
import { faFilter } from "@fortawesome/free-solid-svg-icons";
|
|
5
|
+
import Select from "../components/Select/Select";
|
|
6
|
+
const OPCOES = [
|
|
7
|
+
{ label: "Urgente", value: "urgente" },
|
|
8
|
+
{ label: "Revisão", value: "revisao" },
|
|
9
|
+
];
|
|
10
|
+
afterEach(() => vi.restoreAllMocks());
|
|
11
|
+
describe("Select · open e onOpenChange", () => {
|
|
12
|
+
it("open controlado mostra a lista sem clique; fechado, não mostra", () => {
|
|
13
|
+
const { rerender } = render(_jsx(Select, { ariaLabel: "x", options: OPCOES, open: false }));
|
|
14
|
+
expect(screen.queryByRole("listbox")).toBeNull();
|
|
15
|
+
rerender(_jsx(Select, { ariaLabel: "x", options: OPCOES, open: true }));
|
|
16
|
+
expect(screen.getByRole("listbox")).toBeInTheDocument();
|
|
17
|
+
expect(screen.getByRole("combobox")).toHaveAttribute("aria-expanded", "true");
|
|
18
|
+
});
|
|
19
|
+
it("controlado: o clique só avisa; quem abre é o pai", () => {
|
|
20
|
+
const aoAbrir = vi.fn();
|
|
21
|
+
const { rerender } = render(_jsx(Select, { ariaLabel: "x", options: OPCOES, open: false, onOpenChange: aoAbrir }));
|
|
22
|
+
fireEvent.click(screen.getByRole("combobox"));
|
|
23
|
+
expect(aoAbrir).toHaveBeenCalledWith(true);
|
|
24
|
+
expect(screen.queryByRole("listbox")).toBeNull();
|
|
25
|
+
rerender(_jsx(Select, { ariaLabel: "x", options: OPCOES, open: true, onOpenChange: aoAbrir }));
|
|
26
|
+
expect(screen.getByRole("listbox")).toBeInTheDocument();
|
|
27
|
+
});
|
|
28
|
+
it("controlado aberto: escolher uma opção, Esc e clique fora pedem para fechar", () => {
|
|
29
|
+
const aoAbrir = vi.fn();
|
|
30
|
+
const { rerender } = render(_jsx(Select, { ariaLabel: "x", options: OPCOES, open: true, onOpenChange: aoAbrir }));
|
|
31
|
+
fireEvent.click(screen.getAllByRole("option")[0]);
|
|
32
|
+
expect(aoAbrir).toHaveBeenLastCalledWith(false);
|
|
33
|
+
aoAbrir.mockClear();
|
|
34
|
+
rerender(_jsx(Select, { ariaLabel: "x", options: OPCOES, open: true, onOpenChange: aoAbrir }));
|
|
35
|
+
fireEvent.keyDown(screen.getByRole("combobox"), { key: "Escape" });
|
|
36
|
+
expect(aoAbrir).toHaveBeenLastCalledWith(false);
|
|
37
|
+
aoAbrir.mockClear();
|
|
38
|
+
fireEvent.mouseDown(document.body);
|
|
39
|
+
expect(aoAbrir).toHaveBeenCalledWith(false);
|
|
40
|
+
});
|
|
41
|
+
it("o clique fora não avisa quando a lista está fechada", () => {
|
|
42
|
+
const aoAbrir = vi.fn();
|
|
43
|
+
render(_jsx(Select, { ariaLabel: "x", options: OPCOES, open: false, onOpenChange: aoAbrir }));
|
|
44
|
+
fireEvent.mouseDown(document.body);
|
|
45
|
+
expect(aoAbrir).not.toHaveBeenCalled();
|
|
46
|
+
});
|
|
47
|
+
it("clique fora vê o open de agora, não o do primeiro render", () => {
|
|
48
|
+
const aoAbrir = vi.fn();
|
|
49
|
+
const { rerender } = render(_jsx(Select, { ariaLabel: "x", options: OPCOES, open: false, onOpenChange: aoAbrir }));
|
|
50
|
+
rerender(_jsx(Select, { ariaLabel: "x", options: OPCOES, open: true, onOpenChange: aoAbrir }));
|
|
51
|
+
fireEvent.mouseDown(document.body);
|
|
52
|
+
expect(aoAbrir).toHaveBeenCalledWith(false);
|
|
53
|
+
});
|
|
54
|
+
it("sem open, o Select abre e fecha sozinho e também avisa", () => {
|
|
55
|
+
const aoAbrir = vi.fn();
|
|
56
|
+
render(_jsx(Select, { ariaLabel: "x", options: OPCOES, onOpenChange: aoAbrir }));
|
|
57
|
+
fireEvent.click(screen.getByRole("combobox"));
|
|
58
|
+
expect(screen.getByRole("listbox")).toBeInTheDocument();
|
|
59
|
+
expect(aoAbrir).toHaveBeenLastCalledWith(true);
|
|
60
|
+
fireEvent.click(screen.getAllByRole("option")[1]);
|
|
61
|
+
expect(screen.queryByRole("listbox")).toBeNull();
|
|
62
|
+
expect(aoAbrir).toHaveBeenLastCalledWith(false);
|
|
63
|
+
});
|
|
64
|
+
});
|
|
65
|
+
describe("Select · gatilho com ícone, amostra e aria-required", () => {
|
|
66
|
+
it("triggerIcon e triggerSwatch aparecem no gatilho, decorativos", () => {
|
|
67
|
+
const { container } = render(_jsx(Select, { ariaLabel: "x", options: OPCOES, triggerIcon: faFilter, triggerSwatch: "var(--umds-semantic-color-primary-pure)" }));
|
|
68
|
+
const icone = container.querySelector(".umds-select__trigger-icon");
|
|
69
|
+
expect(icone).toHaveAttribute("aria-hidden", "true");
|
|
70
|
+
expect(icone.querySelector("svg")).toHaveAttribute("data-icon", "filter");
|
|
71
|
+
const amostra = container.querySelector(".umds-select__swatch");
|
|
72
|
+
expect(amostra).toHaveAttribute("aria-hidden", "true");
|
|
73
|
+
expect(amostra.style.background).toContain("--umds-semantic-color-primary-pure");
|
|
74
|
+
expect(container.querySelector(".umds-select--has-trigger-icon")).not.toBeNull();
|
|
75
|
+
});
|
|
76
|
+
it("sem as props, não há ícone nem amostra", () => {
|
|
77
|
+
const { container } = render(_jsx(Select, { ariaLabel: "x", options: OPCOES }));
|
|
78
|
+
expect(container.querySelector(".umds-select__trigger-icon")).toBeNull();
|
|
79
|
+
expect(container.querySelector(".umds-select__swatch")).toBeNull();
|
|
80
|
+
});
|
|
81
|
+
it("required repassa aria-required ao combobox", () => {
|
|
82
|
+
const { rerender } = render(_jsx(Select, { ariaLabel: "x", options: OPCOES, required: true }));
|
|
83
|
+
expect(screen.getByRole("combobox")).toHaveAttribute("aria-required", "true");
|
|
84
|
+
rerender(_jsx(Select, { ariaLabel: "x", options: OPCOES }));
|
|
85
|
+
expect(screen.getByRole("combobox")).not.toHaveAttribute("aria-required");
|
|
86
|
+
});
|
|
87
|
+
});
|
|
88
|
+
describe("Select · variantes de filtro", () => {
|
|
89
|
+
it("search e combo escrevem a classe do filtro e a própria", () => {
|
|
90
|
+
const { container, rerender } = render(_jsx(Select, { ariaLabel: "x", options: OPCOES, variant: "search" }));
|
|
91
|
+
expect(container.querySelector(".umds-select--filter.umds-select--filter-search")).not.toBeNull();
|
|
92
|
+
rerender(_jsx(Select, { ariaLabel: "x", options: OPCOES, variant: "combo" }));
|
|
93
|
+
expect(container.querySelector(".umds-select--filter.umds-select--filter-combo")).not.toBeNull();
|
|
94
|
+
expect(container.querySelector(".umds-select--filter-search")).toBeNull();
|
|
95
|
+
});
|
|
96
|
+
it("search foca a busca ao abrir, como o filter", async () => {
|
|
97
|
+
render(_jsx(Select, { ariaLabel: "x", options: OPCOES, variant: "search", searchable: true }));
|
|
98
|
+
fireEvent.click(screen.getByRole("combobox"));
|
|
99
|
+
await waitFor(() => expect(document.activeElement).toBe(screen.getByRole("textbox")));
|
|
100
|
+
});
|
|
101
|
+
});
|
|
102
|
+
describe("Select · por cima do diálogo", () => {
|
|
103
|
+
it("dentro de role=dialog a lista vira fixed, ancorada no gatilho", async () => {
|
|
104
|
+
const { container } = render(_jsx("div", { role: "dialog", "aria-label": "Filtros", style: { overflow: "clip" }, children: _jsx(Select, { ariaLabel: "x", options: OPCOES }) }));
|
|
105
|
+
fireEvent.click(screen.getByRole("combobox"));
|
|
106
|
+
const lista = container.querySelector(".umds-select__dropdown");
|
|
107
|
+
expect(container.querySelector(".umds-select--floating")).not.toBeNull();
|
|
108
|
+
expect(lista.style.position).toBe("fixed");
|
|
109
|
+
await waitFor(() => expect(lista.style.visibility).toBe("visible"));
|
|
110
|
+
});
|
|
111
|
+
it("fora de diálogo a lista continua posicionada pelo CSS (sem fixed)", () => {
|
|
112
|
+
const { container } = render(_jsx(Select, { ariaLabel: "x", options: OPCOES }));
|
|
113
|
+
fireEvent.click(screen.getByRole("combobox"));
|
|
114
|
+
const lista = container.querySelector(".umds-select__dropdown");
|
|
115
|
+
expect(container.querySelector(".umds-select--floating")).toBeNull();
|
|
116
|
+
expect(lista.style.position).toBe("");
|
|
117
|
+
});
|
|
118
|
+
it("aria-modal também conta como diálogo", () => {
|
|
119
|
+
const { container } = render(_jsx("div", { "aria-modal": "true", children: _jsx(Select, { ariaLabel: "x", options: OPCOES }) }));
|
|
120
|
+
fireEvent.click(screen.getByRole("combobox"));
|
|
121
|
+
expect(container.querySelector(".umds-select--floating")).not.toBeNull();
|
|
122
|
+
});
|
|
123
|
+
});
|
|
124
|
+
describe("Select · placement auto mede o ancestral que rola", () => {
|
|
125
|
+
it("abre para cima e limita a altura da lista ao espaço do ancestral", () => {
|
|
126
|
+
vi.spyOn(HTMLElement.prototype, "getBoundingClientRect").mockImplementation(function () {
|
|
127
|
+
const rolante = this.getAttribute("data-rolante") !== null;
|
|
128
|
+
const [topo, base] = rolante ? [100, 300] : [200, 244];
|
|
129
|
+
return { top: topo, bottom: base, left: 0, right: 0, width: 0, height: base - topo, x: 0, y: topo, toJSON() { } };
|
|
130
|
+
});
|
|
131
|
+
Object.defineProperty(window, "innerHeight", { value: 900, configurable: true });
|
|
132
|
+
const { container } = render(_jsx("div", { "data-rolante": true, style: { overflowY: "auto" }, children: _jsx(Select, { ariaLabel: "x", options: OPCOES, placement: "auto" }) }));
|
|
133
|
+
fireEvent.click(screen.getByRole("combobox"));
|
|
134
|
+
expect(container.querySelector(".umds-select--placement-top")).not.toBeNull();
|
|
135
|
+
expect(container.querySelector(".umds-select__dropdown").style.maxHeight).toBe("96px");
|
|
136
|
+
});
|
|
137
|
+
it("sem ancestral que corta, só a janela conta e a lista não ganha teto", () => {
|
|
138
|
+
vi.spyOn(HTMLElement.prototype, "getBoundingClientRect").mockImplementation(() => ({ top: 20, bottom: 64, left: 0, right: 0, width: 0, height: 44, x: 0, y: 20, toJSON() { } }));
|
|
139
|
+
Object.defineProperty(window, "innerHeight", { value: 900, configurable: true });
|
|
140
|
+
const { container } = render(_jsx(Select, { ariaLabel: "x", options: OPCOES, placement: "auto" }));
|
|
141
|
+
fireEvent.click(screen.getByRole("combobox"));
|
|
142
|
+
expect(container.querySelector(".umds-select--placement-top")).toBeNull();
|
|
143
|
+
expect(container.querySelector(".umds-select__dropdown").style.maxHeight).toBe("");
|
|
144
|
+
});
|
|
145
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { describe, expect, it } from "vitest";
|
|
3
|
+
import { fireEvent, render, screen } from "@testing-library/react";
|
|
4
|
+
import Select from "../components/Select/Select";
|
|
5
|
+
const MARCADORES = [
|
|
6
|
+
{ label: "Urgente", value: "urgente", color: "var(--umds-semantic-color-feedback-negative-pure)" },
|
|
7
|
+
{ label: "Revisão", value: "revisao", color: "var(--umds-semantic-color-primary-pure)" },
|
|
8
|
+
{ label: "Sem marcador", value: "nenhum" },
|
|
9
|
+
];
|
|
10
|
+
describe("Select filtro · tamanho e fundo", () => {
|
|
11
|
+
it("as variantes de filtro nascem no tamanho sm; size explícito manda; o padrão segue md", () => {
|
|
12
|
+
const { container, rerender } = render(_jsx(Select, { ariaLabel: "x", options: MARCADORES, variant: "filter" }));
|
|
13
|
+
const raiz = () => container.firstElementChild;
|
|
14
|
+
expect(raiz()).toHaveClass("umds-select--sm");
|
|
15
|
+
rerender(_jsx(Select, { ariaLabel: "x", options: MARCADORES, variant: "search" }));
|
|
16
|
+
expect(raiz()).toHaveClass("umds-select--sm");
|
|
17
|
+
rerender(_jsx(Select, { ariaLabel: "x", options: MARCADORES, variant: "combo" }));
|
|
18
|
+
expect(raiz()).toHaveClass("umds-select--sm");
|
|
19
|
+
rerender(_jsx(Select, { ariaLabel: "x", options: MARCADORES, variant: "filter", size: "md" }));
|
|
20
|
+
expect(raiz()).toHaveClass("umds-select--md");
|
|
21
|
+
rerender(_jsx(Select, { ariaLabel: "x", options: MARCADORES }));
|
|
22
|
+
expect(raiz()).toHaveClass("umds-select--md");
|
|
23
|
+
expect(raiz()).not.toHaveClass("umds-select--sm");
|
|
24
|
+
});
|
|
25
|
+
it("o azul-claro do gatilho só vem com valor escolhido (--has-value); sem valor, não", () => {
|
|
26
|
+
const { container, rerender } = render(_jsx(Select, { ariaLabel: "x", options: MARCADORES, variant: "filter", placeholder: "Marcadores" }));
|
|
27
|
+
const raiz = () => container.firstElementChild;
|
|
28
|
+
expect(raiz()).not.toHaveClass("umds-select--has-value");
|
|
29
|
+
rerender(_jsx(Select, { ariaLabel: "x", options: MARCADORES, variant: "filter", placeholder: "Marcadores", value: "urgente" }));
|
|
30
|
+
expect(raiz()).toHaveClass("umds-select--has-value");
|
|
31
|
+
rerender(_jsx(Select, { ariaLabel: "x", options: MARCADORES, placeholder: "Marcadores", value: "urgente" }));
|
|
32
|
+
expect(raiz()).not.toHaveClass("umds-select--has-value");
|
|
33
|
+
});
|
|
34
|
+
it("o valor vazio do emptyOptionLabel volta ao estado sem valor", () => {
|
|
35
|
+
const { container } = render(_jsx(Select, { ariaLabel: "x", options: MARCADORES, variant: "filter", placeholder: "Marcadores", emptyOptionLabel: "Todos", value: "" }));
|
|
36
|
+
expect(container.firstElementChild).not.toHaveClass("umds-select--has-value");
|
|
37
|
+
});
|
|
38
|
+
});
|
|
39
|
+
describe("Select · cor por opção", () => {
|
|
40
|
+
it("a lista mostra uma amostra por opção com color; sem color, não", () => {
|
|
41
|
+
const { container } = render(_jsx(Select, { ariaLabel: "x", options: MARCADORES, variant: "filter" }));
|
|
42
|
+
fireEvent.click(screen.getByRole("combobox"));
|
|
43
|
+
const opcoes = [...container.querySelectorAll('[role="option"]')];
|
|
44
|
+
expect(opcoes[0].querySelector(".umds-select__swatch")).toHaveAttribute("aria-hidden", "true");
|
|
45
|
+
expect(opcoes[0].querySelector(".umds-select__swatch").style.background).toContain("--umds-semantic-color-feedback-negative-pure");
|
|
46
|
+
expect(opcoes[1].querySelector(".umds-select__swatch")).not.toBeNull();
|
|
47
|
+
expect(opcoes[2].querySelector(".umds-select__swatch")).toBeNull();
|
|
48
|
+
});
|
|
49
|
+
it("o gatilho ganha a cor da opção escolhida (seleção única)", () => {
|
|
50
|
+
const { container } = render(_jsx(Select, { ariaLabel: "x", options: MARCADORES, variant: "filter", placeholder: "Marcadores", value: "revisao" }));
|
|
51
|
+
const amostra = container.querySelector(".umds-select__trigger .umds-select__swatch");
|
|
52
|
+
expect(amostra.style.background).toContain("--umds-semantic-color-primary-pure");
|
|
53
|
+
});
|
|
54
|
+
it("opção escolhida sem color e estado sem valor: o gatilho não tem amostra", () => {
|
|
55
|
+
const { container, rerender } = render(_jsx(Select, { ariaLabel: "x", options: MARCADORES, placeholder: "Marcadores", value: "nenhum" }));
|
|
56
|
+
expect(container.querySelector(".umds-select__trigger .umds-select__swatch")).toBeNull();
|
|
57
|
+
rerender(_jsx(Select, { ariaLabel: "x", options: MARCADORES, placeholder: "Marcadores" }));
|
|
58
|
+
expect(container.querySelector(".umds-select__trigger .umds-select__swatch")).toBeNull();
|
|
59
|
+
});
|
|
60
|
+
it("triggerSwatch explícito manda sobre a cor da opção", () => {
|
|
61
|
+
const { container } = render(_jsx(Select, { ariaLabel: "x", options: MARCADORES, value: "urgente", triggerSwatch: "var(--umds-semantic-color-feedback-positive-pure)" }));
|
|
62
|
+
const amostras = container.querySelectorAll(".umds-select__trigger .umds-select__swatch");
|
|
63
|
+
expect(amostras).toHaveLength(1);
|
|
64
|
+
expect(amostras[0].style.background).toContain("--umds-semantic-color-feedback-positive-pure");
|
|
65
|
+
});
|
|
66
|
+
it("na seleção múltipla o gatilho não pinta amostra (são várias), mas a lista mostra as cores", () => {
|
|
67
|
+
const { container } = render(_jsx(Select, { ariaLabel: "x", options: MARCADORES, multiple: true, value: ["urgente", "revisao"] }));
|
|
68
|
+
expect(container.querySelector(".umds-select__trigger .umds-select__swatch")).toBeNull();
|
|
69
|
+
fireEvent.click(screen.getByRole("combobox"));
|
|
70
|
+
expect(container.querySelectorAll('[role="option"] .umds-select__swatch')).toHaveLength(2);
|
|
71
|
+
});
|
|
72
|
+
it("a cor não vira texto nem entra no nome acessível da opção", () => {
|
|
73
|
+
render(_jsx(Select, { ariaLabel: "x", options: MARCADORES }));
|
|
74
|
+
fireEvent.click(screen.getByRole("combobox"));
|
|
75
|
+
expect(screen.getByRole("option", { name: "Urgente" })).toBeInTheDocument();
|
|
76
|
+
});
|
|
77
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { afterEach, describe, expect, it, vi } from "vitest";
|
|
3
|
+
import { fireEvent, render, screen } from "@testing-library/react";
|
|
4
|
+
import Select from "../components/Select/Select";
|
|
5
|
+
const OPCOES = [
|
|
6
|
+
{ label: "Urgente", value: "urgente" },
|
|
7
|
+
{ label: "Revisão", value: "revisao" },
|
|
8
|
+
];
|
|
9
|
+
afterEach(() => vi.restoreAllMocks());
|
|
10
|
+
/** jsdom não tem layout: o gatilho "mede" o que o teste mandar. */
|
|
11
|
+
function medirGatilho(topo, base, alturaDaTela) {
|
|
12
|
+
vi.spyOn(HTMLElement.prototype, "getBoundingClientRect").mockImplementation(() => ({ top: topo, bottom: base, left: 0, right: 0, width: 0, height: base - topo, x: 0, y: topo, toJSON() { } }));
|
|
13
|
+
Object.defineProperty(window, "innerHeight", { value: alturaDaTela, configurable: true });
|
|
14
|
+
}
|
|
15
|
+
describe("Select · placement", () => {
|
|
16
|
+
it("padrão abre para baixo", () => {
|
|
17
|
+
const { container } = render(_jsx(Select, { ariaLabel: "x", options: OPCOES }));
|
|
18
|
+
fireEvent.click(screen.getByRole("combobox"));
|
|
19
|
+
expect(container.querySelector(".umds-select--placement-top")).toBeNull();
|
|
20
|
+
});
|
|
21
|
+
it("top abre para cima", () => {
|
|
22
|
+
const { container } = render(_jsx(Select, { ariaLabel: "x", options: OPCOES, placement: "top" }));
|
|
23
|
+
fireEvent.click(screen.getByRole("combobox"));
|
|
24
|
+
expect(container.querySelector(".umds-select--placement-top")).not.toBeNull();
|
|
25
|
+
});
|
|
26
|
+
it("auto abre para cima quando falta espaço embaixo e há mais em cima", () => {
|
|
27
|
+
medirGatilho(500, 544, 600);
|
|
28
|
+
const { container } = render(_jsx(Select, { ariaLabel: "x", options: OPCOES, placement: "auto" }));
|
|
29
|
+
fireEvent.click(screen.getByRole("combobox"));
|
|
30
|
+
expect(container.querySelector(".umds-select--placement-top")).not.toBeNull();
|
|
31
|
+
});
|
|
32
|
+
it("auto abre para baixo quando cabe", () => {
|
|
33
|
+
medirGatilho(20, 64, 900);
|
|
34
|
+
const { container } = render(_jsx(Select, { ariaLabel: "x", options: OPCOES, placement: "auto" }));
|
|
35
|
+
fireEvent.click(screen.getByRole("combobox"));
|
|
36
|
+
expect(container.querySelector(".umds-select--placement-top")).toBeNull();
|
|
37
|
+
});
|
|
38
|
+
it("auto abre para baixo quando falta espaço dos dois lados e embaixo é maior", () => {
|
|
39
|
+
medirGatilho(60, 104, 220);
|
|
40
|
+
const { container } = render(_jsx(Select, { ariaLabel: "x", options: OPCOES, placement: "auto" }));
|
|
41
|
+
fireEvent.click(screen.getByRole("combobox"));
|
|
42
|
+
expect(container.querySelector(".umds-select--placement-top")).toBeNull();
|
|
43
|
+
});
|
|
44
|
+
});
|
|
45
|
+
describe("Select · variant filter", () => {
|
|
46
|
+
it("escreve a classe do filtro; sem variant não escreve", () => {
|
|
47
|
+
const { container, rerender } = render(_jsx(Select, { ariaLabel: "x", options: OPCOES, variant: "filter" }));
|
|
48
|
+
expect(container.querySelector(".umds-select--filter")).not.toBeNull();
|
|
49
|
+
rerender(_jsx(Select, { ariaLabel: "x", options: OPCOES }));
|
|
50
|
+
expect(container.querySelector(".umds-select--filter")).toBeNull();
|
|
51
|
+
});
|
|
52
|
+
it("emptyOptionLabel vem no topo, marcada sem seleção; escolher chama onChange com vazio e volta ao placeholder", () => {
|
|
53
|
+
const aoMudar = vi.fn();
|
|
54
|
+
const { rerender } = render(_jsx(Select, { ariaLabel: "Marcadores", placeholder: "Marcadores", options: OPCOES, emptyOptionLabel: "Todos os marcadores", onChange: aoMudar }));
|
|
55
|
+
fireEvent.click(screen.getByRole("combobox"));
|
|
56
|
+
const opcoes = screen.getAllByRole("option");
|
|
57
|
+
expect(opcoes[0]).toHaveTextContent("Todos os marcadores");
|
|
58
|
+
expect(opcoes[0]).toHaveAttribute("aria-selected", "true");
|
|
59
|
+
fireEvent.click(opcoes[1]);
|
|
60
|
+
expect(aoMudar).toHaveBeenLastCalledWith("urgente");
|
|
61
|
+
rerender(_jsx(Select, { ariaLabel: "Marcadores", placeholder: "Marcadores", options: OPCOES, emptyOptionLabel: "Todos os marcadores", value: "urgente", onChange: aoMudar }));
|
|
62
|
+
expect(screen.getByRole("combobox")).toHaveTextContent("Urgente");
|
|
63
|
+
fireEvent.click(screen.getByRole("combobox"));
|
|
64
|
+
fireEvent.click(screen.getAllByRole("option")[0]);
|
|
65
|
+
expect(aoMudar).toHaveBeenLastCalledWith("");
|
|
66
|
+
rerender(_jsx(Select, { ariaLabel: "Marcadores", placeholder: "Marcadores", options: OPCOES, emptyOptionLabel: "Todos os marcadores", value: "", onChange: aoMudar }));
|
|
67
|
+
expect(screen.getByRole("combobox")).toHaveTextContent("Marcadores");
|
|
68
|
+
});
|
|
69
|
+
it("sem emptyOptionLabel não há opção extra", () => {
|
|
70
|
+
render(_jsx(Select, { ariaLabel: "x", options: OPCOES }));
|
|
71
|
+
fireEvent.click(screen.getByRole("combobox"));
|
|
72
|
+
expect(screen.getAllByRole("option")).toHaveLength(2);
|
|
73
|
+
});
|
|
74
|
+
it("footer aparece dentro da lista aberta, e não fecha ao clicar nele", () => {
|
|
75
|
+
render(_jsx(Select, { ariaLabel: "x", options: OPCOES, footer: _jsx("button", { children: "Gerenciar marcadores" }) }));
|
|
76
|
+
expect(screen.queryByText("Gerenciar marcadores")).toBeNull();
|
|
77
|
+
fireEvent.click(screen.getByRole("combobox"));
|
|
78
|
+
const acao = screen.getByText("Gerenciar marcadores");
|
|
79
|
+
expect(acao.closest(".umds-select__footer")).not.toBeNull();
|
|
80
|
+
fireEvent.mouseDown(acao);
|
|
81
|
+
expect(screen.getByRole("combobox")).toHaveAttribute("aria-expanded", "true");
|
|
82
|
+
});
|
|
83
|
+
it("sem footer não há rodapé", () => {
|
|
84
|
+
const { container } = render(_jsx(Select, { ariaLabel: "x", options: OPCOES }));
|
|
85
|
+
fireEvent.click(screen.getByRole("combobox"));
|
|
86
|
+
expect(container.querySelector(".umds-select__footer")).toBeNull();
|
|
87
|
+
});
|
|
88
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { describe, expect, it, vi } from "vitest";
|
|
3
|
+
import { fireEvent, render, screen } from "@testing-library/react";
|
|
4
|
+
import Stack from "../components/Stack/Stack";
|
|
5
|
+
const TAGS = ["div", "span", "ul", "ol", "li", "section", "nav", "header", "footer", "form"];
|
|
6
|
+
describe("Stack", () => {
|
|
7
|
+
it("sem props continua um div vertical com gap xxxs", () => {
|
|
8
|
+
const { container } = render(_jsx(Stack, { children: "x" }));
|
|
9
|
+
const el = container.firstElementChild;
|
|
10
|
+
expect(el.tagName).toBe("DIV");
|
|
11
|
+
expect(el.className).toBe("umds-stack umds-stack--vertical umds-stack--gap-xxxs");
|
|
12
|
+
});
|
|
13
|
+
it("aceita gap none", () => {
|
|
14
|
+
const { container } = render(_jsx(Stack, { gap: "none", children: "x" }));
|
|
15
|
+
expect(container.firstElementChild).toHaveClass("umds-stack--gap-none");
|
|
16
|
+
});
|
|
17
|
+
it.each(TAGS)("as=%s renderiza o elemento certo", (tag) => {
|
|
18
|
+
const { container } = render(_jsx(Stack, { as: tag, children: "x" }));
|
|
19
|
+
expect(container.firstElementChild?.tagName.toLowerCase()).toBe(tag);
|
|
20
|
+
});
|
|
21
|
+
it("ul e ol mantêm a semântica de lista", () => {
|
|
22
|
+
const { container } = render(_jsx(Stack, { as: "ul", "aria-label": "Itens", children: _jsx(Stack, { as: "li", children: "um" }) }));
|
|
23
|
+
expect(screen.getByRole("list", { name: "Itens" })).toBeInTheDocument();
|
|
24
|
+
expect(container.querySelectorAll("li")).toHaveLength(1);
|
|
25
|
+
});
|
|
26
|
+
it("repassa id, aria-label, title e style ao elemento raiz", () => {
|
|
27
|
+
const { container } = render(_jsx(Stack, { as: "nav", id: "menu", "aria-label": "Principal", title: "Dica", style: { marginTop: 4 }, children: "x" }));
|
|
28
|
+
const el = container.firstElementChild;
|
|
29
|
+
expect(el.id).toBe("menu");
|
|
30
|
+
expect(el.getAttribute("aria-label")).toBe("Principal");
|
|
31
|
+
expect(el.getAttribute("title")).toBe("Dica");
|
|
32
|
+
expect(el.style.marginTop).toBe("4px");
|
|
33
|
+
expect(screen.getByRole("navigation", { name: "Principal" })).toBe(el);
|
|
34
|
+
});
|
|
35
|
+
it("as=form chama onSubmit", () => {
|
|
36
|
+
const aoEnviar = vi.fn((e) => e.preventDefault());
|
|
37
|
+
const { container } = render(_jsx(Stack, { as: "form", onSubmit: aoEnviar, children: _jsx("button", { type: "submit", children: "Enviar" }) }));
|
|
38
|
+
fireEvent.submit(container.querySelector("form"));
|
|
39
|
+
expect(aoEnviar).toHaveBeenCalledTimes(1);
|
|
40
|
+
});
|
|
41
|
+
it("escreve as classes de item flex", () => {
|
|
42
|
+
const { container } = render(_jsx(Stack, { grow: true, shrink: "0", basis: "50", minWidth: "auto", overflow: "hidden", overflowY: "auto", fullHeight: true, children: "x" }));
|
|
43
|
+
const el = container.firstElementChild;
|
|
44
|
+
for (const c of [
|
|
45
|
+
"umds-stack--grow",
|
|
46
|
+
"umds-stack--shrink-0",
|
|
47
|
+
"umds-stack--basis-50",
|
|
48
|
+
"umds-stack--min-w-auto",
|
|
49
|
+
"umds-stack--overflow-hidden",
|
|
50
|
+
"umds-stack--overflow-y-auto",
|
|
51
|
+
"umds-stack--full-height",
|
|
52
|
+
]) {
|
|
53
|
+
expect(el).toHaveClass(c);
|
|
54
|
+
}
|
|
55
|
+
expect(el).not.toHaveClass("umds-stack--full-width");
|
|
56
|
+
});
|
|
57
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { describe, expect, it } from "vitest";
|
|
3
|
+
import { render, screen } from "@testing-library/react";
|
|
4
|
+
import StatCard from "../components/StatCard/StatCard";
|
|
5
|
+
const raiz = (c) => c.firstElementChild;
|
|
6
|
+
describe("StatCard · labelPosition", () => {
|
|
7
|
+
it("top escreve a classe; sem a prop o cartão é o de antes", () => {
|
|
8
|
+
const { container } = render(_jsxs(_Fragment, { children: [_jsx(StatCard, { value: 44, label: "N\u00E3o lidos", labelPosition: "top" }), _jsx(StatCard, { value: 44, label: "N\u00E3o lidos" })] }));
|
|
9
|
+
expect(container.children[0]).toHaveClass("umds-stat-card--rotulo-topo");
|
|
10
|
+
expect(container.children[1]).not.toHaveClass("umds-stat-card--rotulo-topo");
|
|
11
|
+
});
|
|
12
|
+
it("o número continua antes do rótulo no HTML (ordem do leitor de tela)", () => {
|
|
13
|
+
const { container } = render(_jsx(StatCard, { value: 44, label: "N\u00E3o lidos", labelPosition: "top" }));
|
|
14
|
+
const valor = container.querySelector(".umds-stat-card__valor");
|
|
15
|
+
const rotulo = container.querySelector(".umds-stat-card__rotulo");
|
|
16
|
+
expect(valor.compareDocumentPosition(rotulo) & Node.DOCUMENT_POSITION_FOLLOWING).toBeTruthy();
|
|
17
|
+
});
|
|
18
|
+
});
|
|
19
|
+
describe("StatCard · infoTooltip", () => {
|
|
20
|
+
it("mostra o ⓘ como botão nomeado, dentro do rótulo, descrito pelo texto de ajuda", () => {
|
|
21
|
+
const { container } = render(_jsx(StatCard, { value: 44, label: "N\u00E3o lidos", infoTooltip: "Ainda n\u00E3o abertos por voc\u00EA." }));
|
|
22
|
+
const info = screen.getByRole("button", { name: "Mais informações" });
|
|
23
|
+
expect(container.querySelector(".umds-stat-card__rotulo")?.contains(info)).toBe(true);
|
|
24
|
+
expect(info).toHaveAccessibleDescription("Ainda não abertos por você.");
|
|
25
|
+
});
|
|
26
|
+
it("infoLabel traduz o nome do ⓘ", () => {
|
|
27
|
+
render(_jsx(StatCard, { value: 1, label: "Unread", infoTooltip: "Not opened yet.", infoLabel: "More info" }));
|
|
28
|
+
expect(screen.getByRole("button", { name: "More info" })).toBeInTheDocument();
|
|
29
|
+
});
|
|
30
|
+
it("sem infoTooltip não há botão", () => {
|
|
31
|
+
render(_jsx(StatCard, { value: 1, label: "x" }));
|
|
32
|
+
expect(screen.queryByRole("button")).toBeNull();
|
|
33
|
+
});
|
|
34
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { describe, expect, it } from "vitest";
|
|
3
|
+
import { render } from "@testing-library/react";
|
|
4
|
+
import StatCard from "../components/StatCard/StatCard";
|
|
5
|
+
describe("StatCard · segunda medida e valueTone", () => {
|
|
6
|
+
it("secondaryValue e secondaryLabel vêm depois do corpo, e o número principal segue antes do rótulo", () => {
|
|
7
|
+
const { container } = render(_jsx(StatCard, { value: "22,31%", label: "Efici\u00EAncia", description: "Meu Setor", secondaryValue: "14,11%", secondaryLabel: "Geral", labelPosition: "top" }));
|
|
8
|
+
const filhos = [...container.firstElementChild.children].map((e) => e.className);
|
|
9
|
+
expect(filhos[filhos.length - 1]).toBe("umds-stat-card__secundaria");
|
|
10
|
+
const secundaria = container.querySelector(".umds-stat-card__secundaria");
|
|
11
|
+
expect(secundaria.querySelector(".umds-stat-card__valor-secundario")).toHaveTextContent("14,11%");
|
|
12
|
+
expect(secundaria.querySelector(".umds-stat-card__rotulo-secundario")).toHaveTextContent("Geral");
|
|
13
|
+
expect(container.firstElementChild).toHaveClass("umds-stat-card--com-secundaria");
|
|
14
|
+
const texto = container.firstElementChild.textContent;
|
|
15
|
+
expect(texto.indexOf("22,31%")).toBeLessThan(texto.indexOf("Eficiência"));
|
|
16
|
+
expect(texto.indexOf("Eficiência")).toBeLessThan(texto.indexOf("14,11%"));
|
|
17
|
+
});
|
|
18
|
+
it("secondaryValue 0 aparece; vazio e ausente não", () => {
|
|
19
|
+
const { container, rerender } = render(_jsx(StatCard, { value: "5", label: "x", secondaryValue: 0 }));
|
|
20
|
+
expect(container.querySelector(".umds-stat-card__valor-secundario")).toHaveTextContent("0");
|
|
21
|
+
rerender(_jsx(StatCard, { value: "5", label: "x", secondaryValue: "" }));
|
|
22
|
+
expect(container.querySelector(".umds-stat-card__secundaria")).toBeNull();
|
|
23
|
+
rerender(_jsx(StatCard, { value: "5", label: "x" }));
|
|
24
|
+
expect(container.querySelector(".umds-stat-card__secundaria")).toBeNull();
|
|
25
|
+
expect(container.firstElementChild).not.toHaveClass("umds-stat-card--com-secundaria");
|
|
26
|
+
});
|
|
27
|
+
it("secondaryValue sem secondaryLabel não desenha o rótulo", () => {
|
|
28
|
+
const { container } = render(_jsx(StatCard, { value: "5", label: "x", secondaryValue: "9" }));
|
|
29
|
+
expect(container.querySelector(".umds-stat-card__rotulo-secundario")).toBeNull();
|
|
30
|
+
});
|
|
31
|
+
it("valueTone escreve a classe do tom; default e ausente não", () => {
|
|
32
|
+
const { container, rerender } = render(_jsx(StatCard, { value: "5", label: "x", valueTone: "negative" }));
|
|
33
|
+
expect(container.firstElementChild).toHaveClass("umds-stat-card--valor-negative");
|
|
34
|
+
rerender(_jsx(StatCard, { value: "5", label: "x", valueTone: "primary" }));
|
|
35
|
+
expect(container.firstElementChild).toHaveClass("umds-stat-card--valor-primary");
|
|
36
|
+
rerender(_jsx(StatCard, { value: "5", label: "x", valueTone: "default" }));
|
|
37
|
+
expect(container.firstElementChild.className).not.toMatch(/valor-/);
|
|
38
|
+
rerender(_jsx(StatCard, { value: "5", label: "x" }));
|
|
39
|
+
expect(container.firstElementChild.className).not.toMatch(/valor-/);
|
|
40
|
+
});
|
|
41
|
+
it("valueTone não mexe na variant do ícone", () => {
|
|
42
|
+
const { container } = render(_jsx(StatCard, { value: "5", label: "x", variant: "positive", valueTone: "negative" }));
|
|
43
|
+
expect(container.firstElementChild).toHaveClass("umds-stat-card--positive", "umds-stat-card--valor-negative");
|
|
44
|
+
});
|
|
45
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { describe, expect, it, vi } from "vitest";
|
|
3
|
+
import { fireEvent, render, screen } from "@testing-library/react";
|
|
4
|
+
import Tabs from "../components/Tabs/Tabs";
|
|
5
|
+
import Tab from "../components/Tabs/Tab";
|
|
6
|
+
describe("Tab · count", () => {
|
|
7
|
+
it("mostra o contador em pílula e ele entra no nome da aba", () => {
|
|
8
|
+
render(_jsxs(Tabs, { value: "0", ariaLabel: "Tarefas", children: [_jsx(Tab, { label: "Todas", index: "0", count: 31 }), _jsx(Tab, { label: "Atribu\u00EDdas", index: "1", count: 9 })] }));
|
|
9
|
+
expect(screen.getByRole("tab", { name: "Todas 31" })).toBeInTheDocument();
|
|
10
|
+
expect(screen.getByRole("tab", { name: "Atribuídas 9" })).toBeInTheDocument();
|
|
11
|
+
});
|
|
12
|
+
it("o 0 aparece; sem count, não há pílula", () => {
|
|
13
|
+
const { container } = render(_jsxs(Tabs, { value: "0", children: [_jsx(Tab, { label: "Conclu\u00EDdas", index: "0", count: 0 }), _jsx(Tab, { label: "Sem contador", index: "1" })] }));
|
|
14
|
+
const pilulas = container.querySelectorAll(".umds-tabs__count");
|
|
15
|
+
expect(pilulas).toHaveLength(1);
|
|
16
|
+
expect(pilulas[0].textContent).toBe("0");
|
|
17
|
+
});
|
|
18
|
+
it("a pílula fica dentro da aba selecionada (que a pinta de azul pelo CSS)", () => {
|
|
19
|
+
const { container } = render(_jsxs(Tabs, { value: "1", children: [_jsx(Tab, { label: "A", index: "0", count: 1 }), _jsx(Tab, { label: "B", index: "1", count: 2 })] }));
|
|
20
|
+
const selecionada = container.querySelector(".umds-tabs__tab--selected");
|
|
21
|
+
expect(selecionada?.querySelector(".umds-tabs__count")?.textContent).toBe("2");
|
|
22
|
+
});
|
|
23
|
+
});
|
|
24
|
+
describe("Tab · closable", () => {
|
|
25
|
+
it("o × é um botão irmão da aba, com o nome 'Fechar <aba>'", () => {
|
|
26
|
+
render(_jsx(Tabs, { value: "0", children: _jsx(Tab, { label: "Documento 1", index: "0", closable: true }) }));
|
|
27
|
+
const fechar = screen.getByRole("button", { name: "Fechar Documento 1" });
|
|
28
|
+
const aba = screen.getByRole("tab");
|
|
29
|
+
expect(aba.contains(fechar)).toBe(false);
|
|
30
|
+
expect(fechar.parentElement).toBe(aba.parentElement);
|
|
31
|
+
});
|
|
32
|
+
it("o rótulo do × vem por prop", () => {
|
|
33
|
+
render(_jsx(Tabs, { value: "0", children: _jsx(Tab, { label: "Doc 1", index: "0", closable: true, closeLabel: "Close" }) }));
|
|
34
|
+
expect(screen.getByRole("button", { name: "Close Doc 1" })).toBeInTheDocument();
|
|
35
|
+
});
|
|
36
|
+
it("clicar no × chama onClose com o index e não troca de aba", () => {
|
|
37
|
+
const aoFechar = vi.fn();
|
|
38
|
+
const aoTrocar = vi.fn();
|
|
39
|
+
render(_jsxs(Tabs, { value: "0", onChange: aoTrocar, children: [_jsx(Tab, { label: "Um", index: "0" }), _jsx(Tab, { label: "Dois", index: "1", closable: true, onClose: aoFechar })] }));
|
|
40
|
+
fireEvent.click(screen.getByRole("button", { name: "Fechar Dois" }));
|
|
41
|
+
expect(aoFechar).toHaveBeenCalledTimes(1);
|
|
42
|
+
expect(aoFechar.mock.calls[0][0]).toBe("1");
|
|
43
|
+
expect(aoTrocar).not.toHaveBeenCalled();
|
|
44
|
+
});
|
|
45
|
+
it("Delete na aba focada fecha; sem closable, não", () => {
|
|
46
|
+
const aoFechar = vi.fn();
|
|
47
|
+
render(_jsxs(Tabs, { value: "0", children: [_jsx(Tab, { label: "Fech\u00E1vel", index: "0", closable: true, onClose: aoFechar }), _jsx(Tab, { label: "Fixa", index: "1", onClose: aoFechar })] }));
|
|
48
|
+
fireEvent.keyDown(screen.getByRole("tab", { name: "Fechável" }), { key: "Delete" });
|
|
49
|
+
expect(aoFechar).toHaveBeenCalledTimes(1);
|
|
50
|
+
fireEvent.keyDown(screen.getByRole("tab", { name: "Fixa" }), { key: "Delete" });
|
|
51
|
+
expect(aoFechar).toHaveBeenCalledTimes(1);
|
|
52
|
+
});
|
|
53
|
+
it("sem closable não há ×", () => {
|
|
54
|
+
render(_jsx(Tabs, { value: "0", children: _jsx(Tab, { label: "Fixa", index: "0" }) }));
|
|
55
|
+
expect(screen.queryByRole("button")).toBeNull();
|
|
56
|
+
});
|
|
57
|
+
it("o tablist só tem abas como filhas de papel (o × não é tab)", () => {
|
|
58
|
+
render(_jsxs(Tabs, { value: "0", children: [_jsx(Tab, { label: "A", index: "0", closable: true }), _jsx(Tab, { label: "B", index: "1", closable: true })] }));
|
|
59
|
+
expect(screen.getAllByRole("tab")).toHaveLength(2);
|
|
60
|
+
});
|
|
61
|
+
});
|
|
62
|
+
describe("Tabs · onAdd", () => {
|
|
63
|
+
it("mostra o + fora do tablist e chama onAdd", () => {
|
|
64
|
+
const aoAdicionar = vi.fn();
|
|
65
|
+
render(_jsx(Tabs, { value: "0", onAdd: aoAdicionar, children: _jsx(Tab, { label: "A", index: "0" }) }));
|
|
66
|
+
const mais = screen.getByRole("button", { name: "Adicionar aba" });
|
|
67
|
+
expect(screen.getByRole("tablist").contains(mais)).toBe(false);
|
|
68
|
+
fireEvent.click(mais);
|
|
69
|
+
expect(aoAdicionar).toHaveBeenCalledTimes(1);
|
|
70
|
+
});
|
|
71
|
+
it("o rótulo do + vem por prop", () => {
|
|
72
|
+
render(_jsx(Tabs, { value: "0", onAdd: () => { }, addLabel: "New tab", children: _jsx(Tab, { label: "A", index: "0" }) }));
|
|
73
|
+
expect(screen.getByRole("button", { name: "New tab" })).toBeInTheDocument();
|
|
74
|
+
});
|
|
75
|
+
it("sem onAdd não há botão", () => {
|
|
76
|
+
render(_jsx(Tabs, { value: "0", children: _jsx(Tab, { label: "A", index: "0" }) }));
|
|
77
|
+
expect(screen.queryByRole("button")).toBeNull();
|
|
78
|
+
});
|
|
79
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|