|
|
|
@ -188,7 +188,7 @@ test.describe('Respuesta al puntero', () => {
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
test.describe('Contraste del dorado', () => {
|
|
|
|
test.describe('Contraste y color de marca', () => {
|
|
|
|
// El dorado hace dos trabajos y no puede ser el mismo valor en los dos: de
|
|
|
|
// El dorado hace dos trabajos y no puede ser el mismo valor en los dos: de
|
|
|
|
// relleno tiene que ser claro para que encima se lea el marino, y escrito
|
|
|
|
// relleno tiene que ser claro para que encima se lea el marino, y escrito
|
|
|
|
// tiene que ser hondo para leerse sobre el fondo. Esto lo fija.
|
|
|
|
// tiene que ser hondo para leerse sobre el fondo. Esto lo fija.
|
|
|
|
@ -278,58 +278,25 @@ test.describe('Contraste del dorado', () => {
|
|
|
|
await expect(page.locator('html')).toHaveAttribute('data-tema', 'claro');
|
|
|
|
await expect(page.locator('html')).toHaveAttribute('data-tema', 'claro');
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
/* El identificador de cabecera es monocromo y no depende de degradados. */
|
|
|
|
* El símbolo ya es un SVG vectorial autocontenido: el disco negro y el oro
|
|
|
|
|
|
|
|
* viajan dentro del propio recurso. Por eso el tema no debe teñirlo. Además
|
|
|
|
|
|
|
|
* de comprobar que siempre carga el mismo SVG, se mide cada parada del oro
|
|
|
|
|
|
|
|
* contra el disco sobre el que realmente se dibuja.
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
for (const modo of ['oscuro', 'claro'] as const) {
|
|
|
|
for (const modo of ['oscuro', 'claro'] as const) {
|
|
|
|
test(`el logo conserva su oro y contraste en tema ${modo}`, async ({ page }) => {
|
|
|
|
test(`el logo plano conserva el contraste en tema ${modo}`, async ({ page }) => {
|
|
|
|
await page.goto('/');
|
|
|
|
await page.goto('/');
|
|
|
|
await page.evaluate((m) => {
|
|
|
|
await page.evaluate((m) => {
|
|
|
|
document.documentElement.dataset.tema = m;
|
|
|
|
document.documentElement.dataset.tema = m;
|
|
|
|
}, modo);
|
|
|
|
}, modo);
|
|
|
|
|
|
|
|
|
|
|
|
const peor = await page.evaluate(async () => {
|
|
|
|
const resultado = await page.evaluate(() => {
|
|
|
|
const logo = document.querySelector<HTMLImageElement>('header [data-logo-senza-paura]')!;
|
|
|
|
const logo = document.querySelector<SVGElement>('header [data-logo-senza-paura]')!;
|
|
|
|
const respuesta = await fetch(logo.src);
|
|
|
|
const fondo = document.querySelector<HTMLElement>('header')!;
|
|
|
|
const documento = new DOMParser().parseFromString(await respuesta.text(), 'image/svg+xml');
|
|
|
|
const color = getComputedStyle(logo).color;
|
|
|
|
const colores = [...documento.querySelectorAll('linearGradient stop')].map((stop) =>
|
|
|
|
const base = getComputedStyle(fondo).backgroundColor;
|
|
|
|
stop.getAttribute('stop-color')
|
|
|
|
return { color, base, etiqueta: logo.tagName, relleno: getComputedStyle(logo).fill };
|
|
|
|
);
|
|
|
|
|
|
|
|
const fondo = documento.querySelector('circle')?.getAttribute('fill');
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const pincel = document.createElement('canvas').getContext('2d')!;
|
|
|
|
|
|
|
|
const aRgb = (c: string | null) => {
|
|
|
|
|
|
|
|
if (!c) return [0, 0, 0];
|
|
|
|
|
|
|
|
pincel.fillStyle = c;
|
|
|
|
|
|
|
|
pincel.fillRect(0, 0, 1, 1);
|
|
|
|
|
|
|
|
const d = pincel.getImageData(0, 0, 1, 1).data;
|
|
|
|
|
|
|
|
return [d[0], d[1], d[2]];
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
const lum = (rgb: number[]) => {
|
|
|
|
|
|
|
|
const f = (v: number) => {
|
|
|
|
|
|
|
|
v /= 255;
|
|
|
|
|
|
|
|
return v <= 0.03928 ? v / 12.92 : ((v + 0.055) / 1.055) ** 2.4;
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
return 0.2126 * f(rgb[0]) + 0.7152 * f(rgb[1]) + 0.0722 * f(rgb[2]);
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
const contraste = (c: string | null) => {
|
|
|
|
|
|
|
|
const [a, b] = [lum(aRgb(c)), lum(aRgb(fondo))].sort((m, n) => n - m);
|
|
|
|
|
|
|
|
return (a + 0.05) / (b + 0.05);
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
|
|
|
recurso: new URL(logo.src).pathname,
|
|
|
|
|
|
|
|
cuantas: colores.length,
|
|
|
|
|
|
|
|
minimo: Math.min(...colores.map(contraste))
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
expect(peor.recurso).toMatch(/senza-paura-logo.*\.svg$/);
|
|
|
|
expect(resultado.etiqueta).toBe('svg');
|
|
|
|
expect(peor.cuantas).toBeGreaterThanOrEqual(3);
|
|
|
|
expect(resultado.relleno).toBe(resultado.color);
|
|
|
|
expect(peor.minimo).toBeGreaterThan(MINIMO);
|
|
|
|
expect(resultado.color).not.toBe(resultado.base);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|