@1doc/1ds-react 2.10.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 +219 -0
- package/dist/components/Accordion/Accordion.d.ts +6 -0
- package/dist/components/Accordion/Accordion.js +17 -5
- package/dist/components/Badge/Badge.css +13 -4
- package/dist/components/Badge/Badge.d.ts +9 -2
- package/dist/components/Badge/Badge.js +3 -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 +3 -0
- package/dist/components/Calendar/Calendar.js +6 -1
- package/dist/components/Coachmark/Coachmark.d.ts +2 -1
- package/dist/components/Coachmark/Coachmark.js +6 -1
- package/dist/components/DataTable/DataTable.css +42 -0
- package/dist/components/DataTable/DataTable.d.ts +9 -2
- package/dist/components/DataTable/DataTable.js +15 -0
- package/dist/components/Input/Input.css +9 -0
- package/dist/components/Input/Input.d.ts +3 -0
- package/dist/components/Input/Input.js +1 -0
- 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/SegmentedControl/SegmentedControl.css +46 -0
- package/dist/components/SegmentedControl/SegmentedControl.d.ts +3 -0
- package/dist/components/SegmentedControl/SegmentedControl.js +1 -0
- package/dist/components/Select/Select.css +28 -2
- package/dist/components/Select/Select.d.ts +7 -0
- package/dist/components/Select/Select.js +55 -9
- package/dist/components/StatCard/StatCard.css +8 -0
- package/dist/components/StatCard/StatCard.d.ts +3 -0
- package/dist/components/StatCard/StatCard.js +1 -0
- 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/teste/AccordionControlado.test.d.ts +1 -0
- package/dist/teste/AccordionControlado.test.js +73 -0
- package/dist/teste/BadgeAttachedTomEPadding.test.d.ts +1 -0
- package/dist/teste/BadgeAttachedTomEPadding.test.js +43 -0
- package/dist/teste/ButtonDensidade.test.d.ts +1 -0
- package/dist/teste/ButtonDensidade.test.js +28 -0
- package/dist/teste/CalendarCompacto.test.d.ts +1 -0
- package/dist/teste/CalendarCompacto.test.js +29 -0
- package/dist/teste/CoachmarkUmPasso.test.d.ts +1 -0
- package/dist/teste/CoachmarkUmPasso.test.js +34 -0
- package/dist/teste/DataTableCompactaETom.test.d.ts +1 -0
- package/dist/teste/DataTableCompactaETom.test.js +69 -0
- package/dist/teste/InputGhost.test.d.ts +1 -0
- package/dist/teste/InputGhost.test.js +32 -0
- package/dist/teste/ModalProporcoes1Doc.test.d.ts +1 -0
- package/dist/teste/ModalProporcoes1Doc.test.js +32 -0
- package/dist/teste/SegmentedControlSuperficie.test.d.ts +1 -0
- package/dist/teste/SegmentedControlSuperficie.test.js +39 -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/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/lerArquivo.d.ts +1 -0
- package/dist/teste/lerArquivo.js +12 -0
- package/package.json +3 -3
- package/src/teste/AccordionControlado.test.tsx +87 -0
- package/src/teste/BadgeAttachedTomEPadding.test.tsx +60 -0
- package/src/teste/ButtonDensidade.test.tsx +40 -0
- package/src/teste/CalendarCompacto.test.tsx +37 -0
- package/src/teste/CoachmarkUmPasso.test.tsx +45 -0
- package/src/teste/DataTableCompactaETom.test.tsx +85 -0
- package/src/teste/InputGhost.test.tsx +42 -0
- package/src/teste/ModalProporcoes1Doc.test.tsx +36 -0
- package/src/teste/SegmentedControlSuperficie.test.tsx +52 -0
- package/src/teste/SelectItemComEscopo.test.tsx +69 -0
- package/src/teste/SelectListaFiltro.test.tsx +120 -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/lerArquivo.ts +13 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { describe, expect, it } from "vitest";
|
|
3
|
+
import Calendar from "../components/Calendar/Calendar";
|
|
4
|
+
import { render } from "@testing-library/react";
|
|
5
|
+
import { lerArquivo } from "./lerArquivo";
|
|
6
|
+
const cssCalendar = await lerArquivo("../core/src/components/Calendar/Calendar.css");
|
|
7
|
+
const CSS = { Calendar: cssCalendar };
|
|
8
|
+
const css = (componente) => CSS[componente].replace(/\r\n/g, "\n");
|
|
9
|
+
const bloco = (texto, seletor) => {
|
|
10
|
+
const inicio = texto.indexOf(seletor + " {");
|
|
11
|
+
expect(inicio, seletor).toBeGreaterThanOrEqual(0);
|
|
12
|
+
return texto.slice(inicio, texto.indexOf("}", inicio));
|
|
13
|
+
};
|
|
14
|
+
describe("Calendar · density compact", () => {
|
|
15
|
+
it("compact escreve a classe na raiz; sem a prop, não", () => {
|
|
16
|
+
const { container } = render(_jsxs(_Fragment, { children: [_jsx(Calendar, { today: "2026-05-15", defaultDate: "2026-05-15", density: "compact" }), _jsx(Calendar, { today: "2026-05-15", defaultDate: "2026-05-15" })] }));
|
|
17
|
+
expect(container.children[0]).toHaveClass("umds-calendar--compact", "umds-calendar--month");
|
|
18
|
+
expect(container.children[1]).not.toHaveClass("umds-calendar--compact");
|
|
19
|
+
});
|
|
20
|
+
it("CSS: evento de 20px (16 + 4), 4px de padding lateral e linha de 16px; o título só é cortado quando passa da largura", () => {
|
|
21
|
+
const t = css("Calendar");
|
|
22
|
+
const compacto = bloco(t, ".umds-calendar--compact .umds-calendar__event");
|
|
23
|
+
expect(compacto).toMatch(/min-height:\s*calc\(var\(--umds-primitive-spacing-xxxs\)\s*\+\s*var\(--umds-primitive-spacing-quarck\)\)/);
|
|
24
|
+
expect(compacto).toMatch(/padding:\s*var\(--umds-primitive-spacing-micro\)\s+var\(--umds-primitive-spacing-quarck\)/);
|
|
25
|
+
expect(compacto).toMatch(/line-height:\s*var\(--umds-primitive-spacing-xxxs\)/);
|
|
26
|
+
const titulo = bloco(t, ".umds-calendar__event-title");
|
|
27
|
+
expect(titulo).toMatch(/text-overflow:\s*ellipsis/);
|
|
28
|
+
});
|
|
29
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { describe, expect, it } from "vitest";
|
|
3
|
+
import { render, screen } from "@testing-library/react";
|
|
4
|
+
import Coachmark from "../components/Coachmark/Coachmark";
|
|
5
|
+
const UM = [{ target: "#alvo-a", title: "Novo: arrastar", content: "Arraste a linha para trocar a ordem." }];
|
|
6
|
+
const DOIS = [...UM, { title: "Pronto", content: "Sem alvo." }];
|
|
7
|
+
function Pagina({ passos, ...resto }) {
|
|
8
|
+
return (_jsxs("div", { children: [_jsx("button", { id: "alvo-a", children: "A" }), _jsx(Coachmark, { steps: passos, open: true, ...resto })] }));
|
|
9
|
+
}
|
|
10
|
+
describe("Coachmark · contador", () => {
|
|
11
|
+
it("com um passo só não há contador, nem visível nem na região aria-live", () => {
|
|
12
|
+
const { baseElement } = render(_jsx(Pagina, { passos: UM }));
|
|
13
|
+
expect(screen.queryByText("1 de 1")).toBeNull();
|
|
14
|
+
expect(baseElement.textContent).not.toContain("1 de 1");
|
|
15
|
+
expect(baseElement.querySelector(".umds-coachmark__sr")?.textContent).toBe("Novo: arrastar");
|
|
16
|
+
});
|
|
17
|
+
it("com um passo e modal={false} também não (a dica pontual)", () => {
|
|
18
|
+
const { baseElement } = render(_jsx(Pagina, { passos: UM, modal: false }));
|
|
19
|
+
expect(baseElement.textContent).not.toContain("1 de 1");
|
|
20
|
+
});
|
|
21
|
+
it("com dois passos o contador aparece e o leitor de tela o ouve", () => {
|
|
22
|
+
const { baseElement } = render(_jsx(Pagina, { passos: DOIS }));
|
|
23
|
+
expect(screen.getByText("1 de 2")).toBeInTheDocument();
|
|
24
|
+
expect(baseElement.querySelector(".umds-coachmark__sr")?.textContent).toBe("1 de 2: Novo: arrastar");
|
|
25
|
+
});
|
|
26
|
+
it("counterLabel segue valendo com mais de um passo", () => {
|
|
27
|
+
render(_jsx(Pagina, { passos: DOIS, counterLabel: "Step {current} of {total}" }));
|
|
28
|
+
expect(screen.getByText("Step 1 of 2")).toBeInTheDocument();
|
|
29
|
+
});
|
|
30
|
+
it("o botão do último passo continua sendo Concluir", () => {
|
|
31
|
+
render(_jsx(Pagina, { passos: UM }));
|
|
32
|
+
expect(screen.getByRole("button", { name: "Concluir" })).toBeInTheDocument();
|
|
33
|
+
});
|
|
34
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { describe, expect, it } from "vitest";
|
|
3
|
+
import { render } from "@testing-library/react";
|
|
4
|
+
import DataTable from "../components/DataTable/DataTable";
|
|
5
|
+
import { lerArquivo } from "./lerArquivo";
|
|
6
|
+
const cssDataTable = await lerArquivo("../core/src/components/DataTable/DataTable.css");
|
|
7
|
+
const COLUNAS = [
|
|
8
|
+
{ key: "nome", label: "Nome" },
|
|
9
|
+
{ key: "situacao", label: "Situação" },
|
|
10
|
+
];
|
|
11
|
+
const DADOS = [
|
|
12
|
+
{ nome: "Ana Souza", situacao: "Ativa", tom: "positive" },
|
|
13
|
+
{ nome: "Carlos Lima", situacao: "Bloqueado", tom: "negative" },
|
|
14
|
+
{ nome: "Marina Alves", situacao: "Licença", tom: "info" },
|
|
15
|
+
{ nome: "Rafael Pereira", situacao: "Desligado", tom: "muted" },
|
|
16
|
+
{ nome: "Beatriz Lima", situacao: "Ativa" },
|
|
17
|
+
];
|
|
18
|
+
const linhas = (c) => [...c.querySelectorAll("tbody tr")];
|
|
19
|
+
describe("DataTable · rowTone", () => {
|
|
20
|
+
it("o nome de um campo da linha traz o tom", () => {
|
|
21
|
+
const { container } = render(_jsx(DataTable, { columns: COLUNAS, data: DADOS, rowTone: "tom" }));
|
|
22
|
+
const l = linhas(container);
|
|
23
|
+
expect(l[0]).toHaveClass("umds-datatable__row--positive");
|
|
24
|
+
expect(l[1]).toHaveClass("umds-datatable__row--negative");
|
|
25
|
+
expect(l[2]).toHaveClass("umds-datatable__row--info");
|
|
26
|
+
expect(l[3]).toHaveClass("umds-datatable__row--muted");
|
|
27
|
+
expect(l[4].className).toBe("umds-datatable__row");
|
|
28
|
+
});
|
|
29
|
+
it("uma função (row, rowIndex) devolve o tom", () => {
|
|
30
|
+
const { container } = render(_jsx(DataTable, { columns: COLUNAS, data: DADOS, rowTone: (row, i) => (row.situacao === "Bloqueado" || i === 4 ? "negative" : undefined) }));
|
|
31
|
+
const l = linhas(container);
|
|
32
|
+
expect(l[1]).toHaveClass("umds-datatable__row--negative");
|
|
33
|
+
expect(l[4]).toHaveClass("umds-datatable__row--negative");
|
|
34
|
+
expect(l[0].className).toBe("umds-datatable__row");
|
|
35
|
+
});
|
|
36
|
+
it("tom desconhecido ou vazio não vira classe", () => {
|
|
37
|
+
const { container } = render(_jsx(DataTable, { columns: COLUNAS, data: [{ nome: "A", situacao: "x", tom: "rosa" }, { nome: "B", situacao: "y", tom: "" }], rowTone: "tom" }));
|
|
38
|
+
for (const l of linhas(container))
|
|
39
|
+
expect(l.className).toBe("umds-datatable__row");
|
|
40
|
+
});
|
|
41
|
+
it("sem rowTone nada muda", () => {
|
|
42
|
+
const { container } = render(_jsx(DataTable, { columns: COLUNAS, data: DADOS }));
|
|
43
|
+
for (const l of linhas(container))
|
|
44
|
+
expect(l.className).toBe("umds-datatable__row");
|
|
45
|
+
});
|
|
46
|
+
it("o tom convive com a linha selecionada e a zebra (as classes ficam; o CSS faz a selecionada vencer)", () => {
|
|
47
|
+
const { container } = render(_jsx(DataTable, { columns: COLUNAS, data: DADOS, rowTone: "tom", striped: true, rowKey: "nome", selectedRowKeys: ["Carlos Lima"] }));
|
|
48
|
+
const l = linhas(container);
|
|
49
|
+
expect(l[1]).toHaveClass("umds-datatable__row--negative", "umds-datatable__row--selected", "umds-datatable__row--striped");
|
|
50
|
+
});
|
|
51
|
+
});
|
|
52
|
+
describe("DataTable · compacta, 44px e CSS do tom", () => {
|
|
53
|
+
const css = cssDataTable.replace(/\r\n/g, "\n");
|
|
54
|
+
const bloco = (seletor) => {
|
|
55
|
+
const inicio = css.indexOf(seletor + " {");
|
|
56
|
+
return css.slice(inicio, css.indexOf("}", inicio));
|
|
57
|
+
};
|
|
58
|
+
it("a densidade compacta fixa cabeçalho e linha na altura de campo (44px); o documento fica de fora", () => {
|
|
59
|
+
expect(bloco(".umds-datatable--compact:not(.umds-datatable--document) .umds-datatable__td")).toMatch(/height:\s*var\(--umds-semantic-field-height\)/);
|
|
60
|
+
expect(css).toContain(".umds-datatable--compact:not(.umds-datatable--document) .umds-datatable__th,");
|
|
61
|
+
const { container } = render(_jsx(DataTable, { density: "compact", columns: COLUNAS, data: DADOS }));
|
|
62
|
+
expect(container.querySelector(".umds-datatable--compact")).not.toBeNull();
|
|
63
|
+
});
|
|
64
|
+
it("a linha selecionada vence o tom (o :not) e o tom vence a zebra", () => {
|
|
65
|
+
expect(css).toMatch(/\.umds-datatable__row--negative:not\(\.umds-datatable__row--selected\)/);
|
|
66
|
+
expect(css).toMatch(/\.umds-datatable__row--negative:not\(\.umds-datatable__row--selected\)\.umds-datatable__row--striped/);
|
|
67
|
+
expect(bloco(".umds-datatable__row--muted .umds-datatable__td")).toMatch(/neutral-dark-down/);
|
|
68
|
+
});
|
|
69
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { describe, expect, it } from "vitest";
|
|
3
|
+
import Input from "../components/Input/Input";
|
|
4
|
+
import { render } from "@testing-library/react";
|
|
5
|
+
import { lerArquivo } from "./lerArquivo";
|
|
6
|
+
const cssInput = await lerArquivo("../core/src/components/Input/Input.css");
|
|
7
|
+
const CSS = { Input: cssInput };
|
|
8
|
+
const css = (componente) => CSS[componente].replace(/\r\n/g, "\n");
|
|
9
|
+
const bloco = (texto, seletor) => {
|
|
10
|
+
const inicio = texto.indexOf(seletor + " {");
|
|
11
|
+
expect(inicio, seletor).toBeGreaterThanOrEqual(0);
|
|
12
|
+
return texto.slice(inicio, texto.indexOf("}", inicio));
|
|
13
|
+
};
|
|
14
|
+
describe("Input · variant ghost", () => {
|
|
15
|
+
it("ghost escreve a classe; sem a prop e com default, não", () => {
|
|
16
|
+
const { container } = render(_jsxs(_Fragment, { children: [_jsx(Input, { ariaLabel: "a", variant: "ghost" }), _jsx(Input, { ariaLabel: "b" }), _jsx(Input, { ariaLabel: "c", variant: "default" })] }));
|
|
17
|
+
expect(container.children[0]).toHaveClass("umds-input--ghost");
|
|
18
|
+
expect(container.children[1]).not.toHaveClass("umds-input--ghost");
|
|
19
|
+
expect(container.children[2]).not.toHaveClass("umds-input--ghost");
|
|
20
|
+
});
|
|
21
|
+
it("CSS: só o repouso muda (fundo claro, borda clara) e com baixa especificidade, para o hover e o foco vencerem", () => {
|
|
22
|
+
const t = css("Input");
|
|
23
|
+
const ghost = bloco(t, ".umds-input--ghost:where(:not(.umds-input--error):not(.umds-input--disabled):not(.umds-input--readonly)) .umds-input__container");
|
|
24
|
+
expect(ghost).toMatch(/background-color:\s*var\(--umds-semantic-color-background-light\)/);
|
|
25
|
+
expect(ghost).toMatch(/border-color:\s*var\(--umds-semantic-color-neutral-light-medium\)/);
|
|
26
|
+
expect(t.indexOf(".umds-input__container:focus-within:not(")).toBeGreaterThanOrEqual(0);
|
|
27
|
+
});
|
|
28
|
+
it("o foco, o erro e o desabilitado do campo ghost seguem as classes do padrão", () => {
|
|
29
|
+
const { container } = render(_jsx(Input, { ariaLabel: "d", variant: "ghost", errorMessage: "Obrigat\u00F3rio" }));
|
|
30
|
+
expect(container.firstElementChild).toHaveClass("umds-input--ghost", "umds-input--error");
|
|
31
|
+
});
|
|
32
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { describe, expect, it } from "vitest";
|
|
3
|
+
import Modal from "../components/Modal/Modal";
|
|
4
|
+
import { render, screen } from "@testing-library/react";
|
|
5
|
+
import { lerArquivo } from "./lerArquivo";
|
|
6
|
+
const cssModal = await lerArquivo("../core/src/components/Modal/Modal.css");
|
|
7
|
+
const CSS = { Modal: cssModal };
|
|
8
|
+
const css = (componente) => CSS[componente].replace(/\r\n/g, "\n");
|
|
9
|
+
const bloco = (texto, seletor) => {
|
|
10
|
+
const inicio = texto.indexOf(seletor + " {");
|
|
11
|
+
expect(inicio, seletor).toBeGreaterThanOrEqual(0);
|
|
12
|
+
return texto.slice(inicio, texto.indexOf("}", inicio));
|
|
13
|
+
};
|
|
14
|
+
describe("Modal · density 1doc", () => {
|
|
15
|
+
it("escreve a classe e convive com variant primary; sem a prop, não", () => {
|
|
16
|
+
render(_jsx(Modal, { open: true, inline: true, density: "1doc", variant: "primary", title: "Resolver tarefa" }));
|
|
17
|
+
expect(screen.getByRole("dialog", { name: "Resolver tarefa" })).toHaveClass("umds-modal--1doc", "umds-modal--primary", "umds-modal--base");
|
|
18
|
+
});
|
|
19
|
+
it("sem density o modal é o de antes", () => {
|
|
20
|
+
render(_jsx(Modal, { open: true, inline: true, title: "Padr\u00E3o" }));
|
|
21
|
+
expect(screen.getByRole("dialog", { name: "Padrão" })).not.toHaveClass("umds-modal--1doc");
|
|
22
|
+
});
|
|
23
|
+
it("CSS: cabeçalho de 67px, rodapé de 65px (padding 12px 24px) e raio de 12px; o padrão (8px) não muda", () => {
|
|
24
|
+
const t = css("Modal");
|
|
25
|
+
expect(bloco(t, ".umds-modal--1doc.umds-modal--base .umds-modal__header")).toMatch(/min-height:\s*67px/);
|
|
26
|
+
const rodape = bloco(t, ".umds-modal--1doc.umds-modal--base .umds-modal__footer");
|
|
27
|
+
expect(rodape).toMatch(/min-height:\s*65px/);
|
|
28
|
+
expect(rodape).toMatch(/padding:\s*var\(--umds-primitive-spacing-mini\)\s+var\(--umds-primitive-spacing-xxs\)/);
|
|
29
|
+
expect(t).toMatch(/\.umds-modal--1doc:not\(\.umds-modal--fullscreen\):not\(\.umds-modal--janela-fullscreen\):not\(\.umds-modal--sheet\) \{\n(?:\s*\/\*.*\*\/\n)?\s*border-radius:\s*12px/);
|
|
30
|
+
expect(bloco(t, ".umds-modal")).toMatch(/border-radius:\s*var\(--umds-primitive-border-radius-sm\)/);
|
|
31
|
+
});
|
|
32
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { describe, expect, it } from "vitest";
|
|
3
|
+
import SegmentedControl from "../components/SegmentedControl/SegmentedControl";
|
|
4
|
+
import { render } from "@testing-library/react";
|
|
5
|
+
import { lerArquivo } from "./lerArquivo";
|
|
6
|
+
const cssSegmentedControl = await lerArquivo("../core/src/components/SegmentedControl/SegmentedControl.css");
|
|
7
|
+
const CSS = { SegmentedControl: cssSegmentedControl };
|
|
8
|
+
const css = (componente) => CSS[componente].replace(/\r\n/g, "\n");
|
|
9
|
+
const bloco = (texto, seletor) => {
|
|
10
|
+
const inicio = texto.indexOf(seletor + " {");
|
|
11
|
+
expect(inicio, seletor).toBeGreaterThanOrEqual(0);
|
|
12
|
+
return texto.slice(inicio, texto.indexOf("}", inicio));
|
|
13
|
+
};
|
|
14
|
+
describe("SegmentedControl · variant surface", () => {
|
|
15
|
+
const OPCOES = [
|
|
16
|
+
{ label: "Individual", value: "individual", count: 12 },
|
|
17
|
+
{ label: "Em lote", value: "lote" },
|
|
18
|
+
];
|
|
19
|
+
it("surface escreve a classe; sem a prop e com default, não", () => {
|
|
20
|
+
const { container } = render(_jsxs(_Fragment, { children: [_jsx(SegmentedControl, { options: OPCOES, variant: "surface", defaultValue: "individual" }), _jsx(SegmentedControl, { options: OPCOES, defaultValue: "individual" }), _jsx(SegmentedControl, { options: OPCOES, variant: "default", defaultValue: "individual" })] }));
|
|
21
|
+
expect(container.children[0]).toHaveClass("umds-segmented--surface");
|
|
22
|
+
expect(container.children[1]).not.toHaveClass("umds-segmented--surface");
|
|
23
|
+
expect(container.children[2]).not.toHaveClass("umds-segmented--surface");
|
|
24
|
+
});
|
|
25
|
+
it("CSS: o escolhido é branco, em negrito e com sombra; o trilho é cinza claro; o azul cheio do padrão segue", () => {
|
|
26
|
+
const t = css("SegmentedControl");
|
|
27
|
+
const escolhido = bloco(t, ".umds-segmented--surface .umds-segmented__input:checked + .umds-segmented__item,\n.umds-segmented--surface .umds-segmented__input:checked + .umds-segmented__item:hover");
|
|
28
|
+
expect(escolhido).toMatch(/background-color:\s*var\(--umds-semantic-color-background-white\)/);
|
|
29
|
+
expect(escolhido).toMatch(/font-weight:\s*var\(--umds-primitive-font-weight-bold\)/);
|
|
30
|
+
expect(escolhido).toMatch(/box-shadow:\s*var\(--umds-semantic-shadow-md\)/);
|
|
31
|
+
expect(bloco(t, ".umds-segmented--surface .umds-segmented__track")).toMatch(/background-color:\s*var\(--umds-semantic-color-neutral-light-medium\)/);
|
|
32
|
+
expect(t).toMatch(/\.umds-segmented__input:checked \+ \.umds-segmented__item,\n\.umds-segmented__input:checked \+ \.umds-segmented__item:hover \{\n\s*background-color:\s*var\(--umds-semantic-color-primary-pure\)/);
|
|
33
|
+
});
|
|
34
|
+
it("o contador do escolhido fica cinza sobre o branco e o dos outros, branco sobre o trilho", () => {
|
|
35
|
+
const t = css("SegmentedControl");
|
|
36
|
+
expect(bloco(t, ".umds-segmented--surface .umds-segmented__count")).toMatch(/background-color:\s*var\(--umds-semantic-color-background-white\)/);
|
|
37
|
+
expect(bloco(t, ".umds-segmented--surface .umds-segmented__input:checked + .umds-segmented__item .umds-segmented__count")).toMatch(/background-color:\s*var\(--umds-semantic-color-neutral-light-medium\)/);
|
|
38
|
+
});
|
|
39
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { describe, expect, it } from "vitest";
|
|
3
|
+
import { fireEvent, render, screen } from "@testing-library/react";
|
|
4
|
+
import Select from "../components/Select/Select";
|
|
5
|
+
const OPCOES = [
|
|
6
|
+
{ label: "Urgente", value: "urgente", etiqueta: "Prazo hoje" },
|
|
7
|
+
{ label: "Rotina", value: "rotina", etiqueta: "Sem prazo" },
|
|
8
|
+
];
|
|
9
|
+
const item = ({ optionData }) => (_jsxs("span", { "data-testid": "item", children: [_jsx("b", { children: optionData.label }), " ", _jsx("i", { children: optionData.etiqueta })] }));
|
|
10
|
+
describe("Select · item com escopo da opção", () => {
|
|
11
|
+
it("a lista mostra o item de cada opção, recebendo a opção (optionData e o apelido option)", () => {
|
|
12
|
+
const vistos = [];
|
|
13
|
+
render(_jsx(Select, { ariaLabel: "Prioridade", options: OPCOES, item: (escopo) => {
|
|
14
|
+
vistos.push(escopo);
|
|
15
|
+
return _jsx("span", { "data-testid": "item", children: escopo.optionData.label });
|
|
16
|
+
} }));
|
|
17
|
+
fireEvent.click(screen.getByRole("combobox"));
|
|
18
|
+
expect(screen.getAllByTestId("item").map((n) => n.textContent)).toEqual(["Urgente", "Rotina"]);
|
|
19
|
+
expect(vistos[0].optionData).toBe(OPCOES[0]);
|
|
20
|
+
expect(vistos[0].option).toBe(OPCOES[0]);
|
|
21
|
+
});
|
|
22
|
+
it("o gatilho com a opção escolhida mostra o conteúdo do item, não o texto", () => {
|
|
23
|
+
render(_jsx(Select, { ariaLabel: "Prioridade", options: OPCOES, value: "urgente", item: item }));
|
|
24
|
+
const gatilho = screen.getByRole("combobox");
|
|
25
|
+
expect(gatilho.querySelector(".umds-select__trigger-item")).not.toBeNull();
|
|
26
|
+
expect(gatilho).toHaveTextContent("Urgente");
|
|
27
|
+
expect(gatilho).toHaveTextContent("Prazo hoje");
|
|
28
|
+
expect(gatilho.querySelector(".umds-select__placeholder")).toBeNull();
|
|
29
|
+
});
|
|
30
|
+
it("sem valor o gatilho mostra o placeholder; escolher na lista passa o item para o gatilho", () => {
|
|
31
|
+
function App() {
|
|
32
|
+
return _jsx(Select, { ariaLabel: "Prioridade", placeholder: "Escolha", options: OPCOES, item: item });
|
|
33
|
+
}
|
|
34
|
+
render(_jsx(App, {}));
|
|
35
|
+
const gatilho = screen.getByRole("combobox");
|
|
36
|
+
expect(gatilho).toHaveTextContent("Escolha");
|
|
37
|
+
expect(gatilho.querySelector(".umds-select__trigger-item")).toBeNull();
|
|
38
|
+
fireEvent.click(gatilho);
|
|
39
|
+
fireEvent.click(screen.getAllByRole("option")[1]);
|
|
40
|
+
expect(screen.getByRole("combobox").querySelector(".umds-select__trigger-item")).toHaveTextContent("Rotina");
|
|
41
|
+
});
|
|
42
|
+
it("seleção múltipla segue com o texto no gatilho", () => {
|
|
43
|
+
render(_jsx(Select, { ariaLabel: "Prioridade", multiple: true, options: OPCOES, value: ["urgente"], item: item }));
|
|
44
|
+
expect(screen.getByRole("combobox").querySelector(".umds-select__trigger-item")).toBeNull();
|
|
45
|
+
});
|
|
46
|
+
it("sem item nada muda: o gatilho mostra o rótulo; item como nó solto (legado) não vai ao gatilho", () => {
|
|
47
|
+
const { rerender } = render(_jsx(Select, { ariaLabel: "Prioridade", options: OPCOES, value: "urgente" }));
|
|
48
|
+
expect(screen.getByRole("combobox")).toHaveTextContent("Urgente");
|
|
49
|
+
expect(screen.getByRole("combobox").querySelector(".umds-select__trigger-item")).toBeNull();
|
|
50
|
+
rerender(_jsx(Select, { ariaLabel: "Prioridade", options: OPCOES, value: "urgente", item: _jsx("em", { children: "fixo" }) }));
|
|
51
|
+
expect(screen.getByRole("combobox").querySelector(".umds-select__trigger-item")).toBeNull();
|
|
52
|
+
expect(screen.getByRole("combobox")).toHaveTextContent("Urgente");
|
|
53
|
+
});
|
|
54
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { afterEach, describe, expect, it, vi } from "vitest";
|
|
3
|
+
import { fireEvent, render, screen, waitFor } from "@testing-library/react";
|
|
4
|
+
import Select from "../components/Select/Select";
|
|
5
|
+
import { lerArquivo } from "./lerArquivo";
|
|
6
|
+
const cssSelect = await lerArquivo("../core/src/components/Select/Select.css");
|
|
7
|
+
const OPCOES = [
|
|
8
|
+
{ label: "Urgente", value: "urgente" },
|
|
9
|
+
{ label: "Revisão", value: "revisao" },
|
|
10
|
+
];
|
|
11
|
+
afterEach(() => vi.restoreAllMocks());
|
|
12
|
+
const lista = (container) => container.querySelector(".umds-select__dropdown");
|
|
13
|
+
/** jsdom não tem layout: só a lista "mede" o que o teste mandar. */
|
|
14
|
+
function medirLista(direita, larguraDaJanela) {
|
|
15
|
+
vi.spyOn(HTMLElement.prototype, "getBoundingClientRect").mockImplementation(function () {
|
|
16
|
+
const eLista = this.classList.contains("umds-select__dropdown");
|
|
17
|
+
return { top: 0, bottom: 0, left: 0, right: eLista ? direita : 0, width: 0, height: 0, x: 0, y: 0, toJSON() { } };
|
|
18
|
+
});
|
|
19
|
+
Object.defineProperty(window, "innerWidth", { value: larguraDaJanela, configurable: true });
|
|
20
|
+
}
|
|
21
|
+
describe("Select filtro · listMinWidth", () => {
|
|
22
|
+
it("um número vira px e a lista nunca fica mais estreita que o gatilho", () => {
|
|
23
|
+
const { container } = render(_jsx(Select, { ariaLabel: "x", options: OPCOES, variant: "filter", listMinWidth: 220 }));
|
|
24
|
+
fireEvent.click(screen.getByRole("combobox"));
|
|
25
|
+
expect(lista(container).style.minWidth).toBe("max(100%, 220px)");
|
|
26
|
+
});
|
|
27
|
+
it("uma medida CSS vale como veio", () => {
|
|
28
|
+
const { container } = render(_jsx(Select, { ariaLabel: "x", options: OPCOES, variant: "filter", listMinWidth: "18rem" }));
|
|
29
|
+
fireEvent.click(screen.getByRole("combobox"));
|
|
30
|
+
expect(lista(container).style.minWidth).toBe("max(100%, 18rem)");
|
|
31
|
+
});
|
|
32
|
+
it("0 é um valor (sem mínimo além do gatilho), não ausência", () => {
|
|
33
|
+
const { container } = render(_jsx(Select, { ariaLabel: "x", options: OPCOES, variant: "filter", listMinWidth: 0 }));
|
|
34
|
+
fireEvent.click(screen.getByRole("combobox"));
|
|
35
|
+
expect(lista(container).style.minWidth).toBe("max(100%, 0px)");
|
|
36
|
+
});
|
|
37
|
+
it("sem a prop o mínimo é o do CSS (240px), sem estilo inline", () => {
|
|
38
|
+
const { container } = render(_jsx(Select, { ariaLabel: "x", options: OPCOES, variant: "filter" }));
|
|
39
|
+
fireEvent.click(screen.getByRole("combobox"));
|
|
40
|
+
expect(lista(container).style.minWidth).toBe("");
|
|
41
|
+
});
|
|
42
|
+
it("o Select padrão ignora a prop (a lista é a largura do campo)", () => {
|
|
43
|
+
const { container } = render(_jsx(Select, { ariaLabel: "x", options: OPCOES, listMinWidth: 220 }));
|
|
44
|
+
fireEvent.click(screen.getByRole("combobox"));
|
|
45
|
+
expect(lista(container).style.minWidth).toBe("");
|
|
46
|
+
});
|
|
47
|
+
});
|
|
48
|
+
describe("Select filtro · nunca passa da borda da janela", () => {
|
|
49
|
+
it("a lista que estoura a borda direita se alinha ao fim do gatilho", async () => {
|
|
50
|
+
medirLista(1457, 1440);
|
|
51
|
+
const { container } = render(_jsx(Select, { ariaLabel: "x", options: OPCOES, variant: "filter" }));
|
|
52
|
+
fireEvent.click(screen.getByRole("combobox"));
|
|
53
|
+
await waitFor(() => expect(container.querySelector(".umds-select--list-end")).not.toBeNull());
|
|
54
|
+
});
|
|
55
|
+
it("a lista que cabe fica onde está", async () => {
|
|
56
|
+
medirLista(900, 1440);
|
|
57
|
+
const { container } = render(_jsx(Select, { ariaLabel: "x", options: OPCOES, variant: "filter" }));
|
|
58
|
+
fireEvent.click(screen.getByRole("combobox"));
|
|
59
|
+
await waitFor(() => expect(lista(container)).not.toBeNull());
|
|
60
|
+
expect(container.querySelector(".umds-select--list-end")).toBeNull();
|
|
61
|
+
});
|
|
62
|
+
it("deixa 8px de respiro: encostada na borda ainda alinha", async () => {
|
|
63
|
+
medirLista(1436, 1440);
|
|
64
|
+
const { container } = render(_jsx(Select, { ariaLabel: "x", options: OPCOES, variant: "filter" }));
|
|
65
|
+
fireEvent.click(screen.getByRole("combobox"));
|
|
66
|
+
await waitFor(() => expect(container.querySelector(".umds-select--list-end")).not.toBeNull());
|
|
67
|
+
});
|
|
68
|
+
it("fechar desliga o alinhamento", async () => {
|
|
69
|
+
medirLista(1457, 1440);
|
|
70
|
+
const { container } = render(_jsx(Select, { ariaLabel: "x", options: OPCOES, variant: "filter" }));
|
|
71
|
+
fireEvent.click(screen.getByRole("combobox"));
|
|
72
|
+
await waitFor(() => expect(container.querySelector(".umds-select--list-end")).not.toBeNull());
|
|
73
|
+
fireEvent.click(screen.getByRole("combobox"));
|
|
74
|
+
await waitFor(() => expect(container.querySelector(".umds-select--list-end")).toBeNull());
|
|
75
|
+
});
|
|
76
|
+
it("o Select padrão (não filtro) não é movido", async () => {
|
|
77
|
+
medirLista(1457, 1440);
|
|
78
|
+
const { container } = render(_jsx(Select, { ariaLabel: "x", options: OPCOES }));
|
|
79
|
+
fireEvent.click(screen.getByRole("combobox"));
|
|
80
|
+
await waitFor(() => expect(lista(container)).not.toBeNull());
|
|
81
|
+
expect(container.querySelector(".umds-select--list-end")).toBeNull();
|
|
82
|
+
});
|
|
83
|
+
});
|
|
84
|
+
describe("Select filtro · CSS", () => {
|
|
85
|
+
const css = cssSelect.replace(/\r\n/g, "\n");
|
|
86
|
+
const bloco = (seletor) => {
|
|
87
|
+
const inicio = css.indexOf(seletor + " {");
|
|
88
|
+
return css.slice(inicio, css.indexOf("}", inicio));
|
|
89
|
+
};
|
|
90
|
+
it("o wrapper do filtro é fit-content (o auto o esticava até o pai e a lista herdava essa largura)", () => {
|
|
91
|
+
expect(bloco(".umds-select--filter")).toMatch(/width:\s*fit-content/);
|
|
92
|
+
});
|
|
93
|
+
it("a busca da lista fica fora da conta da largura natural", () => {
|
|
94
|
+
expect(bloco(".umds-select--filter .umds-select__search-container")).toMatch(/contain:\s*inline-size/);
|
|
95
|
+
expect(bloco(".umds-select__search-input")).toMatch(/min-width:\s*0/);
|
|
96
|
+
});
|
|
97
|
+
it("o alinhamento ao fim ancora a lista pela direita", () => {
|
|
98
|
+
const b = bloco(".umds-select--filter.umds-select--list-end .umds-select__dropdown");
|
|
99
|
+
expect(b).toMatch(/left:\s*auto/);
|
|
100
|
+
expect(b).toMatch(/right:\s*0/);
|
|
101
|
+
});
|
|
102
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { describe, expect, it } from "vitest";
|
|
3
|
+
import { render } from "@testing-library/react";
|
|
4
|
+
import StatCard from "../components/StatCard/StatCard";
|
|
5
|
+
import { lerArquivo } from "./lerArquivo";
|
|
6
|
+
const cssStatCard = await lerArquivo("../core/src/components/StatCard/StatCard.css");
|
|
7
|
+
const css = cssStatCard.replace(/\r\n/g, "\n");
|
|
8
|
+
const bloco = (seletor) => {
|
|
9
|
+
const inicio = css.indexOf(seletor + " {");
|
|
10
|
+
return css.slice(inicio, css.indexOf("}", inicio));
|
|
11
|
+
};
|
|
12
|
+
describe("StatCard · size", () => {
|
|
13
|
+
it("sm escreve a classe; sem a prop e com md o cartão é o de antes", () => {
|
|
14
|
+
const { container } = render(_jsxs(_Fragment, { children: [_jsx(StatCard, { value: 44, label: "N\u00E3o lidos", size: "sm" }), _jsx(StatCard, { value: 44, label: "N\u00E3o lidos" }), _jsx(StatCard, { value: 44, label: "N\u00E3o lidos", size: "md" })] }));
|
|
15
|
+
expect(container.children[0]).toHaveClass("umds-stat-card--sm");
|
|
16
|
+
expect(container.children[1]).not.toHaveClass("umds-stat-card--sm");
|
|
17
|
+
expect(container.children[2]).not.toHaveClass("umds-stat-card--sm");
|
|
18
|
+
});
|
|
19
|
+
it("o número do sm é 18px/800, e a regra vence o 32/800 do rótulo no topo", () => {
|
|
20
|
+
const regra = bloco(".umds-stat-card.umds-stat-card--sm .umds-stat-card__valor");
|
|
21
|
+
expect(regra).toMatch(/font-size:\s*1\.125rem/);
|
|
22
|
+
expect(regra).toMatch(/font-weight:\s*var\(--umds-primitive-font-weight-extrabold\)/);
|
|
23
|
+
const { container } = render(_jsx(StatCard, { value: 44, label: "N\u00E3o lidos", size: "sm", labelPosition: "top" }));
|
|
24
|
+
expect(container.firstElementChild).toHaveClass("umds-stat-card--sm", "umds-stat-card--rotulo-topo");
|
|
25
|
+
});
|
|
26
|
+
it("o número continua antes do rótulo no HTML", () => {
|
|
27
|
+
const { container } = render(_jsx(StatCard, { value: 44, label: "N\u00E3o lidos", size: "sm" }));
|
|
28
|
+
const valor = container.querySelector(".umds-stat-card__valor");
|
|
29
|
+
const rotulo = container.querySelector(".umds-stat-card__rotulo");
|
|
30
|
+
expect(valor.compareDocumentPosition(rotulo) & Node.DOCUMENT_POSITION_FOLLOWING).toBeTruthy();
|
|
31
|
+
});
|
|
32
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { describe, expect, it } from "vitest";
|
|
3
|
+
import Tabs from "../components/Tabs/Tabs";
|
|
4
|
+
import Tab from "../components/Tabs/Tab";
|
|
5
|
+
import { render } from "@testing-library/react";
|
|
6
|
+
import { lerArquivo } from "./lerArquivo";
|
|
7
|
+
const cssTabs = await lerArquivo("../core/src/components/Tabs/Tabs.css");
|
|
8
|
+
const CSS = { Tabs: cssTabs };
|
|
9
|
+
const css = (componente) => CSS[componente].replace(/\r\n/g, "\n");
|
|
10
|
+
const bloco = (texto, seletor) => {
|
|
11
|
+
const inicio = texto.indexOf(seletor + " {");
|
|
12
|
+
expect(inicio, seletor).toBeGreaterThanOrEqual(0);
|
|
13
|
+
return texto.slice(inicio, texto.indexOf("}", inicio));
|
|
14
|
+
};
|
|
15
|
+
describe("Tabs · density", () => {
|
|
16
|
+
it("compact escreve a classe na raiz; sem a prop e com default, não", () => {
|
|
17
|
+
const { container } = render(_jsxs(_Fragment, { children: [_jsx(Tabs, { value: "0", density: "compact", children: _jsx(Tab, { label: "A", index: "0" }) }), _jsx(Tabs, { value: "0", children: _jsx(Tab, { label: "B", index: "0" }) }), _jsx(Tabs, { value: "0", density: "default", children: _jsx(Tab, { label: "C", index: "0" }) })] }));
|
|
18
|
+
expect(container.children[0]).toHaveClass("umds-tabs--compact");
|
|
19
|
+
expect(container.children[1]).not.toHaveClass("umds-tabs--compact");
|
|
20
|
+
expect(container.children[2]).not.toHaveClass("umds-tabs--compact");
|
|
21
|
+
});
|
|
22
|
+
it("CSS: a compacta tem altura mínima de 40px (degrau sm) e padding vertical de 8px; o padrão segue em 48px", () => {
|
|
23
|
+
const t = css("Tabs");
|
|
24
|
+
const compacta = bloco(t, ".umds-tabs--compact .umds-tabs__tab");
|
|
25
|
+
expect(compacta).toMatch(/min-height:\s*var\(--umds-primitive-spacing-sm\)/);
|
|
26
|
+
expect(compacta).toMatch(/padding-block:\s*var\(--umds-primitive-spacing-nano\)/);
|
|
27
|
+
expect(bloco(t, ".umds-tabs__tab")).toMatch(/min-height:\s*48px/);
|
|
28
|
+
});
|
|
29
|
+
it("a pílula do contador é cinza na aba inativa e azul só na ativa (nas duas densidades)", () => {
|
|
30
|
+
const t = css("Tabs");
|
|
31
|
+
expect(bloco(t, ".umds-tabs__count")).toMatch(/background-color:\s*var\(--umds-semantic-color-neutral-light-medium\)/);
|
|
32
|
+
expect(bloco(t, ".umds-tabs__tab--selected .umds-tabs__count")).toMatch(/background-color:\s*var\(--umds-semantic-color-primary-pure\)/);
|
|
33
|
+
expect(t).not.toMatch(/--compact[^{]*\.umds-tabs__count/);
|
|
34
|
+
});
|
|
35
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { describe, expect, it } from "vitest";
|
|
3
|
+
import { render } from "@testing-library/react";
|
|
4
|
+
import Tag from "../components/Tag/Tag";
|
|
5
|
+
import { lerArquivo } from "./lerArquivo";
|
|
6
|
+
const cssTag = await lerArquivo("../core/src/components/Tag/Tag.css");
|
|
7
|
+
const tema1doc = await lerArquivo("../tokens/dist/css/theme-1doc.css");
|
|
8
|
+
const temaEscuro = await lerArquivo("../tokens/dist/css/theme-1doc-dark.css");
|
|
9
|
+
const temaAltoContraste = await lerArquivo("../tokens/dist/css/theme-1doc-high-contrast.css");
|
|
10
|
+
const css = cssTag.replace(/\r\n/g, "\n");
|
|
11
|
+
const bloco = (seletor) => {
|
|
12
|
+
const inicio = css.indexOf(seletor + " {");
|
|
13
|
+
return css.slice(inicio, css.indexOf("}", inicio));
|
|
14
|
+
};
|
|
15
|
+
const TEMAS = { "theme-1doc.css": tema1doc, "theme-1doc-dark.css": temaEscuro, "theme-1doc-high-contrast.css": temaAltoContraste };
|
|
16
|
+
const tema = (arquivo) => {
|
|
17
|
+
const texto = TEMAS[arquivo];
|
|
18
|
+
const cor = (nome) => texto.match(new RegExp("--umds-theme-" + nome + ":\\s*(#[0-9A-Fa-f]{6})"))[1];
|
|
19
|
+
return cor;
|
|
20
|
+
};
|
|
21
|
+
const luz = (hex) => {
|
|
22
|
+
const c = [1, 3, 5].map((i) => parseInt(hex.slice(i, i + 2), 16) / 255).map((v) => (v <= 0.03928 ? v / 12.92 : ((v + 0.055) / 1.055) ** 2.4));
|
|
23
|
+
return 0.2126 * c[0] + 0.7152 * c[1] + 0.0722 * c[2];
|
|
24
|
+
};
|
|
25
|
+
const contraste = (a, b) => {
|
|
26
|
+
const [x, y] = [luz(a), luz(b)].sort((m, n) => n - m);
|
|
27
|
+
return (x + 0.05) / (y + 0.05);
|
|
28
|
+
};
|
|
29
|
+
describe("Tag positive outlined sobre fundo tingido", () => {
|
|
30
|
+
it("escreve as classes que a regra de CSS escolhe", () => {
|
|
31
|
+
const { container } = render(_jsx(Tag, { label: "Entregue", variant: "positive", appearance: "outlined" }));
|
|
32
|
+
const tag = container.firstElementChild;
|
|
33
|
+
expect(tag).toHaveClass("umds-tag--outlined", "umds-tag--positive");
|
|
34
|
+
});
|
|
35
|
+
it("o texto é positive-dark e o contorno segue positive-pure", () => {
|
|
36
|
+
const regra = bloco(".umds-tag--outlined.umds-tag--positive");
|
|
37
|
+
expect(regra).toMatch(/color:\s*var\(--umds-semantic-color-feedback-positive-dark\)/);
|
|
38
|
+
expect(regra).toMatch(/border-color:\s*var\(--umds-semantic-color-feedback-positive-pure\)/);
|
|
39
|
+
});
|
|
40
|
+
it("no tema 1doc, sobre o azul-claro do card o texto passa de 4,5:1 (o pure dava 3,6:1)", () => {
|
|
41
|
+
const cor = tema("theme-1doc.css");
|
|
42
|
+
const fundo = cor("primary-light");
|
|
43
|
+
expect(contraste(cor("feedback-positive-pure"), fundo)).toBeLessThan(4.5);
|
|
44
|
+
expect(contraste(cor("feedback-positive-dark"), fundo)).toBeGreaterThanOrEqual(4.5);
|
|
45
|
+
});
|
|
46
|
+
it("nos temas escuro e de alto contraste o texto também passa de 4,5:1 sobre o fundo tingido e sobre a página", () => {
|
|
47
|
+
for (const arquivo of ["theme-1doc-dark.css", "theme-1doc-high-contrast.css"]) {
|
|
48
|
+
const cor = tema(arquivo);
|
|
49
|
+
for (const fundo of [cor("primary-light"), cor("background-white")]) {
|
|
50
|
+
expect(contraste(cor("feedback-positive-dark"), fundo)).toBeGreaterThanOrEqual(4.5);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function lerArquivo(relativo: string): Promise<string>;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Lê um arquivo do pacote (relativo à pasta `packages/react`) para os testes que conferem uma regra de CSS na
|
|
3
|
+
* fonte: o jsdom não tem cascata de arquivo, e o `css: false` do vitest esvazia o `?raw` do CSS.
|
|
4
|
+
* O `node:fs` entra por import dinâmico com nome calculado porque o `tsc` do pacote não traz os tipos do Node.
|
|
5
|
+
*/
|
|
6
|
+
const modulo = (nome) => import(/* @vite-ignore */ nome);
|
|
7
|
+
export async function lerArquivo(relativo) {
|
|
8
|
+
const fs = await modulo("node:fs");
|
|
9
|
+
const path = await modulo("node:path");
|
|
10
|
+
const raiz = globalThis.process.cwd();
|
|
11
|
+
return fs.readFileSync(path.resolve(raiz, relativo), "utf8");
|
|
12
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@1doc/1ds-react",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.11.0",
|
|
4
4
|
"main": "dist/index.js",
|
|
5
5
|
"sideEffects": [
|
|
6
6
|
"**/*.css"
|
|
@@ -45,8 +45,8 @@
|
|
|
45
45
|
"react-dom": "^18.0.0",
|
|
46
46
|
"typescript": "^5.0.0",
|
|
47
47
|
"vitest": "^3.2.7",
|
|
48
|
-
"@1doc/1ds-core": "2.
|
|
49
|
-
"@1doc/1ds-tokens": "0.
|
|
48
|
+
"@1doc/1ds-core": "2.11.0",
|
|
49
|
+
"@1doc/1ds-tokens": "0.6.0"
|
|
50
50
|
},
|
|
51
51
|
"publishConfig": {
|
|
52
52
|
"access": "public"
|