sokko-g/e2e/nds-controls.spec.js
Shinuwa e52d6e66eb
All checks were successful
Deploy Sokko G / deploy (push) Successful in 18s
Cover remaining Sass families and fix autocomplete hover
2026-09-14 13:58:40 +02:00

146 lines
10 KiB
JavaScript

// 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, `<div style="padding:24px;display:grid;gap:12px;width:300px">
<input class="nds-input" type="text" data-size="${size}" placeholder="Name">
<input class="nds-time" type="time" data-size="${size}">
<select class="nds-select" data-size="${size}"><option>Choice</option></select>
<textarea class="nds-textarea" data-size="${size}"></textarea>
<button class="nds-select-trigger" data-size="${size}">Choice</button>
<button class="nds-date-trigger" data-size="${size}">Date</button>
</div>`);
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, `<div style="padding:24px;display:flex;flex-wrap:wrap;gap:12px">
${[["md", 40], ["sm", 34], ["xs", 30], ["xxs", 26], ["micro", 22]].map(([size]) =>
`<button class="nds-icon-button" data-size="${size}"><i class="ui-icon"></i></button>`).join("")}
${["md", "sm", "xs"].map((size) => `<button class="nds-button" data-size="${size}">${size}</button>`).join("")}
${["primary", "secondary", "ghost", "dashed", "danger"].map((variant) => `<button class="nds-button" data-variant="${variant}">${variant}</button>`).join("")}
<button id="edge" class="nds-icon-button" data-edge="left" data-border="joined">L</button>
</div>`);
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, `<button style="margin:24px" class="nds-switch" data-size="${size}" aria-pressed="false"><span class="ui-icon"></span><i></i></button>`);
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, `<div style="padding:24px">
${["md", "sm", "xs"].map((size) => `<input type="checkbox" class="nds-checkbox" data-size="${size}" aria-label="${size}">`).join("")}
<label class="nds-native-switch"><input type="checkbox"><span></span><b>Native</b></label>
</div>`);
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, `<div style="padding:24px">
<div class="nds-quantity-stepper" data-size="${size}"><button>-</button><span class="nds-quantity-stepper-value"><input type="number" value="1" class="nds-quantity-stepper-input"></span><button>+</button></div>
<div class="nds-radio-button-group" data-size="${size}"><button>A</button><button class="active">B</button></div>
<div class="nds-compound-toggle-field"><button class="active">Hold</button><input type="number" class="nds-compound-toggle-field-input"></div>
</div>`);
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, `<div style="padding:24px">
<button class="nds-swatch" style="--swatch-color:#22d3ee"></button>
<button class="nds-swatch" data-variant="rainbow"></button>
<button class="nds-large-icon-picker-trigger"><i class="ui-icon"></i></button>
<input class="nds-inline-input" type="text" value="Inline">
<textarea class="nds-textarea" data-variant="ghost">Memo</textarea>
<div class="nds-autocomplete-field"><input class="nds-input" type="text"><div class="nds-autocomplete-menu"><button class="nds-autocomplete-option">Choice</button></div></div>
</div>`);
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)");
});