测试:按实际可见文字校验列表对比度

This commit is contained in:
cieanyau committed 2026-11-07 04:35:56 +08:00
1 parent ba094275ec
commit bdb9b00b6e
1 file changed
+27 -11
+27 -11
View File
@@ -138,7 +138,6 @@ async function measure(page) {
gap: style.gap, gap: style.gap,
padding: style.padding, padding: style.padding,
background: style.backgroundColor, background: style.backgroundColor,
color: style.color,
weight: style.fontWeight, weight: style.fontWeight,
fontSize: style.fontSize, fontSize: style.fontSize,
shadow: style.boxShadow, shadow: style.boxShadow,
@@ -239,6 +238,29 @@ for (const [name, routePath, kind, visibleText] of pages) {
.locator(".p-datatable-mask") .locator(".p-datatable-mask")
.waitFor({ state: "hidden" }); .waitFor({ state: "hidden" });
const filled = await measure(page); const filled = await measure(page);
const visible = content
.getByText(visibleText, { exact: true })
.first();
assert.equal(await visible.isVisible(), true);
// 容器可能没有直接绘制文字;对比度应取可见业务文字及其实际承载背景。
filled.text = await visible.evaluate((element) => {
const rgb = (color) => color.match(/[\d.]+/g).map(Number);
const layers = [];
for (let owner = element; owner; owner = owner.parentElement)
layers.push(rgb(getComputedStyle(owner).backgroundColor));
let background = [255, 255, 255];
for (const layer of layers.reverse()) {
const alpha = layer[3] ?? 1;
background = background.map(
(channel, index) =>
channel * (1 - alpha) + layer[index] * alpha,
);
}
return {
color: getComputedStyle(element).color,
background: `rgb(${background.join(", ")})`,
};
});
const violations = []; const violations = [];
for (const [stateName, observed] of [ for (const [stateName, observed] of [
["empty", empty], ["empty", empty],
@@ -290,22 +312,16 @@ for (const [name, routePath, kind, visibleText] of pages) {
} }
const surface = kind === "table" ? filled.table : filled.article; const surface = kind === "table" ? filled.table : filled.article;
const background = luminance(surface.background); const background = luminance(surface.background);
const foreground = luminance(surface.color); const textBackground = luminance(filled.text.background);
const foreground = luminance(filled.text.color);
if (theme === "light" ? background < 0.5 : background > 0.1) if (theme === "light" ? background < 0.5 : background > 0.1)
violations.push("filled: surface ignores theme"); violations.push("filled: surface ignores theme");
if ( if (
(Math.max(background, foreground) + 0.05) / (Math.max(textBackground, foreground) + 0.05) /
(Math.min(background, foreground) + 0.05) < (Math.min(textBackground, foreground) + 0.05) <
4.5 4.5
) )
violations.push("filled: unreadable theme contrast"); violations.push("filled: unreadable theme contrast");
assert.equal(
await content
.getByText(visibleText, { exact: true })
.first()
.isVisible(),
true,
);
assert.deepEqual(violations, [], JSON.stringify({ empty, filled })); assert.deepEqual(violations, [], JSON.stringify({ empty, filled }));
return { routePath, width, theme, kind, empty, filled }; return { routePath, width, theme, kind, empty, filled };
}), }),