// Rôle : vérifie les tailles et états rendus des familles de contrôles NDS.
import { test, expect } from "@playwright/test";
import { mountStyles, computed, expectPseudo } from "./fixtures/compiled-styles.js";
test("fields, selects and date triggers keep public sizes and keyboard focus", async ({ page }) => {
for (const [size, height, textareaHeight] of [["md", 44, 108], ["sm", 36, 88], ["xs", 32, 72]]) {
await mountStyles(page, `
Choice
Choice
Date
`);
for (const field of await page.locator("input, select, textarea, button").all()) {
const isTextarea = await field.evaluate((element) => element.tagName === "TEXTAREA");
await expect(field).toHaveCSS("min-height", `${isTextarea ? textareaHeight : height}px`);
await field.focus();
await expect(field).toHaveCSS("border-top-color", "rgb(139, 92, 246)");
await expect(field).toHaveCSS("box-shadow", "rgba(139, 92, 246, 0.16) 0px 0px 0px 3px");
await expect(field).toHaveCSS("outline-style", "solid");
await field.evaluate((element) => { element.disabled = true; });
await expect(field).toHaveCSS("cursor", "not-allowed");
}
await expect(page.locator("textarea")).toHaveCSS("resize", "vertical");
await expect(page.locator("select")).toHaveCSS("appearance", "none");
await expect(page.locator("select")).toHaveCSS("background-image", /data:image\/svg/);
expect(await computed(page.locator(".nds-date-trigger"), "mask-image", "::after")).toContain("data:image/svg");
await expectPseudo(page.locator(".nds-date-trigger"), "::after", "pointer-events", "none");
}
});
test("text and icon buttons retain dimensions, variants, active and joined edges", async ({ page }) => {
await mountStyles(page, `
${[["md", 40], ["sm", 34], ["xs", 30], ["xxs", 26], ["micro", 22]].map(([size]) =>
` `).join("")}
${["md", "sm", "xs"].map((size) => `${size} `).join("")}
${["primary", "secondary", "ghost", "dashed", "danger"].map((variant) => `${variant} `).join("")}
L
`);
for (const [size, button, icon] of [["md", 40, 21], ["sm", 34, 19], ["xs", 30, 17], ["xxs", 26, 15], ["micro", 22, 12]]) {
const target = page.locator(`.nds-icon-button[data-size="${size}"]`);
await expect(target).toHaveCSS("width", `${button}px`);
await expect(target).toHaveCSS("height", `${button}px`);
await expect(target.locator("i")).toHaveCSS("width", `${icon}px`);
await expect(target.locator("i")).toHaveCSS("height", `${icon}px`);
await target.hover();
await expect(target).toHaveCSS("background-image", /139, 92, 246/);
await expect(target).toHaveCSS("width", `${button}px`);
}
await page.mouse.move(0, 0);
for (const [size, height] of [["md", 42], ["sm", 34], ["xs", 30]]) {
await expect(page.locator(`.nds-button[data-size="${size}"]`)).toHaveCSS("min-height", `${height}px`);
}
await expect(page.locator('[data-variant="primary"]')).toHaveCSS("background-image", /246, 196, 83/);
await expect(page.locator('[data-variant="danger"]')).toHaveCSS("color", "rgb(251, 113, 133)");
await expect(page.locator('[data-variant="ghost"]')).toHaveCSS("background-color", "rgba(0, 0, 0, 0)");
await expect(page.locator('[data-variant="dashed"]')).toHaveCSS("border-top-style", "dashed");
const toggle = page.locator('[data-variant="secondary"]');
await toggle.evaluate((element) => element.setAttribute("aria-pressed", "true"));
await expect(toggle).toHaveCSS("background-image", /246, 196, 83/);
await toggle.evaluate((element) => { element.disabled = true; });
await expect(toggle).toHaveCSS("cursor", "not-allowed");
await expect(page.locator("#edge")).toHaveCSS("border-top-right-radius", "0px");
await expect(page.locator("#edge")).toHaveCSS("border-right-color", "rgba(0, 0, 0, 0)");
});
test("switches and native checkboxes expose checked and disabled states at each size", async ({ page }) => {
for (const [size, height, width, trackHeight, off, on] of [["md", 34, 34, 18, 3, 17], ["lg", 40, 30, 16, 3, 15], ["sm", 28, 24, 14, 2, 12], ["xs", 26, 18, 12, 2, 7]]) {
await mountStyles(page, ` `);
const control = page.locator("button");
const track = control.locator("i");
await expect(control).toHaveCSS("min-height", `${height}px`);
await expect(track).toHaveCSS("width", `${width}px`);
await expect(track).toHaveCSS("height", `${trackHeight}px`);
await expectPseudo(track, "::before", "left", `${off}px`);
await control.evaluate((element) => element.setAttribute("aria-pressed", "true"));
await expectPseudo(track, "::before", "left", `${on}px`);
await expectPseudo(track, "::before", "background-color", "rgb(246, 196, 83)");
}
await mountStyles(page, `
${["md", "sm", "xs"].map((size) => ` `).join("")}
Native
`);
for (const [size, dimension] of [["md", 20], ["sm", 18], ["xs", 14]]) {
const checkbox = page.getByRole("checkbox", { name: size, exact: true });
await expect(checkbox).toHaveCSS("width", `${dimension}px`);
await expect(checkbox).toHaveCSS("height", `${dimension}px`);
await expectPseudo(checkbox, "::before", "transform", "matrix(0, 0, 0, 0, 0, 0)");
await checkbox.check();
await expectPseudo(checkbox, "::before", "transform", "matrix(1, 0, 0, 1, 0, 0)");
await checkbox.evaluate((element) => { element.disabled = true; });
await expect(checkbox).toHaveCSS("cursor", "not-allowed");
}
await page.getByText("Native", { exact: true }).click();
const native = page.locator(".nds-native-switch");
await expect(native.locator("input")).toBeChecked();
await expectPseudo(native.locator("span"), "::before", "left", "19px");
await native.locator("input").evaluate((element) => { element.disabled = true; });
await expect(native).toHaveCSS("cursor", "not-allowed");
});
test("steppers, radio groups and compound fields retain compact geometry", async ({ page }) => {
for (const [size, buttonSize, optionHeight] of [["md", 28, 34], ["sm", 18, 28], ["xs", 16, 26]]) {
await mountStyles(page, ``);
for (const button of await page.locator(".nds-quantity-stepper button").all()) {
await expect(button).toHaveCSS("width", `${buttonSize}px`);
await expect(button).toHaveCSS("height", `${buttonSize}px`);
}
await expect(page.locator(".nds-radio-button-group > button").first()).toHaveCSS("min-height", `${optionHeight}px`);
await expect(page.locator(".nds-radio-button-group > .active")).toHaveCSS("background-image", /246, 196, 83/);
await expect(page.locator(".nds-compound-toggle-field-input")).toHaveCSS("min-height", "26px");
await expect(page.locator(".nds-compound-toggle-field-input")).toHaveCSS("width", "34px");
await expect(page.locator(".nds-compound-toggle-field > button")).toHaveCSS("background-image", /246, 196, 83/);
}
});
test("palettes, inline fields and autocomplete menus render their specialised states", async ({ page }) => {
await mountStyles(page, ``);
await expectPseudo(page.locator(".nds-swatch").first(), "::before", "background-color", "rgb(34, 211, 238)");
expect(await computed(page.locator('[data-variant="rainbow"]'), "background-image", "::before")).toContain("conic-gradient");
await expect(page.locator(".nds-large-icon-picker-trigger")).toHaveCSS("width", "100px");
await expect(page.locator(".nds-large-icon-picker-trigger i")).toHaveCSS("width", "72px");
await expect(page.locator(".nds-inline-input")).toHaveCSS("background-color", "rgba(0, 0, 0, 0)");
await page.locator(".nds-inline-input").focus();
await expect(page.locator(".nds-inline-input")).toHaveCSS("border-top-color", "rgb(139, 92, 246)");
await expect(page.locator("textarea")).toHaveCSS("background-color", "rgba(0, 0, 0, 0)");
await expect(page.locator(".nds-autocomplete-menu")).toHaveCSS("position", "absolute");
await expect(page.locator(".nds-autocomplete-menu")).toHaveCSS("overflow-y", "auto");
await page.locator(".nds-autocomplete-option").hover();
await expect(page.locator(".nds-autocomplete-option")).toHaveCSS("background-color", "rgba(246, 196, 83, 0.1)");
await page.mouse.move(0, 0);
await page.locator(".nds-autocomplete-option").evaluate((element) => element.classList.add("is-active"));
await expect(page.locator(".nds-autocomplete-option")).toHaveCSS("background-color", "rgba(246, 196, 83, 0.1)");
});