feat: release design system engine, studio and component contracts
This commit is contained in:
1 parent
ff1065fb27
commit
3943b946d6
693 files changed
+175546
-3894
No files matched your search
@@ -72,64 +72,89 @@ test("carousel exposes both unframed and framed surfaces", async () => {
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
test("rating commits a star selection and readonly rating stays disabled", async () => {
|
||||
const dom = await mount("Rating", {value: 2});
|
||||
(dom.querySelector('[aria-label="Rate 4 of 5"]') as HTMLButtonElement).click();
|
||||
expect(dom.querySelector('output')?.textContent).toContain("4 / 5");
|
||||
expect(dom.querySelectorAll('[data-filled="true"]').length).toBe(4);
|
||||
const readonly = await mount("Rating", {readonly:true});
|
||||
expect((readonly.querySelector('button') as HTMLButtonElement).disabled).toBe(true);
|
||||
const dom = await mount("Rating", { value: 2 });
|
||||
(dom.querySelector('[aria-label="Rate 4 of 5"]') as HTMLButtonElement).click();
|
||||
expect(dom.querySelector("output")?.textContent).toContain("4 / 5");
|
||||
expect(dom.querySelectorAll('[data-filled="true"]').length).toBe(4);
|
||||
const readonly = await mount("Rating", { readonly: true });
|
||||
expect((readonly.querySelector("button") as HTMLButtonElement).disabled).toBe(true);
|
||||
});
|
||||
|
||||
|
||||
test("fractional rating uses the requested step and commits precise values", async () => {
|
||||
const dom = await mount("Rating", {value:3.5, step:0.2});
|
||||
const slider = dom.querySelector('input[type="range"]') as HTMLInputElement;
|
||||
expect(slider.step).toBe("0.2");
|
||||
slider.value = "4.2";
|
||||
slider.dispatchEvent(new (dom.window as Window & typeof globalThis).Event("input", {bubbles:true}));
|
||||
expect(dom.querySelector('output')?.textContent).toContain("4.2 / 5");
|
||||
const dom = await mount("Rating", { value: 3.5, step: 0.2 });
|
||||
const slider = dom.querySelector('input[type="range"]') as HTMLInputElement;
|
||||
expect(slider.step).toBe("0.2");
|
||||
slider.value = "4.2";
|
||||
slider.dispatchEvent(
|
||||
new (dom.window as Window & typeof globalThis).Event("input", { bubbles: true }),
|
||||
);
|
||||
expect(dom.querySelector("output")?.textContent).toContain("4.2 / 5");
|
||||
});
|
||||
|
||||
test("card header and footer can be suppressed independently", async () => {
|
||||
const dom = await mount("Card", {title:"Hidden title",footer:"Hidden footer",showHeader:false,showFooter:false,description:"Body remains"});
|
||||
expect(dom.querySelector('.wrn-next__card-header')).toBeNull();
|
||||
expect(dom.querySelector('.wrn-next__card-footer')).toBeNull();
|
||||
expect(dom.document.body.textContent).toContain("Body remains");
|
||||
const dom = await mount("Card", {
|
||||
title: "Hidden title",
|
||||
footer: "Hidden footer",
|
||||
showHeader: false,
|
||||
showFooter: false,
|
||||
description: "Body remains",
|
||||
});
|
||||
expect(dom.querySelector(".wrn-next__card-header")).toBeNull();
|
||||
expect(dom.querySelector(".wrn-next__card-footer")).toBeNull();
|
||||
expect(dom.document.body.textContent).toContain("Body remains");
|
||||
});
|
||||
|
||||
test("map embeds a geographic provider and requires a Google key", async () => {
|
||||
const osm = await mount("Map", {latitude:12.97,longitude:77.59});
|
||||
expect(osm.querySelector('iframe')?.getAttribute('src')).toContain('openstreetmap.org/export/embed.html');
|
||||
const google = await mount("Map", {provider:"google",apiKey:""});
|
||||
expect(google.querySelector('iframe')).toBeNull();
|
||||
expect(google.document.body.textContent).toContain('API key');
|
||||
const osm = await mount("Map", { latitude: 12.97, longitude: 77.59 });
|
||||
expect(osm.querySelector("iframe")?.getAttribute("src")).toContain(
|
||||
"openstreetmap.org/export/embed.html",
|
||||
);
|
||||
const google = await mount("Map", { provider: "google", apiKey: "" });
|
||||
expect(google.querySelector("iframe")).toBeNull();
|
||||
expect(google.document.body.textContent).toContain("API key");
|
||||
});
|
||||
|
||||
test("chart accepts data arrays and chooses line rendering", async () => {
|
||||
const dom = await mount("Chart", {type:"line",data:[{label:"Mon",value:12},{label:"Tue",value:18}]});
|
||||
expect(dom.querySelector('path.wrn-chart__line')).not.toBeNull();
|
||||
expect(dom.querySelectorAll('.wrn-chart__hit').length).toBe(2);
|
||||
test("chart accepts data arrays and configures Chart.js line rendering", async () => {
|
||||
const dom = await mount("Chart", {
|
||||
type: "line",
|
||||
data: [
|
||||
{ label: "Mon", value: 12 },
|
||||
{ label: "Tue", value: 18 },
|
||||
],
|
||||
});
|
||||
const root = dom.querySelector('[data-ui-component="Chart"]') as HTMLElement;
|
||||
expect(root.dataset.wrnexusRuntime).toBe("chartjs");
|
||||
expect(root.querySelector("canvas")?.getAttribute("role")).toBe("img");
|
||||
const config = JSON.parse(root.dataset.chartConfig!);
|
||||
expect(config.type).toBe("line");
|
||||
expect(config.data).toEqual([
|
||||
{ label: "Mon", value: 12 },
|
||||
{ label: "Tue", value: 18 },
|
||||
]);
|
||||
});
|
||||
|
||||
test("calendar Done and outside dismiss both close the panel", async () => {
|
||||
const dom = await mount("DatePicker", {value:"2026-09-20"});
|
||||
const trigger = dom.querySelector('.wrn-next__date-trigger') as HTMLButtonElement;
|
||||
trigger.click();
|
||||
(dom.querySelector('.wrn-next__date-done') as HTMLButtonElement).click();
|
||||
expect(trigger.getAttribute('aria-expanded')).toBe('false');
|
||||
trigger.click();
|
||||
(dom.querySelector('.wrn-picker-dismiss') as HTMLButtonElement).click();
|
||||
expect(trigger.getAttribute('aria-expanded')).toBe('false');
|
||||
const dom = await mount("DatePicker", { value: "2026-09-20" });
|
||||
const trigger = dom.querySelector(".wrn-next__date-trigger") as HTMLButtonElement;
|
||||
trigger.click();
|
||||
(dom.querySelector(".wrn-next__date-done") as HTMLButtonElement).click();
|
||||
expect(trigger.getAttribute("aria-expanded")).toBe("false");
|
||||
trigger.click();
|
||||
(dom.querySelector(".wrn-picker-dismiss") as HTMLButtonElement).click();
|
||||
expect(trigger.getAttribute("aria-expanded")).toBe("false");
|
||||
});
|
||||
|
||||
|
||||
test("fractional slider increments stay precise and disabled controls do not change", async () => {
|
||||
const dom = await mount("RangeSlider", {min:0,max:5,value:2.4,step:0.2});
|
||||
(dom.querySelector('[aria-label="Increase Range"]') as HTMLButtonElement).click();
|
||||
expect(dom.querySelector('[role="slider"]')?.getAttribute('aria-valuenow')).toBe('2.6');
|
||||
const locked = await mount("RangeSlider", {value:2,disabled:true});
|
||||
(locked.querySelector('[role="slider"]') as HTMLElement).dispatchEvent(new (locked.window as Window & typeof globalThis).KeyboardEvent('keydown',{key:'ArrowRight',bubbles:true}));
|
||||
expect(locked.querySelector('[role="slider"]')?.getAttribute('aria-valuenow')).toBe('2');
|
||||
const dom = await mount("RangeSlider", { min: 0, max: 5, value: 2.4, step: 0.2 });
|
||||
(dom.querySelector('[aria-label="Increase Range"]') as HTMLButtonElement).click();
|
||||
expect(dom.querySelector('[role="slider"]')?.getAttribute("aria-valuenow")).toBe("2.6");
|
||||
const locked = await mount("RangeSlider", { value: 2, disabled: true });
|
||||
(locked.querySelector('[role="slider"]') as HTMLElement).dispatchEvent(
|
||||
new (locked.window as Window & typeof globalThis).KeyboardEvent("keydown", {
|
||||
key: "ArrowRight",
|
||||
bubbles: true,
|
||||
}),
|
||||
);
|
||||
expect(locked.querySelector('[role="slider"]')?.getAttribute("aria-valuenow")).toBe("2");
|
||||
});
|
||||
Reference in new issue
Block a user