From bd16de2aa32fa3f789a8e0d67c6dae20788318b4 Mon Sep 17 00:00:00 2001 From: erikgh Date: Fri, 31 Jul 2026 11:14:02 -0600 Subject: [PATCH] fix(grafico): SecuenciaClaridad usa el grosor de su propia barra MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cada línea resuelta tomaba el grosor de LINEAS_SIMBOLO[0] sin importar a qué barra pertenecía; funcionaba por coincidencia porque las tres barras del manual comparten height: 8. Se indexa ahora por DISPERSAS[i].barra, y se agrega una prueba de regresión que fija el grosor de cada línea al de su propia barra (derivado de LINEAS_SIMBOLO, no hardcodeado). --- components/primitives/SecuenciaClaridad.tsx | 3 +- .../__tests__/SecuenciaClaridad.test.tsx | 37 ++++++++++++++++++- 2 files changed, 38 insertions(+), 2 deletions(-) diff --git a/components/primitives/SecuenciaClaridad.tsx b/components/primitives/SecuenciaClaridad.tsx index 0e1e4ae..0241734 100644 --- a/components/primitives/SecuenciaClaridad.tsx +++ b/components/primitives/SecuenciaClaridad.tsx @@ -80,7 +80,8 @@ export function SecuenciaClaridad({ }; }; - const grosor = (i: number) => (completa && SOBREVIVE.includes(i) ? LINEAS_SIMBOLO[0].grosor : 1.5); + const grosor = (i: number) => + completa && SOBREVIVE.includes(i) ? LINEAS_SIMBOLO[DISPERSAS[i].barra].grosor : 1.5; // Reduced motion renders plain elements: motion.line would apply its // own dash scaffolding and leave the drawing invisible (see the same trap in diff --git a/components/primitives/__tests__/SecuenciaClaridad.test.tsx b/components/primitives/__tests__/SecuenciaClaridad.test.tsx index 946ac8d..4b62603 100644 --- a/components/primitives/__tests__/SecuenciaClaridad.test.tsx +++ b/components/primitives/__tests__/SecuenciaClaridad.test.tsx @@ -1,8 +1,14 @@ import { render } from '@testing-library/react'; -import { describe, it, expect } from 'vitest'; +import { describe, it, expect, afterEach } from 'vitest'; import { SecuenciaClaridad } from '../SecuenciaClaridad'; +import { LINEAS_SIMBOLO } from '@/lib/simbolo'; describe('', () => { + const matchMediaOriginal = window.matchMedia; + afterEach(() => { + window.matchMedia = matchMediaOriginal; + }); + it('is decorative: hidden from assistive tech', () => { const { container } = render(); const svg = container.querySelector('svg'); @@ -21,6 +27,35 @@ describe('', () => { expect(resolucion).toHaveLength(3); }); + it('gives each resolved line its own bar\'s stroke width, not the first bar\'s', () => { + // Force the reduced-motion branch: it is the only one where stroke-width + // is a literal DOM attribute rather than a Framer Motion `animate` target + // jsdom's inert IntersectionObserver stub never resolves (see + // lib/__tests__/motion.test.tsx), so the animated branch's `enVista` never + // flips true and its resolved strokeWidth is unreachable from the DOM. + window.matchMedia = (query: string) => + ({ + matches: true, + media: query, + onchange: null, + addEventListener: () => {}, + removeEventListener: () => {}, + addListener: () => {}, + removeListener: () => {}, + dispatchEvent: () => false, + }) as unknown as MediaQueryList; + + const { container } = render(); + const resueltas = container.querySelectorAll('[data-resolucion]'); + expect(resueltas).toHaveLength(3); + + // The three survivors appear in document order following DISPERSAS, one + // per group, so they line up 1:1 with the symbol's own three bars. + resueltas.forEach((linea, i) => { + expect(linea).toHaveAttribute('stroke-width', String(LINEAS_SIMBOLO[i].grosor)); + }); + }); + it('leaves the tension unresolved in the hero variant', () => { const { container } = render(); expect(container.querySelectorAll('[data-resolucion]')).toHaveLength(0);