@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,221 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { describe, expect, it, vi } from "vitest";
|
|
3
|
+
import { useState } from "react";
|
|
4
|
+
import { render, screen, within } from "@testing-library/react";
|
|
5
|
+
import userEvent from "@testing-library/user-event";
|
|
6
|
+
import Calendar from "../components/Calendar/Calendar";
|
|
7
|
+
const HOJE = "2026-05-15";
|
|
8
|
+
const EVENTOS = [
|
|
9
|
+
{ id: "a", date: "2026-05-04", title: "Proc. Administrativo 002/2020", color: "--umds-primitive-blue-pure" },
|
|
10
|
+
{ id: "b", date: "2026-05-11", title: "Protocolo 005/2020", color: "--umds-primitive-green-pure", time: "09:00" },
|
|
11
|
+
{ id: "c", date: "2026-05-11", title: "Ofício 001/2020", color: "--umds-primitive-red-pure", time: "08:00" },
|
|
12
|
+
{ id: "d1", date: "2026-05-20", title: "Reunião 1" },
|
|
13
|
+
{ id: "d2", date: "2026-05-20", title: "Reunião 2" },
|
|
14
|
+
{ id: "d3", date: "2026-05-20", title: "Reunião 3" },
|
|
15
|
+
{ id: "d4", date: "2026-05-20", title: "Reunião 4" },
|
|
16
|
+
{ id: "d5", date: "2026-05-20", title: "Reunião 5" },
|
|
17
|
+
];
|
|
18
|
+
const celula = (container, iso) => container.querySelector(`[data-date="${iso}"]`);
|
|
19
|
+
describe("Calendar", () => {
|
|
20
|
+
it("é uma grade nomeada pelo mês, com sete cabeçalhos de dia", () => {
|
|
21
|
+
render(_jsx(Calendar, { today: HOJE, defaultDate: HOJE }));
|
|
22
|
+
expect(screen.getByRole("grid", { name: "Maio 2026" })).toBeInTheDocument();
|
|
23
|
+
const cabecalhos = screen.getAllByRole("columnheader");
|
|
24
|
+
expect(cabecalhos).toHaveLength(7);
|
|
25
|
+
expect(cabecalhos[0]).toHaveAccessibleName("Domingo");
|
|
26
|
+
expect(screen.getByText("Maio 2026")).toBeInTheDocument();
|
|
27
|
+
});
|
|
28
|
+
it("o mês de maio de 2026 ocupa seis semanas inteiras; dias de fora ganham a classe", () => {
|
|
29
|
+
const { container } = render(_jsx(Calendar, { today: HOJE, defaultDate: HOJE }));
|
|
30
|
+
expect(container.querySelectorAll('[role="gridcell"]')).toHaveLength(42);
|
|
31
|
+
expect(celula(container, "2026-04-26")).toHaveClass("umds-calendar__cell--outside");
|
|
32
|
+
expect(celula(container, "2026-05-15")).not.toHaveClass("umds-calendar__cell--outside");
|
|
33
|
+
});
|
|
34
|
+
it("hoje é marcado com aria-current", () => {
|
|
35
|
+
const { container } = render(_jsx(Calendar, { today: HOJE, defaultDate: HOJE }));
|
|
36
|
+
expect(celula(container, HOJE)).toHaveAttribute("aria-current", "date");
|
|
37
|
+
expect(celula(container, "2026-05-16")).not.toHaveAttribute("aria-current");
|
|
38
|
+
});
|
|
39
|
+
it("cada dia tem nome acessível com a data e a contagem de eventos", () => {
|
|
40
|
+
const { container } = render(_jsx(Calendar, { today: HOJE, defaultDate: HOJE, events: EVENTOS }));
|
|
41
|
+
expect(celula(container, "2026-05-11")).toHaveAttribute("aria-label", "segunda-feira, 11 de maio de 2026, 2 eventos");
|
|
42
|
+
expect(celula(container, "2026-05-04")).toHaveAttribute("aria-label", "segunda-feira, 4 de maio de 2026, 1 evento");
|
|
43
|
+
expect(celula(container, "2026-05-12")).toHaveAttribute("aria-label", "terça-feira, 12 de maio de 2026, sem eventos");
|
|
44
|
+
});
|
|
45
|
+
it("dayLabel troca o nome do dia", () => {
|
|
46
|
+
const { container } = render(_jsx(Calendar, { today: HOJE, defaultDate: HOJE, dayLabel: (iso, n) => `${iso}:${n}`, events: EVENTOS }));
|
|
47
|
+
expect(celula(container, "2026-05-11")).toHaveAttribute("aria-label", "2026-05-11:2");
|
|
48
|
+
});
|
|
49
|
+
it("os eventos caem no dia certo, em ordem de horário, com a cor do dado", () => {
|
|
50
|
+
const { container } = render(_jsx(Calendar, { today: HOJE, defaultDate: HOJE, events: EVENTOS }));
|
|
51
|
+
const dia = celula(container, "2026-05-11");
|
|
52
|
+
const chips = within(dia).getAllByRole("button");
|
|
53
|
+
expect(chips).toHaveLength(2);
|
|
54
|
+
expect(chips[0]).toHaveTextContent("08:00");
|
|
55
|
+
expect(chips[0]).toHaveTextContent("Ofício 001/2020");
|
|
56
|
+
expect(chips[0].style.borderLeftColor).toBe("var(--umds-primitive-red-pure)");
|
|
57
|
+
});
|
|
58
|
+
it("evento sem cor usa o primário", () => {
|
|
59
|
+
const { container } = render(_jsx(Calendar, { today: HOJE, defaultDate: HOJE, events: EVENTOS }));
|
|
60
|
+
const chip = within(celula(container, "2026-05-20")).getAllByRole("button")[0];
|
|
61
|
+
expect(chip.style.borderLeftColor).toBe("var(--umds-semantic-color-primary-pure)");
|
|
62
|
+
});
|
|
63
|
+
it("passou de maxVisible: mostra três e um +N, que avisa com os escondidos", async () => {
|
|
64
|
+
const usuario = userEvent.setup();
|
|
65
|
+
const aoVerMais = vi.fn();
|
|
66
|
+
const { container } = render(_jsx(Calendar, { today: HOJE, defaultDate: HOJE, events: EVENTOS, onMoreClick: aoVerMais }));
|
|
67
|
+
const dia = celula(container, "2026-05-20");
|
|
68
|
+
expect(within(dia).getAllByText(/Reunião/)).toHaveLength(3);
|
|
69
|
+
const mais = within(dia).getByRole("button", { name: "2 eventos a mais em 20 de maio" });
|
|
70
|
+
expect(mais).toHaveTextContent("+2");
|
|
71
|
+
await usuario.click(mais);
|
|
72
|
+
expect(aoVerMais).toHaveBeenCalledTimes(1);
|
|
73
|
+
expect(aoVerMais.mock.calls[0][0]).toBe("2026-05-20");
|
|
74
|
+
expect(aoVerMais.mock.calls[0][1].map((e) => e.id)).toEqual(["d4", "d5"]);
|
|
75
|
+
});
|
|
76
|
+
it("maxVisible muda o corte", () => {
|
|
77
|
+
const { container } = render(_jsx(Calendar, { today: HOJE, defaultDate: HOJE, events: EVENTOS, maxVisible: 1 }));
|
|
78
|
+
expect(within(celula(container, "2026-05-20")).getAllByText(/Reunião/)).toHaveLength(1);
|
|
79
|
+
expect(within(celula(container, "2026-05-20")).getByText("+4")).toBeInTheDocument();
|
|
80
|
+
});
|
|
81
|
+
it("clicar no evento avisa com o evento e não clica no dia", async () => {
|
|
82
|
+
const usuario = userEvent.setup();
|
|
83
|
+
const aoEvento = vi.fn();
|
|
84
|
+
const aoDia = vi.fn();
|
|
85
|
+
render(_jsx(Calendar, { today: HOJE, defaultDate: HOJE, events: EVENTOS, onEventClick: aoEvento, onDayClick: aoDia }));
|
|
86
|
+
await usuario.click(screen.getByRole("button", { name: /Proc\. Administrativo 002\/2020/ }));
|
|
87
|
+
expect(aoEvento).toHaveBeenCalledWith(expect.objectContaining({ id: "a" }));
|
|
88
|
+
expect(aoDia).not.toHaveBeenCalled();
|
|
89
|
+
});
|
|
90
|
+
it("clicar no dia avisa com o ISO", async () => {
|
|
91
|
+
const usuario = userEvent.setup();
|
|
92
|
+
const aoDia = vi.fn();
|
|
93
|
+
const { container } = render(_jsx(Calendar, { today: HOJE, defaultDate: HOJE, onDayClick: aoDia }));
|
|
94
|
+
await usuario.click(celula(container, "2026-05-12"));
|
|
95
|
+
expect(aoDia).toHaveBeenCalledWith("2026-05-12");
|
|
96
|
+
});
|
|
97
|
+
it("anterior, próximo e hoje navegam e avisam em onDateChange", async () => {
|
|
98
|
+
const usuario = userEvent.setup();
|
|
99
|
+
const aoMudar = vi.fn();
|
|
100
|
+
render(_jsx(Calendar, { today: HOJE, defaultDate: HOJE, onDateChange: aoMudar }));
|
|
101
|
+
await usuario.click(screen.getByRole("button", { name: "Próximo" }));
|
|
102
|
+
expect(screen.getByText("Junho 2026")).toBeInTheDocument();
|
|
103
|
+
expect(aoMudar).toHaveBeenLastCalledWith("2026-06-15");
|
|
104
|
+
await usuario.click(screen.getByRole("button", { name: "Anterior" }));
|
|
105
|
+
await usuario.click(screen.getByRole("button", { name: "Anterior" }));
|
|
106
|
+
expect(screen.getByText("Abril 2026")).toBeInTheDocument();
|
|
107
|
+
await usuario.click(screen.getByRole("button", { name: "Hoje" }));
|
|
108
|
+
expect(screen.getByText("Maio 2026")).toBeInTheDocument();
|
|
109
|
+
expect(aoMudar).toHaveBeenLastCalledWith(HOJE);
|
|
110
|
+
});
|
|
111
|
+
it("só um dia entra na ordem de Tab (hoje), com os eventos dele", () => {
|
|
112
|
+
const { container } = render(_jsx(Calendar, { today: "2026-05-11", defaultDate: "2026-05-11", events: EVENTOS }));
|
|
113
|
+
const comTab = [...container.querySelectorAll('[role="gridcell"]')].filter((c) => c.getAttribute("tabindex") === "0");
|
|
114
|
+
expect(comTab).toHaveLength(1);
|
|
115
|
+
expect(comTab[0]).toHaveAttribute("data-date", "2026-05-11");
|
|
116
|
+
const chipsComTab = [...container.querySelectorAll(".umds-calendar__event")].filter((c) => c.getAttribute("tabindex") === "0");
|
|
117
|
+
expect(chipsComTab).toHaveLength(2);
|
|
118
|
+
});
|
|
119
|
+
it("setas movem o foco entre os dias; Home, End e Enter", async () => {
|
|
120
|
+
const usuario = userEvent.setup();
|
|
121
|
+
const aoDia = vi.fn();
|
|
122
|
+
const { container } = render(_jsx(Calendar, { today: HOJE, defaultDate: HOJE, onDayClick: aoDia }));
|
|
123
|
+
celula(container, HOJE).focus();
|
|
124
|
+
await usuario.keyboard("{ArrowRight}");
|
|
125
|
+
expect(celula(container, "2026-05-16")).toHaveFocus();
|
|
126
|
+
await usuario.keyboard("{ArrowDown}");
|
|
127
|
+
expect(celula(container, "2026-05-23")).toHaveFocus();
|
|
128
|
+
await usuario.keyboard("{ArrowLeft}{ArrowUp}");
|
|
129
|
+
expect(celula(container, "2026-05-15")).toHaveFocus();
|
|
130
|
+
await usuario.keyboard("{Home}");
|
|
131
|
+
expect(celula(container, "2026-05-10")).toHaveFocus();
|
|
132
|
+
await usuario.keyboard("{End}");
|
|
133
|
+
expect(celula(container, "2026-05-16")).toHaveFocus();
|
|
134
|
+
await usuario.keyboard("{Enter}");
|
|
135
|
+
expect(aoDia).toHaveBeenCalledWith("2026-05-16");
|
|
136
|
+
});
|
|
137
|
+
it("a seta que sai do mês troca de mês e leva o foco", async () => {
|
|
138
|
+
const usuario = userEvent.setup();
|
|
139
|
+
const { container } = render(_jsx(Calendar, { today: HOJE, defaultDate: "2026-05-30" }));
|
|
140
|
+
celula(container, "2026-05-30").focus();
|
|
141
|
+
await usuario.keyboard("{ArrowRight}{ArrowRight}");
|
|
142
|
+
expect(screen.getByText("Junho 2026")).toBeInTheDocument();
|
|
143
|
+
expect(celula(container, "2026-06-01")).toHaveFocus();
|
|
144
|
+
});
|
|
145
|
+
it("PageDown e PageUp trocam de mês", async () => {
|
|
146
|
+
const usuario = userEvent.setup();
|
|
147
|
+
const { container } = render(_jsx(Calendar, { today: HOJE, defaultDate: HOJE }));
|
|
148
|
+
celula(container, HOJE).focus();
|
|
149
|
+
await usuario.keyboard("{PageDown}");
|
|
150
|
+
expect(screen.getByText("Junho 2026")).toBeInTheDocument();
|
|
151
|
+
expect(celula(container, "2026-06-15")).toHaveFocus();
|
|
152
|
+
await usuario.keyboard("{PageUp}{PageUp}");
|
|
153
|
+
expect(screen.getByText("Abril 2026")).toBeInTheDocument();
|
|
154
|
+
});
|
|
155
|
+
it("a visão de semana mostra sete dias, todos os eventos, e avisa em onViewChange", async () => {
|
|
156
|
+
const usuario = userEvent.setup();
|
|
157
|
+
const aoVisao = vi.fn();
|
|
158
|
+
const { container } = render(_jsx(Calendar, { today: "2026-05-20", defaultDate: "2026-05-20", events: EVENTOS, onViewChange: aoVisao }));
|
|
159
|
+
await usuario.click(screen.getByRole("radio", { name: "Semana" }));
|
|
160
|
+
expect(aoVisao).toHaveBeenCalledWith("week");
|
|
161
|
+
expect(container.querySelectorAll('[role="gridcell"]')).toHaveLength(7);
|
|
162
|
+
expect(within(celula(container, "2026-05-20")).getAllByText(/Reunião/)).toHaveLength(5);
|
|
163
|
+
expect(screen.queryByText("+2")).toBeNull();
|
|
164
|
+
expect(container.querySelector(".umds-calendar--week")).not.toBeNull();
|
|
165
|
+
});
|
|
166
|
+
it("na semana, anterior e próximo andam sete dias", async () => {
|
|
167
|
+
const usuario = userEvent.setup();
|
|
168
|
+
const aoMudar = vi.fn();
|
|
169
|
+
render(_jsx(Calendar, { today: "2026-05-20", defaultDate: "2026-05-20", defaultView: "week", onDateChange: aoMudar }));
|
|
170
|
+
await usuario.click(screen.getByRole("button", { name: "Próximo" }));
|
|
171
|
+
expect(aoMudar).toHaveBeenLastCalledWith("2026-05-27");
|
|
172
|
+
await usuario.click(screen.getByRole("button", { name: "Anterior" }));
|
|
173
|
+
await usuario.click(screen.getByRole("button", { name: "Anterior" }));
|
|
174
|
+
expect(aoMudar).toHaveBeenLastCalledWith("2026-05-13");
|
|
175
|
+
});
|
|
176
|
+
it("weekStartsOn=1 começa a semana na segunda", () => {
|
|
177
|
+
render(_jsx(Calendar, { today: HOJE, defaultDate: HOJE, weekStartsOn: 1 }));
|
|
178
|
+
expect(screen.getAllByRole("columnheader")[0]).toHaveAccessibleName("Segunda-feira");
|
|
179
|
+
});
|
|
180
|
+
it("controlado: date e view mandam", () => {
|
|
181
|
+
function Pai() {
|
|
182
|
+
const [data, setData] = useState("2026-08-10");
|
|
183
|
+
return _jsx(Calendar, { today: HOJE, date: data, onDateChange: setData, view: "month" });
|
|
184
|
+
}
|
|
185
|
+
render(_jsx(Pai, {}));
|
|
186
|
+
expect(screen.getByText("Agosto 2026")).toBeInTheDocument();
|
|
187
|
+
});
|
|
188
|
+
it("locale e textos por prop (inglês)", () => {
|
|
189
|
+
render(_jsx(Calendar, { today: HOJE, defaultDate: HOJE, locale: "en-US", previousLabel: "Previous", nextLabel: "Next", todayLabel: "Today", monthLabel: "Month", weekLabel: "Week", viewLabel: "View" }));
|
|
190
|
+
expect(screen.getByText("May 2026")).toBeInTheDocument();
|
|
191
|
+
expect(screen.getByRole("button", { name: "Previous" })).toBeInTheDocument();
|
|
192
|
+
expect(screen.getByRole("button", { name: "Next" })).toBeInTheDocument();
|
|
193
|
+
expect(screen.getByRole("button", { name: "Today" })).toBeInTheDocument();
|
|
194
|
+
expect(screen.getByRole("radio", { name: "Week" })).toBeInTheDocument();
|
|
195
|
+
expect(screen.getByRole("group", { name: "View" })).toBeInTheDocument();
|
|
196
|
+
expect(screen.getAllByRole("columnheader")[0]).toHaveAccessibleName("Sunday");
|
|
197
|
+
});
|
|
198
|
+
it("moreLabel e moreAriaLabel traduzem o +N", () => {
|
|
199
|
+
render(_jsx(Calendar, { today: HOJE, defaultDate: HOJE, events: EVENTOS, locale: "en-US", moreLabel: "{count} more", moreAriaLabel: "{count} more events on {date}" }));
|
|
200
|
+
expect(screen.getByRole("button", { name: "2 more events on May 20" })).toHaveTextContent("2 more");
|
|
201
|
+
});
|
|
202
|
+
it("hideViewSwitcher esconde o seletor; os slots do cabeçalho aparecem", () => {
|
|
203
|
+
render(_jsx(Calendar, { today: HOJE, defaultDate: HOJE, hideViewSwitcher: true, headerStart: _jsx("span", { "data-testid": "filtro", children: "Todos os documentos" }), headerEnd: _jsx("span", { "data-testid": "legenda", children: "Legenda" }) }));
|
|
204
|
+
expect(screen.queryByRole("radio")).toBeNull();
|
|
205
|
+
expect(screen.getByTestId("filtro")).toBeInTheDocument();
|
|
206
|
+
expect(screen.getByTestId("legenda")).toBeInTheDocument();
|
|
207
|
+
});
|
|
208
|
+
it("selectedDate marca o dia", () => {
|
|
209
|
+
const { container } = render(_jsx(Calendar, { today: HOJE, defaultDate: HOJE, selectedDate: "2026-05-12" }));
|
|
210
|
+
expect(celula(container, "2026-05-12")).toHaveAttribute("aria-selected", "true");
|
|
211
|
+
expect(celula(container, "2026-05-12")).toHaveClass("umds-calendar__cell--selected");
|
|
212
|
+
});
|
|
213
|
+
it("evento com Date e com data-hora entra no dia", () => {
|
|
214
|
+
const { container } = render(_jsx(Calendar, { today: HOJE, defaultDate: HOJE, events: [
|
|
215
|
+
{ date: new Date(2026, 4, 12), title: "Com Date" },
|
|
216
|
+
{ date: "2026-05-13T10:30:00", title: "Com hora" },
|
|
217
|
+
] }));
|
|
218
|
+
expect(within(celula(container, "2026-05-12")).getByText("Com Date")).toBeInTheDocument();
|
|
219
|
+
expect(within(celula(container, "2026-05-13")).getByText("Com hora")).toBeInTheDocument();
|
|
220
|
+
});
|
|
221
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,11 @@
|
|
|
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 Calendar from "../components/Calendar/Calendar";
|
|
5
|
+
describe("Calendar · cabeçalho", () => {
|
|
6
|
+
it("headerStart e headerEnd (React: props com nó) chegam ao cabeçalho", () => {
|
|
7
|
+
render(_jsx(Calendar, { events: [], defaultDate: "2026-10-08", headerStart: _jsx("span", { children: "Todos os documentos" }), headerEnd: _jsx("span", { children: "Legenda" }) }));
|
|
8
|
+
expect(screen.getByText("Todos os documentos")).toBeInTheDocument();
|
|
9
|
+
expect(screen.getByText("Legenda")).toBeInTheDocument();
|
|
10
|
+
});
|
|
11
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { describe, expect, it, vi } from "vitest";
|
|
3
|
+
import { fireEvent, render, screen } from "@testing-library/react";
|
|
4
|
+
import Chips from "../components/Chips/Chips";
|
|
5
|
+
const raiz = (c) => c.firstElementChild;
|
|
6
|
+
describe("Chips · xs e × em círculo", () => {
|
|
7
|
+
it("size xs escreve a classe; sem size continua md", () => {
|
|
8
|
+
const { container } = render(_jsxs(_Fragment, { children: [_jsx(Chips, { label: "a", size: "xs" }), _jsx(Chips, { label: "b" })] }));
|
|
9
|
+
expect(container.children[0]).toHaveClass("umds-chip--xs");
|
|
10
|
+
expect(container.children[1]).toHaveClass("umds-chip--md");
|
|
11
|
+
});
|
|
12
|
+
it("circularRemove com removable escreve a classe do círculo", () => {
|
|
13
|
+
const { container } = render(_jsx(Chips, { label: "Marcador", removable: true, circularRemove: true }));
|
|
14
|
+
expect(raiz(container)).toHaveClass("umds-chip--remove-circle");
|
|
15
|
+
});
|
|
16
|
+
it("circularRemove sem removable não escreve a classe (não há ×)", () => {
|
|
17
|
+
const { container } = render(_jsx(Chips, { label: "Marcador", circularRemove: true }));
|
|
18
|
+
expect(raiz(container)).not.toHaveClass("umds-chip--remove-circle");
|
|
19
|
+
expect(screen.queryByRole("button")).toBeNull();
|
|
20
|
+
});
|
|
21
|
+
it("o × em círculo continua sendo o mesmo botão, com o mesmo nome e o mesmo clique", () => {
|
|
22
|
+
const aoRemover = vi.fn();
|
|
23
|
+
render(_jsx(Chips, { label: "Urgente", size: "xs", removable: true, circularRemove: true, onRemove: aoRemover }));
|
|
24
|
+
fireEvent.click(screen.getByRole("button", { name: "Remover Urgente" }));
|
|
25
|
+
expect(aoRemover).toHaveBeenCalledTimes(1);
|
|
26
|
+
});
|
|
27
|
+
it("sem circularRemove o chip removível é o de antes", () => {
|
|
28
|
+
const { container } = render(_jsx(Chips, { label: "x", removable: true }));
|
|
29
|
+
expect(raiz(container)).not.toHaveClass("umds-chip--remove-circle");
|
|
30
|
+
});
|
|
31
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { describe, expect, it, vi } from "vitest";
|
|
3
|
+
import { useRef, useState } from "react";
|
|
4
|
+
import { render, screen, waitFor } from "@testing-library/react";
|
|
5
|
+
import userEvent from "@testing-library/user-event";
|
|
6
|
+
import Coachmark from "../components/Coachmark/Coachmark";
|
|
7
|
+
const PASSOS = [
|
|
8
|
+
{ target: "#alvo-a", title: "Cada item é uma aba", content: "Fluxos e formulários abrem em abas." },
|
|
9
|
+
{ target: "#alvo-b", title: "Salvo sozinho", content: "Tudo fica neste navegador." },
|
|
10
|
+
{ title: "Pronto", content: "Sem alvo: o cartão fica no centro." },
|
|
11
|
+
];
|
|
12
|
+
function Pagina(props) {
|
|
13
|
+
return (_jsxs("div", { children: [_jsx("button", { id: "alvo-a", children: "A" }), _jsx("button", { id: "alvo-b", children: "B" }), _jsx(Coachmark, { steps: PASSOS, ...props })] }));
|
|
14
|
+
}
|
|
15
|
+
describe("Coachmark", () => {
|
|
16
|
+
it("fechado não desenha nada", () => {
|
|
17
|
+
render(_jsx(Pagina, { open: false }));
|
|
18
|
+
expect(screen.queryByRole("dialog")).toBeNull();
|
|
19
|
+
});
|
|
20
|
+
it("aberto é um diálogo modal nomeado pelo título, com contador e texto", () => {
|
|
21
|
+
render(_jsx(Pagina, { open: true }));
|
|
22
|
+
const dialogo = screen.getByRole("dialog", { name: "Cada item é uma aba" });
|
|
23
|
+
expect(dialogo).toHaveAttribute("aria-modal", "true");
|
|
24
|
+
expect(dialogo).toHaveAccessibleDescription("Fluxos e formulários abrem em abas.");
|
|
25
|
+
expect(screen.getAllByText("1 de 3").length).toBeGreaterThan(0);
|
|
26
|
+
expect(screen.getByRole("button", { name: "Próximo" })).toBeInTheDocument();
|
|
27
|
+
expect(screen.queryByRole("button", { name: "Anterior" })).toBeNull();
|
|
28
|
+
});
|
|
29
|
+
it("o foco entra no cartão ao abrir", () => {
|
|
30
|
+
render(_jsx(Pagina, { open: true }));
|
|
31
|
+
expect(screen.getByRole("dialog")).toHaveFocus();
|
|
32
|
+
});
|
|
33
|
+
it("Próximo e Anterior trocam de passo e avisam em onStepChange", async () => {
|
|
34
|
+
const usuario = userEvent.setup();
|
|
35
|
+
const aoMudar = vi.fn();
|
|
36
|
+
render(_jsx(Pagina, { open: true, onStepChange: aoMudar }));
|
|
37
|
+
await usuario.click(screen.getByRole("button", { name: "Próximo" }));
|
|
38
|
+
expect(aoMudar).toHaveBeenLastCalledWith(1);
|
|
39
|
+
expect(screen.getByRole("dialog", { name: "Salvo sozinho" })).toBeInTheDocument();
|
|
40
|
+
await usuario.click(screen.getByRole("button", { name: "Anterior" }));
|
|
41
|
+
expect(aoMudar).toHaveBeenLastCalledWith(0);
|
|
42
|
+
expect(screen.getByRole("dialog", { name: "Cada item é uma aba" })).toBeInTheDocument();
|
|
43
|
+
});
|
|
44
|
+
it("setas direita e esquerda avançam e voltam", async () => {
|
|
45
|
+
const usuario = userEvent.setup();
|
|
46
|
+
render(_jsx(Pagina, { open: true }));
|
|
47
|
+
await usuario.keyboard("{ArrowRight}");
|
|
48
|
+
expect(screen.getByRole("dialog", { name: "Salvo sozinho" })).toBeInTheDocument();
|
|
49
|
+
await usuario.keyboard("{ArrowLeft}");
|
|
50
|
+
expect(screen.getByRole("dialog", { name: "Cada item é uma aba" })).toBeInTheDocument();
|
|
51
|
+
});
|
|
52
|
+
it("o último passo troca Próximo por Concluir e fecha com 'finish'", async () => {
|
|
53
|
+
const usuario = userEvent.setup();
|
|
54
|
+
const aoFechar = vi.fn();
|
|
55
|
+
render(_jsx(Pagina, { open: true, defaultStep: 2, onClose: aoFechar }));
|
|
56
|
+
expect(screen.queryByRole("button", { name: "Próximo" })).toBeNull();
|
|
57
|
+
await usuario.click(screen.getByRole("button", { name: "Concluir" }));
|
|
58
|
+
expect(aoFechar).toHaveBeenCalledWith("finish");
|
|
59
|
+
});
|
|
60
|
+
it("Sair do tour fecha com 'skip' e hideSkip esconde o botão", async () => {
|
|
61
|
+
const usuario = userEvent.setup();
|
|
62
|
+
const aoFechar = vi.fn();
|
|
63
|
+
const { rerender } = render(_jsx(Pagina, { open: true, onClose: aoFechar }));
|
|
64
|
+
await usuario.click(screen.getByRole("button", { name: "Sair do tour" }));
|
|
65
|
+
expect(aoFechar).toHaveBeenCalledWith("skip");
|
|
66
|
+
rerender(_jsx(Pagina, { open: true, hideSkip: true, onClose: aoFechar }));
|
|
67
|
+
expect(screen.queryByRole("button", { name: "Sair do tour" })).toBeNull();
|
|
68
|
+
});
|
|
69
|
+
it("Esc fecha com 'escape'", async () => {
|
|
70
|
+
const usuario = userEvent.setup();
|
|
71
|
+
const aoFechar = vi.fn();
|
|
72
|
+
render(_jsx(Pagina, { open: true, onClose: aoFechar }));
|
|
73
|
+
await usuario.keyboard("{Escape}");
|
|
74
|
+
expect(aoFechar).toHaveBeenCalledWith("escape");
|
|
75
|
+
});
|
|
76
|
+
it("o foco fica preso no cartão: Tab gira e Shift+Tab volta", async () => {
|
|
77
|
+
const usuario = userEvent.setup();
|
|
78
|
+
render(_jsx(Pagina, { open: true }));
|
|
79
|
+
const sair = screen.getByRole("button", { name: "Sair do tour" });
|
|
80
|
+
const proximo = screen.getByRole("button", { name: "Próximo" });
|
|
81
|
+
proximo.focus();
|
|
82
|
+
await usuario.tab();
|
|
83
|
+
expect(sair).toHaveFocus();
|
|
84
|
+
await usuario.tab({ shift: true });
|
|
85
|
+
expect(proximo).toHaveFocus();
|
|
86
|
+
});
|
|
87
|
+
it("todos os textos vêm por prop", () => {
|
|
88
|
+
render(_jsx(Pagina, { open: true, defaultStep: 1, nextLabel: "Next", previousLabel: "Back", skipLabel: "Skip tour", counterLabel: "{current} of {total}" }));
|
|
89
|
+
expect(screen.getByRole("button", { name: "Next" })).toBeInTheDocument();
|
|
90
|
+
expect(screen.getByRole("button", { name: "Back" })).toBeInTheDocument();
|
|
91
|
+
expect(screen.getByRole("button", { name: "Skip tour" })).toBeInTheDocument();
|
|
92
|
+
expect(screen.getAllByText("2 of 3").length).toBeGreaterThan(0);
|
|
93
|
+
});
|
|
94
|
+
it("finishLabel troca o texto do último passo", () => {
|
|
95
|
+
render(_jsx(Pagina, { open: true, defaultStep: 2, finishLabel: "Done" }));
|
|
96
|
+
expect(screen.getByRole("button", { name: "Done" })).toBeInTheDocument();
|
|
97
|
+
});
|
|
98
|
+
it("com alvo, desenha o recorte; sem alvo (ou alvo que não existe), não", () => {
|
|
99
|
+
const { container, rerender } = render(_jsx(Pagina, { open: true }));
|
|
100
|
+
expect(document.querySelector(".umds-coachmark__cutout")).not.toBeNull();
|
|
101
|
+
rerender(_jsx(Pagina, { open: true, step: 2 }));
|
|
102
|
+
expect(document.querySelector(".umds-coachmark__cutout")).toBeNull();
|
|
103
|
+
expect(document.querySelector(".umds-coachmark--no-target")).not.toBeNull();
|
|
104
|
+
void container;
|
|
105
|
+
});
|
|
106
|
+
it("alvo por ref do React e por elemento", () => {
|
|
107
|
+
function ComRef() {
|
|
108
|
+
const ref = useRef(null);
|
|
109
|
+
return (_jsxs("div", { children: [_jsx("button", { ref: ref, children: "Alvo" }), _jsx(Coachmark, { open: true, steps: [{ target: ref, title: "Por ref" }] })] }));
|
|
110
|
+
}
|
|
111
|
+
render(_jsx(ComRef, {}));
|
|
112
|
+
expect(screen.getByRole("dialog", { name: "Por ref" })).toBeInTheDocument();
|
|
113
|
+
expect(document.querySelector(".umds-coachmark__cutout")).not.toBeNull();
|
|
114
|
+
});
|
|
115
|
+
it("step controlado manda no passo atual", () => {
|
|
116
|
+
render(_jsx(Pagina, { open: true, step: 1 }));
|
|
117
|
+
expect(screen.getByRole("dialog", { name: "Salvo sozinho" })).toBeInTheDocument();
|
|
118
|
+
});
|
|
119
|
+
it("ao fechar, o foco volta ao elemento de antes", async () => {
|
|
120
|
+
const usuario = userEvent.setup();
|
|
121
|
+
function Dono() {
|
|
122
|
+
const [aberto, setAberto] = useState(false);
|
|
123
|
+
return (_jsxs("div", { children: [_jsx("button", { id: "abrir", onClick: () => setAberto(true), children: "Fazer o tour" }), _jsx(Coachmark, { open: aberto, steps: PASSOS, onClose: () => setAberto(false) })] }));
|
|
124
|
+
}
|
|
125
|
+
render(_jsx(Dono, {}));
|
|
126
|
+
const abrir = screen.getByRole("button", { name: "Fazer o tour" });
|
|
127
|
+
await usuario.click(abrir);
|
|
128
|
+
expect(screen.getByRole("dialog")).toBeInTheDocument();
|
|
129
|
+
// O foco entra no cartão depois da montagem (um quadro de animação): na CI,
|
|
130
|
+
// mais lenta, o Esc chegava antes e caía no body.
|
|
131
|
+
await waitFor(() => expect(screen.getByRole("dialog").contains(document.activeElement)).toBe(true));
|
|
132
|
+
await usuario.keyboard("{Escape}");
|
|
133
|
+
await waitFor(() => expect(screen.queryByRole("dialog")).toBeNull());
|
|
134
|
+
expect(abrir).toHaveFocus();
|
|
135
|
+
});
|
|
136
|
+
it("reabrir recomeça do primeiro passo", async () => {
|
|
137
|
+
const usuario = userEvent.setup();
|
|
138
|
+
function Dono() {
|
|
139
|
+
const [aberto, setAberto] = useState(true);
|
|
140
|
+
return (_jsxs("div", { children: [_jsx("button", { onClick: () => setAberto(true), children: "Reabrir" }), _jsx(Coachmark, { open: aberto, steps: PASSOS, onClose: () => setAberto(false) })] }));
|
|
141
|
+
}
|
|
142
|
+
render(_jsx(Dono, {}));
|
|
143
|
+
await usuario.keyboard("{ArrowRight}");
|
|
144
|
+
expect(screen.getByRole("dialog", { name: "Salvo sozinho" })).toBeInTheDocument();
|
|
145
|
+
await usuario.keyboard("{Escape}");
|
|
146
|
+
await usuario.click(screen.getByRole("button", { name: "Reabrir" }));
|
|
147
|
+
expect(screen.getByRole("dialog", { name: "Cada item é uma aba" })).toBeInTheDocument();
|
|
148
|
+
});
|
|
149
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,85 @@
|
|
|
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, waitFor } from "@testing-library/react";
|
|
4
|
+
import Coachmark from "../components/Coachmark/Coachmark";
|
|
5
|
+
const PASSOS = [{ target: "#alvo-a", title: "Novo: arrastar", content: "Arraste a linha para trocar a ordem." }];
|
|
6
|
+
function Pagina(props) {
|
|
7
|
+
return (_jsxs("div", { children: [_jsx("button", { id: "alvo-a", children: "A" }), _jsx("button", { id: "fora", children: "Fora" }), _jsx(Coachmark, { steps: PASSOS, open: true, ...props })] }));
|
|
8
|
+
}
|
|
9
|
+
describe("Coachmark · modal={false}", () => {
|
|
10
|
+
it("sem véu nem recorte; o cartão é um diálogo não modal e a raiz deixa o ponteiro passar", () => {
|
|
11
|
+
const { baseElement } = render(_jsx(Pagina, { modal: false }));
|
|
12
|
+
expect(baseElement.querySelector(".umds-coachmark__veil")).toBeNull();
|
|
13
|
+
expect(baseElement.querySelector(".umds-coachmark__cutout")).toBeNull();
|
|
14
|
+
expect(baseElement.querySelector(".umds-coachmark")).toHaveClass("umds-coachmark--modeless");
|
|
15
|
+
expect(screen.getByRole("dialog", { name: "Novo: arrastar" })).toHaveAttribute("aria-modal", "false");
|
|
16
|
+
});
|
|
17
|
+
it("o padrão continua modal: véu, recorte e aria-modal verdadeiro", () => {
|
|
18
|
+
const { baseElement } = render(_jsx(Pagina, {}));
|
|
19
|
+
expect(baseElement.querySelector(".umds-coachmark__veil")).not.toBeNull();
|
|
20
|
+
expect(baseElement.querySelector(".umds-coachmark__cutout")).not.toBeNull();
|
|
21
|
+
expect(baseElement.querySelector(".umds-coachmark")).not.toHaveClass("umds-coachmark--modeless");
|
|
22
|
+
expect(screen.getByRole("dialog")).toHaveAttribute("aria-modal", "true");
|
|
23
|
+
const { unmount } = render(_jsx(Pagina, { modal: true }));
|
|
24
|
+
unmount();
|
|
25
|
+
});
|
|
26
|
+
it("o foco entra no cartão, mas o Tab não fica preso", async () => {
|
|
27
|
+
render(_jsx(Pagina, { modal: false }));
|
|
28
|
+
const cartao = screen.getByRole("dialog");
|
|
29
|
+
await waitFor(() => expect(cartao).toHaveFocus());
|
|
30
|
+
const concluir = screen.getByRole("button", { name: "Concluir" });
|
|
31
|
+
concluir.focus();
|
|
32
|
+
const evento = new KeyboardEvent("keydown", { key: "Tab", bubbles: true, cancelable: true });
|
|
33
|
+
concluir.dispatchEvent(evento);
|
|
34
|
+
expect(evento.defaultPrevented).toBe(false);
|
|
35
|
+
});
|
|
36
|
+
it("no modal o Tab continua preso (o último volta ao primeiro)", () => {
|
|
37
|
+
render(_jsx(Pagina, {}));
|
|
38
|
+
const concluir = screen.getByRole("button", { name: "Concluir" });
|
|
39
|
+
concluir.focus();
|
|
40
|
+
const evento = new KeyboardEvent("keydown", { key: "Tab", bubbles: true, cancelable: true });
|
|
41
|
+
concluir.dispatchEvent(evento);
|
|
42
|
+
expect(evento.defaultPrevented).toBe(true);
|
|
43
|
+
});
|
|
44
|
+
it("a página segue clicável: o clique fora não é capturado e o tour não fecha sozinho", () => {
|
|
45
|
+
const aoFechar = vi.fn();
|
|
46
|
+
render(_jsx(Pagina, { modal: false, onClose: aoFechar }));
|
|
47
|
+
fireEvent.click(screen.getByRole("button", { name: "Fora" }));
|
|
48
|
+
expect(aoFechar).not.toHaveBeenCalled();
|
|
49
|
+
expect(screen.getByRole("dialog")).toBeInTheDocument();
|
|
50
|
+
});
|
|
51
|
+
it("o Esc fecha de qualquer lugar da página, uma vez só", () => {
|
|
52
|
+
const aoFechar = vi.fn();
|
|
53
|
+
render(_jsx(Pagina, { modal: false, onClose: aoFechar }));
|
|
54
|
+
const fora = screen.getByRole("button", { name: "Fora" });
|
|
55
|
+
fora.focus();
|
|
56
|
+
fireEvent.keyDown(fora, { key: "Escape" });
|
|
57
|
+
expect(aoFechar).toHaveBeenCalledTimes(1);
|
|
58
|
+
expect(aoFechar).toHaveBeenCalledWith("escape");
|
|
59
|
+
});
|
|
60
|
+
it("o Esc dentro do cartão também fecha uma vez só", async () => {
|
|
61
|
+
const aoFechar = vi.fn();
|
|
62
|
+
render(_jsx(Pagina, { modal: false, onClose: aoFechar }));
|
|
63
|
+
await waitFor(() => expect(screen.getByRole("dialog")).toHaveFocus());
|
|
64
|
+
fireEvent.keyDown(screen.getByRole("dialog"), { key: "Escape" });
|
|
65
|
+
expect(aoFechar).toHaveBeenCalledTimes(1);
|
|
66
|
+
});
|
|
67
|
+
it("depois de fechar, o ouvinte do Esc sai do documento", () => {
|
|
68
|
+
const aoFechar = vi.fn();
|
|
69
|
+
const { rerender } = render(_jsx(Pagina, { modal: false, onClose: aoFechar }));
|
|
70
|
+
rerender(_jsx(Pagina, { modal: false, open: false, onClose: aoFechar }));
|
|
71
|
+
fireEvent.keyDown(document, { key: "Escape" });
|
|
72
|
+
expect(aoFechar).not.toHaveBeenCalled();
|
|
73
|
+
});
|
|
74
|
+
it("ao fechar, o foco volta ao elemento de antes, se a pessoa não foi a outro lugar", async () => {
|
|
75
|
+
const { rerender } = render(_jsx(Pagina, { modal: false, open: false }));
|
|
76
|
+
const gatilho = screen.getByRole("button", { name: "Fora" });
|
|
77
|
+
gatilho.focus();
|
|
78
|
+
expect(gatilho).toHaveFocus();
|
|
79
|
+
rerender(_jsx(Pagina, { modal: false, open: true }));
|
|
80
|
+
// O foco entra no cartão depois da montagem (um quadro de animação).
|
|
81
|
+
await waitFor(() => expect(screen.getByRole("dialog")).toHaveFocus());
|
|
82
|
+
rerender(_jsx(Pagina, { modal: false, open: false }));
|
|
83
|
+
await waitFor(() => expect(gatilho).toHaveFocus());
|
|
84
|
+
});
|
|
85
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|