@1doc/1ds-react 2.9.0 → 2.11.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 +653 -0
- package/dist/components/Accordion/Accordion.css +13 -0
- package/dist/components/Accordion/Accordion.d.ts +9 -0
- package/dist/components/Accordion/Accordion.js +18 -5
- package/dist/components/AppSubheader/AppSubheader.css +10 -1
- package/dist/components/AttachmentCard/AttachmentCard.css +10 -8
- package/dist/components/AttachmentCard/AttachmentCard.d.ts +3 -0
- package/dist/components/AttachmentCard/AttachmentCard.js +8 -1
- package/dist/components/Badge/Badge.css +27 -5
- package/dist/components/Badge/Badge.d.ts +20 -4
- package/dist/components/Badge/Badge.js +6 -0
- package/dist/components/Button/Button.css +5 -0
- package/dist/components/Button/Button.d.ts +3 -0
- package/dist/components/Button/Button.js +1 -0
- package/dist/components/Calendar/Calendar.css +10 -0
- package/dist/components/Calendar/Calendar.d.ts +10 -6
- package/dist/components/Calendar/Calendar.js +6 -1
- package/dist/components/Coachmark/Coachmark.css +10 -0
- package/dist/components/Coachmark/Coachmark.d.ts +14 -1
- package/dist/components/Coachmark/Coachmark.js +51 -5
- package/dist/components/ColorPicker/ColorPicker.css +8 -1
- package/dist/components/ColorPicker/ColorPicker.d.ts +2 -2
- package/dist/components/DataTable/DataTable.css +216 -0
- package/dist/components/DataTable/DataTable.d.ts +70 -2
- package/dist/components/DataTable/DataTable.js +293 -6
- package/dist/components/DescriptionList/DescriptionList.css +14 -0
- package/dist/components/DescriptionList/DescriptionList.d.ts +3 -0
- package/dist/components/DescriptionList/DescriptionList.js +1 -0
- package/dist/components/EmptyState/EmptyState.d.ts +4 -2
- package/dist/components/EmptyState/EmptyState.js +2 -2
- package/dist/components/Input/Input.css +30 -0
- package/dist/components/Input/Input.d.ts +10 -0
- package/dist/components/Input/Input.js +3 -1
- package/dist/components/List/ListItem.d.ts +14 -2
- package/dist/components/List/ListItem.js +3 -2
- package/dist/components/Modal/Modal.css +19 -0
- package/dist/components/Modal/Modal.d.ts +7 -0
- package/dist/components/Modal/Modal.js +1 -0
- package/dist/components/RichTextEditor/RichTextEditor.css +47 -0
- package/dist/components/RichTextEditor/RichTextEditor.d.ts +22 -8
- package/dist/components/RichTextEditor/RichTextEditor.js +460 -3
- package/dist/components/SegmentedControl/SegmentedControl.css +70 -0
- package/dist/components/SegmentedControl/SegmentedControl.d.ts +5 -0
- package/dist/components/SegmentedControl/SegmentedControl.js +5 -1
- package/dist/components/Select/Select.css +122 -2
- package/dist/components/Select/Select.d.ts +33 -4
- package/dist/components/Select/Select.js +256 -35
- package/dist/components/StatCard/StatCard.css +73 -0
- package/dist/components/StatCard/StatCard.d.ts +12 -0
- package/dist/components/StatCard/StatCard.js +11 -1
- package/dist/components/Tabs/Tabs.css +11 -0
- package/dist/components/Tabs/Tabs.d.ts +7 -0
- package/dist/components/Tabs/Tabs.js +7 -1
- package/dist/components/Tag/Tag.css +3 -1
- 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/teste/AccordionControlado.test.d.ts +1 -0
- package/dist/teste/AccordionControlado.test.js +73 -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/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/BadgeAttachedTomEPadding.test.d.ts +1 -0
- package/dist/teste/BadgeAttachedTomEPadding.test.js +43 -0
- package/dist/teste/BadgeNeutroColado.test.d.ts +1 -0
- package/dist/teste/BadgeNeutroColado.test.js +11 -0
- package/dist/teste/BadgeTag.test.js +13 -0
- package/dist/teste/ButtonDensidade.test.d.ts +1 -0
- package/dist/teste/ButtonDensidade.test.js +28 -0
- package/dist/teste/CalendarCabecalho.test.d.ts +1 -0
- package/dist/teste/CalendarCabecalho.test.js +11 -0
- package/dist/teste/CalendarCompacto.test.d.ts +1 -0
- package/dist/teste/CalendarCompacto.test.js +29 -0
- package/dist/teste/CoachmarkSemVeu.test.d.ts +1 -0
- package/dist/teste/CoachmarkSemVeu.test.js +85 -0
- package/dist/teste/CoachmarkUmPasso.test.d.ts +1 -0
- package/dist/teste/CoachmarkUmPasso.test.js +34 -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/DataTableCompactaETom.test.d.ts +1 -0
- package/dist/teste/DataTableCompactaETom.test.js +69 -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/InputAgrupado.test.d.ts +1 -0
- package/dist/teste/InputAgrupado.test.js +24 -0
- package/dist/teste/InputGhost.test.d.ts +1 -0
- package/dist/teste/InputGhost.test.js +32 -0
- package/dist/teste/ListItemTooltipStandalone.test.d.ts +1 -0
- package/dist/teste/ListItemTooltipStandalone.test.js +39 -0
- package/dist/teste/ModalProporcoes1Doc.test.d.ts +1 -0
- package/dist/teste/ModalProporcoes1Doc.test.js +32 -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/SegmentedControlSuperficie.test.d.ts +1 -0
- package/dist/teste/SegmentedControlSuperficie.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/SelectItemComEscopo.test.d.ts +1 -0
- package/dist/teste/SelectItemComEscopo.test.js +54 -0
- package/dist/teste/SelectListaFiltro.test.d.ts +1 -0
- package/dist/teste/SelectListaFiltro.test.js +102 -0
- package/dist/teste/StatCardSecundariaETom.test.d.ts +1 -0
- package/dist/teste/StatCardSecundariaETom.test.js +45 -0
- package/dist/teste/StatCardTamanhoSm.test.d.ts +1 -0
- package/dist/teste/StatCardTamanhoSm.test.js +32 -0
- package/dist/teste/TabsCompacta.test.d.ts +1 -0
- package/dist/teste/TabsCompacta.test.js +35 -0
- package/dist/teste/TagPositivoTingido.test.d.ts +1 -0
- package/dist/teste/TagPositivoTingido.test.js +54 -0
- package/dist/teste/ToastAcaoEDetalhes.test.d.ts +1 -0
- package/dist/teste/ToastAcaoEDetalhes.test.js +94 -0
- package/dist/teste/lerArquivo.d.ts +1 -0
- package/dist/teste/lerArquivo.js +12 -0
- package/dist/utils/html-seguro.d.ts +19 -1
- package/dist/utils/html-seguro.js +113 -2
- package/dist/utils/toast.d.ts +10 -1
- package/dist/utils/toast.js +2 -1
- package/package.json +3 -3
- package/src/teste/AccordionControlado.test.tsx +87 -0
- package/src/teste/AccordionTituloNeutro.test.tsx +25 -0
- package/src/teste/AppSubheaderRegiao.test.tsx +17 -0
- package/src/teste/AttachmentCardLista.test.tsx +53 -0
- package/src/teste/AttachmentCardSm.test.tsx +29 -0
- package/src/teste/BadgeAttachedTomEPadding.test.tsx +60 -0
- package/src/teste/BadgeNeutroColado.test.tsx +15 -0
- package/src/teste/BadgeTag.test.tsx +21 -0
- package/src/teste/ButtonDensidade.test.tsx +40 -0
- package/src/teste/CalendarCabecalho.test.tsx +11 -0
- package/src/teste/CalendarCompacto.test.tsx +37 -0
- package/src/teste/CoachmarkSemVeu.test.tsx +101 -0
- package/src/teste/CoachmarkUmPasso.test.tsx +45 -0
- package/src/teste/ColorPickerXs.test.tsx +22 -0
- package/src/teste/DataTableArvoreEVariantes.test.tsx +240 -0
- package/src/teste/DataTableCompactaETom.test.tsx +85 -0
- package/src/teste/DescriptionListCompacta.test.tsx +24 -0
- package/src/teste/EmptyStateTituloRico.test.tsx +34 -0
- package/src/teste/InputAgrupado.test.tsx +26 -0
- package/src/teste/InputGhost.test.tsx +42 -0
- package/src/teste/ListItemTooltipStandalone.test.tsx +64 -0
- package/src/teste/ModalProporcoes1Doc.test.tsx +36 -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/SegmentedControlSuperficie.test.tsx +52 -0
- package/src/teste/SelectAbertoControladoEFlutuante.test.tsx +180 -0
- package/src/teste/SelectFiltroCorETamanho.test.tsx +90 -0
- package/src/teste/SelectItemComEscopo.test.tsx +69 -0
- package/src/teste/SelectListaFiltro.test.tsx +120 -0
- package/src/teste/StatCardSecundariaETom.test.tsx +51 -0
- package/src/teste/StatCardTamanhoSm.test.tsx +42 -0
- package/src/teste/TabsCompacta.test.tsx +45 -0
- package/src/teste/TagPositivoTingido.test.tsx +60 -0
- package/src/teste/ToastAcaoEDetalhes.test.tsx +109 -0
- package/src/teste/lerArquivo.ts +13 -0
- package/src/utils/html-seguro.ts +105 -2
- package/src/utils/toast.ts +12 -2
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
import { afterEach, describe, expect, it, vi } from "vitest";
|
|
2
|
+
import { fireEvent, render, screen, waitFor } from "@testing-library/react";
|
|
3
|
+
import { faFilter } from "@fortawesome/free-solid-svg-icons";
|
|
4
|
+
import Select from "../components/Select/Select";
|
|
5
|
+
|
|
6
|
+
const OPCOES = [
|
|
7
|
+
{ label: "Urgente", value: "urgente" },
|
|
8
|
+
{ label: "Revisão", value: "revisao" },
|
|
9
|
+
];
|
|
10
|
+
|
|
11
|
+
afterEach(() => vi.restoreAllMocks());
|
|
12
|
+
|
|
13
|
+
describe("Select · open e onOpenChange", () => {
|
|
14
|
+
it("open controlado mostra a lista sem clique; fechado, não mostra", () => {
|
|
15
|
+
const { rerender } = render(<Select ariaLabel="x" options={OPCOES} open={false} />);
|
|
16
|
+
expect(screen.queryByRole("listbox")).toBeNull();
|
|
17
|
+
rerender(<Select ariaLabel="x" options={OPCOES} open />);
|
|
18
|
+
expect(screen.getByRole("listbox")).toBeInTheDocument();
|
|
19
|
+
expect(screen.getByRole("combobox")).toHaveAttribute("aria-expanded", "true");
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
it("controlado: o clique só avisa; quem abre é o pai", () => {
|
|
23
|
+
const aoAbrir = vi.fn();
|
|
24
|
+
const { rerender } = render(<Select ariaLabel="x" options={OPCOES} open={false} onOpenChange={aoAbrir} />);
|
|
25
|
+
fireEvent.click(screen.getByRole("combobox"));
|
|
26
|
+
expect(aoAbrir).toHaveBeenCalledWith(true);
|
|
27
|
+
expect(screen.queryByRole("listbox")).toBeNull();
|
|
28
|
+
rerender(<Select ariaLabel="x" options={OPCOES} open onOpenChange={aoAbrir} />);
|
|
29
|
+
expect(screen.getByRole("listbox")).toBeInTheDocument();
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
it("controlado aberto: escolher uma opção, Esc e clique fora pedem para fechar", () => {
|
|
33
|
+
const aoAbrir = vi.fn();
|
|
34
|
+
const { rerender } = render(<Select ariaLabel="x" options={OPCOES} open onOpenChange={aoAbrir} />);
|
|
35
|
+
fireEvent.click(screen.getAllByRole("option")[0]);
|
|
36
|
+
expect(aoAbrir).toHaveBeenLastCalledWith(false);
|
|
37
|
+
|
|
38
|
+
aoAbrir.mockClear();
|
|
39
|
+
rerender(<Select ariaLabel="x" options={OPCOES} open onOpenChange={aoAbrir} />);
|
|
40
|
+
fireEvent.keyDown(screen.getByRole("combobox"), { key: "Escape" });
|
|
41
|
+
expect(aoAbrir).toHaveBeenLastCalledWith(false);
|
|
42
|
+
|
|
43
|
+
aoAbrir.mockClear();
|
|
44
|
+
fireEvent.mouseDown(document.body);
|
|
45
|
+
expect(aoAbrir).toHaveBeenCalledWith(false);
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
it("o clique fora não avisa quando a lista está fechada", () => {
|
|
49
|
+
const aoAbrir = vi.fn();
|
|
50
|
+
render(<Select ariaLabel="x" options={OPCOES} open={false} onOpenChange={aoAbrir} />);
|
|
51
|
+
fireEvent.mouseDown(document.body);
|
|
52
|
+
expect(aoAbrir).not.toHaveBeenCalled();
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
it("clique fora vê o open de agora, não o do primeiro render", () => {
|
|
56
|
+
const aoAbrir = vi.fn();
|
|
57
|
+
const { rerender } = render(<Select ariaLabel="x" options={OPCOES} open={false} onOpenChange={aoAbrir} />);
|
|
58
|
+
rerender(<Select ariaLabel="x" options={OPCOES} open onOpenChange={aoAbrir} />);
|
|
59
|
+
fireEvent.mouseDown(document.body);
|
|
60
|
+
expect(aoAbrir).toHaveBeenCalledWith(false);
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
it("sem open, o Select abre e fecha sozinho e também avisa", () => {
|
|
64
|
+
const aoAbrir = vi.fn();
|
|
65
|
+
render(<Select ariaLabel="x" options={OPCOES} onOpenChange={aoAbrir} />);
|
|
66
|
+
fireEvent.click(screen.getByRole("combobox"));
|
|
67
|
+
expect(screen.getByRole("listbox")).toBeInTheDocument();
|
|
68
|
+
expect(aoAbrir).toHaveBeenLastCalledWith(true);
|
|
69
|
+
fireEvent.click(screen.getAllByRole("option")[1]);
|
|
70
|
+
expect(screen.queryByRole("listbox")).toBeNull();
|
|
71
|
+
expect(aoAbrir).toHaveBeenLastCalledWith(false);
|
|
72
|
+
});
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
describe("Select · gatilho com ícone, amostra e aria-required", () => {
|
|
76
|
+
it("triggerIcon e triggerSwatch aparecem no gatilho, decorativos", () => {
|
|
77
|
+
const { container } = render(
|
|
78
|
+
<Select ariaLabel="x" options={OPCOES} triggerIcon={faFilter} triggerSwatch="var(--umds-semantic-color-primary-pure)" />,
|
|
79
|
+
);
|
|
80
|
+
const icone = container.querySelector(".umds-select__trigger-icon") as HTMLElement;
|
|
81
|
+
expect(icone).toHaveAttribute("aria-hidden", "true");
|
|
82
|
+
expect(icone.querySelector("svg")).toHaveAttribute("data-icon", "filter");
|
|
83
|
+
const amostra = container.querySelector(".umds-select__swatch") as HTMLElement;
|
|
84
|
+
expect(amostra).toHaveAttribute("aria-hidden", "true");
|
|
85
|
+
expect(amostra.style.background).toContain("--umds-semantic-color-primary-pure");
|
|
86
|
+
expect(container.querySelector(".umds-select--has-trigger-icon")).not.toBeNull();
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
it("sem as props, não há ícone nem amostra", () => {
|
|
90
|
+
const { container } = render(<Select ariaLabel="x" options={OPCOES} />);
|
|
91
|
+
expect(container.querySelector(".umds-select__trigger-icon")).toBeNull();
|
|
92
|
+
expect(container.querySelector(".umds-select__swatch")).toBeNull();
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
it("required repassa aria-required ao combobox", () => {
|
|
96
|
+
const { rerender } = render(<Select ariaLabel="x" options={OPCOES} required />);
|
|
97
|
+
expect(screen.getByRole("combobox")).toHaveAttribute("aria-required", "true");
|
|
98
|
+
rerender(<Select ariaLabel="x" options={OPCOES} />);
|
|
99
|
+
expect(screen.getByRole("combobox")).not.toHaveAttribute("aria-required");
|
|
100
|
+
});
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
describe("Select · variantes de filtro", () => {
|
|
104
|
+
it("search e combo escrevem a classe do filtro e a própria", () => {
|
|
105
|
+
const { container, rerender } = render(<Select ariaLabel="x" options={OPCOES} variant="search" />);
|
|
106
|
+
expect(container.querySelector(".umds-select--filter.umds-select--filter-search")).not.toBeNull();
|
|
107
|
+
rerender(<Select ariaLabel="x" options={OPCOES} variant="combo" />);
|
|
108
|
+
expect(container.querySelector(".umds-select--filter.umds-select--filter-combo")).not.toBeNull();
|
|
109
|
+
expect(container.querySelector(".umds-select--filter-search")).toBeNull();
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
it("search foca a busca ao abrir, como o filter", async () => {
|
|
113
|
+
render(<Select ariaLabel="x" options={OPCOES} variant="search" searchable />);
|
|
114
|
+
fireEvent.click(screen.getByRole("combobox"));
|
|
115
|
+
await waitFor(() => expect(document.activeElement).toBe(screen.getByRole("textbox")));
|
|
116
|
+
});
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
describe("Select · por cima do diálogo", () => {
|
|
120
|
+
it("dentro de role=dialog a lista vira fixed, ancorada no gatilho", async () => {
|
|
121
|
+
const { container } = render(
|
|
122
|
+
<div role="dialog" aria-label="Filtros" style={{ overflow: "clip" }}>
|
|
123
|
+
<Select ariaLabel="x" options={OPCOES} />
|
|
124
|
+
</div>,
|
|
125
|
+
);
|
|
126
|
+
fireEvent.click(screen.getByRole("combobox"));
|
|
127
|
+
const lista = container.querySelector(".umds-select__dropdown") as HTMLElement;
|
|
128
|
+
expect(container.querySelector(".umds-select--floating")).not.toBeNull();
|
|
129
|
+
expect(lista.style.position).toBe("fixed");
|
|
130
|
+
await waitFor(() => expect(lista.style.visibility).toBe("visible"));
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
it("fora de diálogo a lista continua posicionada pelo CSS (sem fixed)", () => {
|
|
134
|
+
const { container } = render(<Select ariaLabel="x" options={OPCOES} />);
|
|
135
|
+
fireEvent.click(screen.getByRole("combobox"));
|
|
136
|
+
const lista = container.querySelector(".umds-select__dropdown") as HTMLElement;
|
|
137
|
+
expect(container.querySelector(".umds-select--floating")).toBeNull();
|
|
138
|
+
expect(lista.style.position).toBe("");
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
it("aria-modal também conta como diálogo", () => {
|
|
142
|
+
const { container } = render(
|
|
143
|
+
<div aria-modal="true">
|
|
144
|
+
<Select ariaLabel="x" options={OPCOES} />
|
|
145
|
+
</div>,
|
|
146
|
+
);
|
|
147
|
+
fireEvent.click(screen.getByRole("combobox"));
|
|
148
|
+
expect(container.querySelector(".umds-select--floating")).not.toBeNull();
|
|
149
|
+
});
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
describe("Select · placement auto mede o ancestral que rola", () => {
|
|
153
|
+
it("abre para cima e limita a altura da lista ao espaço do ancestral", () => {
|
|
154
|
+
vi.spyOn(HTMLElement.prototype, "getBoundingClientRect").mockImplementation(function (this: HTMLElement) {
|
|
155
|
+
const rolante = this.getAttribute("data-rolante") !== null;
|
|
156
|
+
const [topo, base] = rolante ? [100, 300] : [200, 244];
|
|
157
|
+
return { top: topo, bottom: base, left: 0, right: 0, width: 0, height: base - topo, x: 0, y: topo, toJSON() {} } as any;
|
|
158
|
+
});
|
|
159
|
+
Object.defineProperty(window, "innerHeight", { value: 900, configurable: true });
|
|
160
|
+
const { container } = render(
|
|
161
|
+
<div data-rolante style={{ overflowY: "auto" }}>
|
|
162
|
+
<Select ariaLabel="x" options={OPCOES} placement="auto" />
|
|
163
|
+
</div>,
|
|
164
|
+
);
|
|
165
|
+
fireEvent.click(screen.getByRole("combobox"));
|
|
166
|
+
expect(container.querySelector(".umds-select--placement-top")).not.toBeNull();
|
|
167
|
+
expect((container.querySelector(".umds-select__dropdown") as HTMLElement).style.maxHeight).toBe("96px");
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
it("sem ancestral que corta, só a janela conta e a lista não ganha teto", () => {
|
|
171
|
+
vi.spyOn(HTMLElement.prototype, "getBoundingClientRect").mockImplementation(
|
|
172
|
+
() => ({ top: 20, bottom: 64, left: 0, right: 0, width: 0, height: 44, x: 0, y: 20, toJSON() {} }) as any,
|
|
173
|
+
);
|
|
174
|
+
Object.defineProperty(window, "innerHeight", { value: 900, configurable: true });
|
|
175
|
+
const { container } = render(<Select ariaLabel="x" options={OPCOES} placement="auto" />);
|
|
176
|
+
fireEvent.click(screen.getByRole("combobox"));
|
|
177
|
+
expect(container.querySelector(".umds-select--placement-top")).toBeNull();
|
|
178
|
+
expect((container.querySelector(".umds-select__dropdown") as HTMLElement).style.maxHeight).toBe("");
|
|
179
|
+
});
|
|
180
|
+
});
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
|
+
import { fireEvent, render, screen } from "@testing-library/react";
|
|
3
|
+
import Select from "../components/Select/Select";
|
|
4
|
+
|
|
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
|
+
|
|
11
|
+
describe("Select filtro · tamanho e fundo", () => {
|
|
12
|
+
it("as variantes de filtro nascem no tamanho sm; size explícito manda; o padrão segue md", () => {
|
|
13
|
+
const { container, rerender } = render(<Select ariaLabel="x" options={MARCADORES} variant="filter" />);
|
|
14
|
+
const raiz = () => container.firstElementChild as HTMLElement;
|
|
15
|
+
expect(raiz()).toHaveClass("umds-select--sm");
|
|
16
|
+
rerender(<Select ariaLabel="x" options={MARCADORES} variant="search" />);
|
|
17
|
+
expect(raiz()).toHaveClass("umds-select--sm");
|
|
18
|
+
rerender(<Select ariaLabel="x" options={MARCADORES} variant="combo" />);
|
|
19
|
+
expect(raiz()).toHaveClass("umds-select--sm");
|
|
20
|
+
rerender(<Select ariaLabel="x" options={MARCADORES} variant="filter" size="md" />);
|
|
21
|
+
expect(raiz()).toHaveClass("umds-select--md");
|
|
22
|
+
rerender(<Select ariaLabel="x" options={MARCADORES} />);
|
|
23
|
+
expect(raiz()).toHaveClass("umds-select--md");
|
|
24
|
+
expect(raiz()).not.toHaveClass("umds-select--sm");
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
it("o azul-claro do gatilho só vem com valor escolhido (--has-value); sem valor, não", () => {
|
|
28
|
+
const { container, rerender } = render(<Select ariaLabel="x" options={MARCADORES} variant="filter" placeholder="Marcadores" />);
|
|
29
|
+
const raiz = () => container.firstElementChild as HTMLElement;
|
|
30
|
+
expect(raiz()).not.toHaveClass("umds-select--has-value");
|
|
31
|
+
rerender(<Select ariaLabel="x" options={MARCADORES} variant="filter" placeholder="Marcadores" value="urgente" />);
|
|
32
|
+
expect(raiz()).toHaveClass("umds-select--has-value");
|
|
33
|
+
rerender(<Select ariaLabel="x" options={MARCADORES} placeholder="Marcadores" value="urgente" />);
|
|
34
|
+
expect(raiz()).not.toHaveClass("umds-select--has-value");
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
it("o valor vazio do emptyOptionLabel volta ao estado sem valor", () => {
|
|
38
|
+
const { container } = render(
|
|
39
|
+
<Select ariaLabel="x" options={MARCADORES} variant="filter" placeholder="Marcadores" emptyOptionLabel="Todos" value="" />,
|
|
40
|
+
);
|
|
41
|
+
expect(container.firstElementChild).not.toHaveClass("umds-select--has-value");
|
|
42
|
+
});
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
describe("Select · cor por opção", () => {
|
|
46
|
+
it("a lista mostra uma amostra por opção com color; sem color, não", () => {
|
|
47
|
+
const { container } = render(<Select ariaLabel="x" options={MARCADORES} variant="filter" />);
|
|
48
|
+
fireEvent.click(screen.getByRole("combobox"));
|
|
49
|
+
const opcoes = [...container.querySelectorAll('[role="option"]')];
|
|
50
|
+
expect(opcoes[0].querySelector(".umds-select__swatch")).toHaveAttribute("aria-hidden", "true");
|
|
51
|
+
expect((opcoes[0].querySelector(".umds-select__swatch") as HTMLElement).style.background).toContain("--umds-semantic-color-feedback-negative-pure");
|
|
52
|
+
expect(opcoes[1].querySelector(".umds-select__swatch")).not.toBeNull();
|
|
53
|
+
expect(opcoes[2].querySelector(".umds-select__swatch")).toBeNull();
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
it("o gatilho ganha a cor da opção escolhida (seleção única)", () => {
|
|
57
|
+
const { container } = render(<Select ariaLabel="x" options={MARCADORES} variant="filter" placeholder="Marcadores" value="revisao" />);
|
|
58
|
+
const amostra = container.querySelector(".umds-select__trigger .umds-select__swatch") as HTMLElement;
|
|
59
|
+
expect(amostra.style.background).toContain("--umds-semantic-color-primary-pure");
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
it("opção escolhida sem color e estado sem valor: o gatilho não tem amostra", () => {
|
|
63
|
+
const { container, rerender } = render(<Select ariaLabel="x" options={MARCADORES} placeholder="Marcadores" value="nenhum" />);
|
|
64
|
+
expect(container.querySelector(".umds-select__trigger .umds-select__swatch")).toBeNull();
|
|
65
|
+
rerender(<Select ariaLabel="x" options={MARCADORES} placeholder="Marcadores" />);
|
|
66
|
+
expect(container.querySelector(".umds-select__trigger .umds-select__swatch")).toBeNull();
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
it("triggerSwatch explícito manda sobre a cor da opção", () => {
|
|
70
|
+
const { container } = render(
|
|
71
|
+
<Select ariaLabel="x" options={MARCADORES} value="urgente" triggerSwatch="var(--umds-semantic-color-feedback-positive-pure)" />,
|
|
72
|
+
);
|
|
73
|
+
const amostras = container.querySelectorAll(".umds-select__trigger .umds-select__swatch");
|
|
74
|
+
expect(amostras).toHaveLength(1);
|
|
75
|
+
expect((amostras[0] as HTMLElement).style.background).toContain("--umds-semantic-color-feedback-positive-pure");
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
it("na seleção múltipla o gatilho não pinta amostra (são várias), mas a lista mostra as cores", () => {
|
|
79
|
+
const { container } = render(<Select ariaLabel="x" options={MARCADORES} multiple value={["urgente", "revisao"]} />);
|
|
80
|
+
expect(container.querySelector(".umds-select__trigger .umds-select__swatch")).toBeNull();
|
|
81
|
+
fireEvent.click(screen.getByRole("combobox"));
|
|
82
|
+
expect(container.querySelectorAll('[role="option"] .umds-select__swatch')).toHaveLength(2);
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
it("a cor não vira texto nem entra no nome acessível da opção", () => {
|
|
86
|
+
render(<Select ariaLabel="x" options={MARCADORES} />);
|
|
87
|
+
fireEvent.click(screen.getByRole("combobox"));
|
|
88
|
+
expect(screen.getByRole("option", { name: "Urgente" })).toBeInTheDocument();
|
|
89
|
+
});
|
|
90
|
+
});
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
|
+
import { fireEvent, render, screen } from "@testing-library/react";
|
|
3
|
+
import Select from "../components/Select/Select";
|
|
4
|
+
|
|
5
|
+
const OPCOES = [
|
|
6
|
+
{ label: "Urgente", value: "urgente", etiqueta: "Prazo hoje" },
|
|
7
|
+
{ label: "Rotina", value: "rotina", etiqueta: "Sem prazo" },
|
|
8
|
+
];
|
|
9
|
+
const item = ({ optionData }: any) => (
|
|
10
|
+
<span data-testid="item">
|
|
11
|
+
<b>{optionData.label}</b> <i>{optionData.etiqueta}</i>
|
|
12
|
+
</span>
|
|
13
|
+
);
|
|
14
|
+
|
|
15
|
+
describe("Select · item com escopo da opção", () => {
|
|
16
|
+
it("a lista mostra o item de cada opção, recebendo a opção (optionData e o apelido option)", () => {
|
|
17
|
+
const vistos: any[] = [];
|
|
18
|
+
render(
|
|
19
|
+
<Select
|
|
20
|
+
ariaLabel="Prioridade"
|
|
21
|
+
options={OPCOES}
|
|
22
|
+
item={(escopo: any) => {
|
|
23
|
+
vistos.push(escopo);
|
|
24
|
+
return <span data-testid="item">{escopo.optionData.label}</span>;
|
|
25
|
+
}}
|
|
26
|
+
/>,
|
|
27
|
+
);
|
|
28
|
+
fireEvent.click(screen.getByRole("combobox"));
|
|
29
|
+
expect(screen.getAllByTestId("item").map((n) => n.textContent)).toEqual(["Urgente", "Rotina"]);
|
|
30
|
+
expect(vistos[0].optionData).toBe(OPCOES[0]);
|
|
31
|
+
expect(vistos[0].option).toBe(OPCOES[0]);
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
it("o gatilho com a opção escolhida mostra o conteúdo do item, não o texto", () => {
|
|
35
|
+
render(<Select ariaLabel="Prioridade" options={OPCOES} value="urgente" item={item} />);
|
|
36
|
+
const gatilho = screen.getByRole("combobox");
|
|
37
|
+
expect(gatilho.querySelector(".umds-select__trigger-item")).not.toBeNull();
|
|
38
|
+
expect(gatilho).toHaveTextContent("Urgente");
|
|
39
|
+
expect(gatilho).toHaveTextContent("Prazo hoje");
|
|
40
|
+
expect(gatilho.querySelector(".umds-select__placeholder")).toBeNull();
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
it("sem valor o gatilho mostra o placeholder; escolher na lista passa o item para o gatilho", () => {
|
|
44
|
+
function App() {
|
|
45
|
+
return <Select ariaLabel="Prioridade" placeholder="Escolha" options={OPCOES} item={item} />;
|
|
46
|
+
}
|
|
47
|
+
render(<App />);
|
|
48
|
+
const gatilho = screen.getByRole("combobox");
|
|
49
|
+
expect(gatilho).toHaveTextContent("Escolha");
|
|
50
|
+
expect(gatilho.querySelector(".umds-select__trigger-item")).toBeNull();
|
|
51
|
+
fireEvent.click(gatilho);
|
|
52
|
+
fireEvent.click(screen.getAllByRole("option")[1]);
|
|
53
|
+
expect(screen.getByRole("combobox").querySelector(".umds-select__trigger-item")).toHaveTextContent("Rotina");
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
it("seleção múltipla segue com o texto no gatilho", () => {
|
|
57
|
+
render(<Select ariaLabel="Prioridade" multiple options={OPCOES} value={["urgente"]} item={item} />);
|
|
58
|
+
expect(screen.getByRole("combobox").querySelector(".umds-select__trigger-item")).toBeNull();
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
it("sem item nada muda: o gatilho mostra o rótulo; item como nó solto (legado) não vai ao gatilho", () => {
|
|
62
|
+
const { rerender } = render(<Select ariaLabel="Prioridade" options={OPCOES} value="urgente" />);
|
|
63
|
+
expect(screen.getByRole("combobox")).toHaveTextContent("Urgente");
|
|
64
|
+
expect(screen.getByRole("combobox").querySelector(".umds-select__trigger-item")).toBeNull();
|
|
65
|
+
rerender(<Select ariaLabel="Prioridade" options={OPCOES} value="urgente" item={<em>fixo</em>} />);
|
|
66
|
+
expect(screen.getByRole("combobox").querySelector(".umds-select__trigger-item")).toBeNull();
|
|
67
|
+
expect(screen.getByRole("combobox")).toHaveTextContent("Urgente");
|
|
68
|
+
});
|
|
69
|
+
});
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import { afterEach, describe, expect, it, vi } from "vitest";
|
|
2
|
+
import { fireEvent, render, screen, waitFor } from "@testing-library/react";
|
|
3
|
+
import Select from "../components/Select/Select";
|
|
4
|
+
import { lerArquivo } from "./lerArquivo";
|
|
5
|
+
|
|
6
|
+
const cssSelect = await lerArquivo("../core/src/components/Select/Select.css");
|
|
7
|
+
|
|
8
|
+
const OPCOES = [
|
|
9
|
+
{ label: "Urgente", value: "urgente" },
|
|
10
|
+
{ label: "Revisão", value: "revisao" },
|
|
11
|
+
];
|
|
12
|
+
|
|
13
|
+
afterEach(() => vi.restoreAllMocks());
|
|
14
|
+
|
|
15
|
+
const lista = (container: HTMLElement) => container.querySelector(".umds-select__dropdown") as HTMLElement;
|
|
16
|
+
|
|
17
|
+
/** jsdom não tem layout: só a lista "mede" o que o teste mandar. */
|
|
18
|
+
function medirLista(direita: number, larguraDaJanela: number) {
|
|
19
|
+
vi.spyOn(HTMLElement.prototype, "getBoundingClientRect").mockImplementation(function (this: HTMLElement) {
|
|
20
|
+
const eLista = this.classList.contains("umds-select__dropdown");
|
|
21
|
+
return { top: 0, bottom: 0, left: 0, right: eLista ? direita : 0, width: 0, height: 0, x: 0, y: 0, toJSON() {} } as any;
|
|
22
|
+
});
|
|
23
|
+
Object.defineProperty(window, "innerWidth", { value: larguraDaJanela, configurable: true });
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
describe("Select filtro · listMinWidth", () => {
|
|
27
|
+
it("um número vira px e a lista nunca fica mais estreita que o gatilho", () => {
|
|
28
|
+
const { container } = render(<Select ariaLabel="x" options={OPCOES} variant="filter" listMinWidth={220} />);
|
|
29
|
+
fireEvent.click(screen.getByRole("combobox"));
|
|
30
|
+
expect(lista(container).style.minWidth).toBe("max(100%, 220px)");
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
it("uma medida CSS vale como veio", () => {
|
|
34
|
+
const { container } = render(<Select ariaLabel="x" options={OPCOES} variant="filter" listMinWidth="18rem" />);
|
|
35
|
+
fireEvent.click(screen.getByRole("combobox"));
|
|
36
|
+
expect(lista(container).style.minWidth).toBe("max(100%, 18rem)");
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
it("0 é um valor (sem mínimo além do gatilho), não ausência", () => {
|
|
40
|
+
const { container } = render(<Select ariaLabel="x" options={OPCOES} variant="filter" listMinWidth={0} />);
|
|
41
|
+
fireEvent.click(screen.getByRole("combobox"));
|
|
42
|
+
expect(lista(container).style.minWidth).toBe("max(100%, 0px)");
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
it("sem a prop o mínimo é o do CSS (240px), sem estilo inline", () => {
|
|
46
|
+
const { container } = render(<Select ariaLabel="x" options={OPCOES} variant="filter" />);
|
|
47
|
+
fireEvent.click(screen.getByRole("combobox"));
|
|
48
|
+
expect(lista(container).style.minWidth).toBe("");
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
it("o Select padrão ignora a prop (a lista é a largura do campo)", () => {
|
|
52
|
+
const { container } = render(<Select ariaLabel="x" options={OPCOES} listMinWidth={220} />);
|
|
53
|
+
fireEvent.click(screen.getByRole("combobox"));
|
|
54
|
+
expect(lista(container).style.minWidth).toBe("");
|
|
55
|
+
});
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
describe("Select filtro · nunca passa da borda da janela", () => {
|
|
59
|
+
it("a lista que estoura a borda direita se alinha ao fim do gatilho", async () => {
|
|
60
|
+
medirLista(1457, 1440);
|
|
61
|
+
const { container } = render(<Select ariaLabel="x" options={OPCOES} variant="filter" />);
|
|
62
|
+
fireEvent.click(screen.getByRole("combobox"));
|
|
63
|
+
await waitFor(() => expect(container.querySelector(".umds-select--list-end")).not.toBeNull());
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
it("a lista que cabe fica onde está", async () => {
|
|
67
|
+
medirLista(900, 1440);
|
|
68
|
+
const { container } = render(<Select ariaLabel="x" options={OPCOES} variant="filter" />);
|
|
69
|
+
fireEvent.click(screen.getByRole("combobox"));
|
|
70
|
+
await waitFor(() => expect(lista(container)).not.toBeNull());
|
|
71
|
+
expect(container.querySelector(".umds-select--list-end")).toBeNull();
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
it("deixa 8px de respiro: encostada na borda ainda alinha", async () => {
|
|
75
|
+
medirLista(1436, 1440);
|
|
76
|
+
const { container } = render(<Select ariaLabel="x" options={OPCOES} variant="filter" />);
|
|
77
|
+
fireEvent.click(screen.getByRole("combobox"));
|
|
78
|
+
await waitFor(() => expect(container.querySelector(".umds-select--list-end")).not.toBeNull());
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
it("fechar desliga o alinhamento", async () => {
|
|
82
|
+
medirLista(1457, 1440);
|
|
83
|
+
const { container } = render(<Select ariaLabel="x" options={OPCOES} variant="filter" />);
|
|
84
|
+
fireEvent.click(screen.getByRole("combobox"));
|
|
85
|
+
await waitFor(() => expect(container.querySelector(".umds-select--list-end")).not.toBeNull());
|
|
86
|
+
fireEvent.click(screen.getByRole("combobox"));
|
|
87
|
+
await waitFor(() => expect(container.querySelector(".umds-select--list-end")).toBeNull());
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
it("o Select padrão (não filtro) não é movido", async () => {
|
|
91
|
+
medirLista(1457, 1440);
|
|
92
|
+
const { container } = render(<Select ariaLabel="x" options={OPCOES} />);
|
|
93
|
+
fireEvent.click(screen.getByRole("combobox"));
|
|
94
|
+
await waitFor(() => expect(lista(container)).not.toBeNull());
|
|
95
|
+
expect(container.querySelector(".umds-select--list-end")).toBeNull();
|
|
96
|
+
});
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
describe("Select filtro · CSS", () => {
|
|
100
|
+
const css = cssSelect.replace(/\r\n/g, "\n");
|
|
101
|
+
const bloco = (seletor: string) => {
|
|
102
|
+
const inicio = css.indexOf(seletor + " {");
|
|
103
|
+
return css.slice(inicio, css.indexOf("}", inicio));
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
it("o wrapper do filtro é fit-content (o auto o esticava até o pai e a lista herdava essa largura)", () => {
|
|
107
|
+
expect(bloco(".umds-select--filter")).toMatch(/width:\s*fit-content/);
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
it("a busca da lista fica fora da conta da largura natural", () => {
|
|
111
|
+
expect(bloco(".umds-select--filter .umds-select__search-container")).toMatch(/contain:\s*inline-size/);
|
|
112
|
+
expect(bloco(".umds-select__search-input")).toMatch(/min-width:\s*0/);
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
it("o alinhamento ao fim ancora a lista pela direita", () => {
|
|
116
|
+
const b = bloco(".umds-select--filter.umds-select--list-end .umds-select__dropdown");
|
|
117
|
+
expect(b).toMatch(/left:\s*auto/);
|
|
118
|
+
expect(b).toMatch(/right:\s*0/);
|
|
119
|
+
});
|
|
120
|
+
});
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
|
+
import { render } from "@testing-library/react";
|
|
3
|
+
import StatCard from "../components/StatCard/StatCard";
|
|
4
|
+
|
|
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(
|
|
8
|
+
<StatCard value="22,31%" label="Eficiência" description="Meu Setor" secondaryValue="14,11%" secondaryLabel="Geral" labelPosition="top" />,
|
|
9
|
+
);
|
|
10
|
+
const filhos = [...(container.firstElementChild as HTMLElement).children].map((e) => e.className);
|
|
11
|
+
expect(filhos[filhos.length - 1]).toBe("umds-stat-card__secundaria");
|
|
12
|
+
const secundaria = container.querySelector(".umds-stat-card__secundaria") as HTMLElement;
|
|
13
|
+
expect(secundaria.querySelector(".umds-stat-card__valor-secundario")).toHaveTextContent("14,11%");
|
|
14
|
+
expect(secundaria.querySelector(".umds-stat-card__rotulo-secundario")).toHaveTextContent("Geral");
|
|
15
|
+
expect(container.firstElementChild).toHaveClass("umds-stat-card--com-secundaria");
|
|
16
|
+
const texto = (container.firstElementChild as HTMLElement).textContent as string;
|
|
17
|
+
expect(texto.indexOf("22,31%")).toBeLessThan(texto.indexOf("Eficiência"));
|
|
18
|
+
expect(texto.indexOf("Eficiência")).toBeLessThan(texto.indexOf("14,11%"));
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
it("secondaryValue 0 aparece; vazio e ausente não", () => {
|
|
22
|
+
const { container, rerender } = render(<StatCard value="5" label="x" secondaryValue={0} />);
|
|
23
|
+
expect(container.querySelector(".umds-stat-card__valor-secundario")).toHaveTextContent("0");
|
|
24
|
+
rerender(<StatCard value="5" label="x" secondaryValue="" />);
|
|
25
|
+
expect(container.querySelector(".umds-stat-card__secundaria")).toBeNull();
|
|
26
|
+
rerender(<StatCard value="5" label="x" />);
|
|
27
|
+
expect(container.querySelector(".umds-stat-card__secundaria")).toBeNull();
|
|
28
|
+
expect(container.firstElementChild).not.toHaveClass("umds-stat-card--com-secundaria");
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
it("secondaryValue sem secondaryLabel não desenha o rótulo", () => {
|
|
32
|
+
const { container } = render(<StatCard value="5" label="x" secondaryValue="9" />);
|
|
33
|
+
expect(container.querySelector(".umds-stat-card__rotulo-secundario")).toBeNull();
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
it("valueTone escreve a classe do tom; default e ausente não", () => {
|
|
37
|
+
const { container, rerender } = render(<StatCard value="5" label="x" valueTone="negative" />);
|
|
38
|
+
expect(container.firstElementChild).toHaveClass("umds-stat-card--valor-negative");
|
|
39
|
+
rerender(<StatCard value="5" label="x" valueTone="primary" />);
|
|
40
|
+
expect(container.firstElementChild).toHaveClass("umds-stat-card--valor-primary");
|
|
41
|
+
rerender(<StatCard value="5" label="x" valueTone="default" />);
|
|
42
|
+
expect(container.firstElementChild!.className).not.toMatch(/valor-/);
|
|
43
|
+
rerender(<StatCard value="5" label="x" />);
|
|
44
|
+
expect(container.firstElementChild!.className).not.toMatch(/valor-/);
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
it("valueTone não mexe na variant do ícone", () => {
|
|
48
|
+
const { container } = render(<StatCard value="5" label="x" variant="positive" valueTone="negative" />);
|
|
49
|
+
expect(container.firstElementChild).toHaveClass("umds-stat-card--positive", "umds-stat-card--valor-negative");
|
|
50
|
+
});
|
|
51
|
+
});
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
|
+
import { render } from "@testing-library/react";
|
|
3
|
+
import StatCard from "../components/StatCard/StatCard";
|
|
4
|
+
import { lerArquivo } from "./lerArquivo";
|
|
5
|
+
|
|
6
|
+
const cssStatCard = await lerArquivo("../core/src/components/StatCard/StatCard.css");
|
|
7
|
+
|
|
8
|
+
const css = cssStatCard.replace(/\r\n/g, "\n");
|
|
9
|
+
const bloco = (seletor: string) => {
|
|
10
|
+
const inicio = css.indexOf(seletor + " {");
|
|
11
|
+
return css.slice(inicio, css.indexOf("}", inicio));
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
describe("StatCard · size", () => {
|
|
15
|
+
it("sm escreve a classe; sem a prop e com md o cartão é o de antes", () => {
|
|
16
|
+
const { container } = render(
|
|
17
|
+
<>
|
|
18
|
+
<StatCard value={44} label="Não lidos" size="sm" />
|
|
19
|
+
<StatCard value={44} label="Não lidos" />
|
|
20
|
+
<StatCard value={44} label="Não lidos" size="md" />
|
|
21
|
+
</>,
|
|
22
|
+
);
|
|
23
|
+
expect(container.children[0]).toHaveClass("umds-stat-card--sm");
|
|
24
|
+
expect(container.children[1]).not.toHaveClass("umds-stat-card--sm");
|
|
25
|
+
expect(container.children[2]).not.toHaveClass("umds-stat-card--sm");
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
it("o número do sm é 18px/800, e a regra vence o 32/800 do rótulo no topo", () => {
|
|
29
|
+
const regra = bloco(".umds-stat-card.umds-stat-card--sm .umds-stat-card__valor");
|
|
30
|
+
expect(regra).toMatch(/font-size:\s*1\.125rem/);
|
|
31
|
+
expect(regra).toMatch(/font-weight:\s*var\(--umds-primitive-font-weight-extrabold\)/);
|
|
32
|
+
const { container } = render(<StatCard value={44} label="Não lidos" size="sm" labelPosition="top" />);
|
|
33
|
+
expect(container.firstElementChild).toHaveClass("umds-stat-card--sm", "umds-stat-card--rotulo-topo");
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
it("o número continua antes do rótulo no HTML", () => {
|
|
37
|
+
const { container } = render(<StatCard value={44} label="Não lidos" size="sm" />);
|
|
38
|
+
const valor = container.querySelector(".umds-stat-card__valor") as HTMLElement;
|
|
39
|
+
const rotulo = container.querySelector(".umds-stat-card__rotulo") as HTMLElement;
|
|
40
|
+
expect(valor.compareDocumentPosition(rotulo) & Node.DOCUMENT_POSITION_FOLLOWING).toBeTruthy();
|
|
41
|
+
});
|
|
42
|
+
});
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
|
+
import Tabs from "../components/Tabs/Tabs";
|
|
3
|
+
import Tab from "../components/Tabs/Tab";
|
|
4
|
+
import { render } from "@testing-library/react";
|
|
5
|
+
import { lerArquivo } from "./lerArquivo";
|
|
6
|
+
|
|
7
|
+
const cssTabs = await lerArquivo("../core/src/components/Tabs/Tabs.css");
|
|
8
|
+
|
|
9
|
+
const CSS: Record<string, string> = { Tabs: cssTabs };
|
|
10
|
+
const css = (componente: string) => CSS[componente].replace(/\r\n/g, "\n");
|
|
11
|
+
const bloco = (texto: string, seletor: string) => {
|
|
12
|
+
const inicio = texto.indexOf(seletor + " {");
|
|
13
|
+
expect(inicio, seletor).toBeGreaterThanOrEqual(0);
|
|
14
|
+
return texto.slice(inicio, texto.indexOf("}", inicio));
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
describe("Tabs · density", () => {
|
|
18
|
+
it("compact escreve a classe na raiz; sem a prop e com default, não", () => {
|
|
19
|
+
const { container } = render(
|
|
20
|
+
<>
|
|
21
|
+
<Tabs value="0" density="compact"><Tab label="A" index="0" /></Tabs>
|
|
22
|
+
<Tabs value="0"><Tab label="B" index="0" /></Tabs>
|
|
23
|
+
<Tabs value="0" density="default"><Tab label="C" index="0" /></Tabs>
|
|
24
|
+
</>,
|
|
25
|
+
);
|
|
26
|
+
expect(container.children[0]).toHaveClass("umds-tabs--compact");
|
|
27
|
+
expect(container.children[1]).not.toHaveClass("umds-tabs--compact");
|
|
28
|
+
expect(container.children[2]).not.toHaveClass("umds-tabs--compact");
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
it("CSS: a compacta tem altura mínima de 40px (degrau sm) e padding vertical de 8px; o padrão segue em 48px", () => {
|
|
32
|
+
const t = css("Tabs");
|
|
33
|
+
const compacta = bloco(t, ".umds-tabs--compact .umds-tabs__tab");
|
|
34
|
+
expect(compacta).toMatch(/min-height:\s*var\(--umds-primitive-spacing-sm\)/);
|
|
35
|
+
expect(compacta).toMatch(/padding-block:\s*var\(--umds-primitive-spacing-nano\)/);
|
|
36
|
+
expect(bloco(t, ".umds-tabs__tab")).toMatch(/min-height:\s*48px/);
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
it("a pílula do contador é cinza na aba inativa e azul só na ativa (nas duas densidades)", () => {
|
|
40
|
+
const t = css("Tabs");
|
|
41
|
+
expect(bloco(t, ".umds-tabs__count")).toMatch(/background-color:\s*var\(--umds-semantic-color-neutral-light-medium\)/);
|
|
42
|
+
expect(bloco(t, ".umds-tabs__tab--selected .umds-tabs__count")).toMatch(/background-color:\s*var\(--umds-semantic-color-primary-pure\)/);
|
|
43
|
+
expect(t).not.toMatch(/--compact[^{]*\.umds-tabs__count/);
|
|
44
|
+
});
|
|
45
|
+
});
|