Skip to content

test(helpers): extract synthetic xlsx builders for reuse - #2

Merged
4a4c53 merged 10 commits into
mainfrom
claude/test-coverage-analysis-e3dw9m
Sep 6, 2026
Merged

4a4c53 merged 10 commits into
mainfrom
claude/test-coverage-analysis-e3dw9m

Conversation

@4a4c53

@4a4c53 4a4c53 commented Aug 23, 2026

Copy link
Copy Markdown
Owner

Los constructores de .xlsx de bajo nivel vivían duplicados dentro de hardening.test.ts y no se podían reutilizar desde otros ficheros de test.

El script de test pasa a usar un glob explícito para que node --test no recorra el nuevo directorio de helpers como si fuera un fichero de tests.

claude added 9 commits August 23, 2026 07:48
Los constructores de .xlsx de bajo nivel vivían duplicados dentro de hardening.test.ts y no se podían reutilizar desde otros ficheros de test.

El script de test pasa a usar un glob explícito para que node --test no recorra el nuevo directorio de helpers como si fuera un fichero de tests.
La rama de fórmula de sheetToXml solo escribía <v> para number, string y boolean, y no tenía caso para Date ni else. Un valor cacheado de tipo Date se aceptaba, se guardaba en memoria y desaparecía al serializar: la celda salía como <f> sin <v> y sin estilo, y al releerla el valor era null. No se emitía ningún error.

La lógica de estilo de fecha se extrae a dateCellAttrs() y ahora la comparten las dos ramas. Las celdas de solo fórmula siguen emitiéndose sin <v>.

Cambia los bytes de salida de los libros con fórmulas de fecha: es la corrección de una pérdida de datos, no una regresión.
reader.ts tenía el 68% de ramas cubiertas: inlineStr, t="e", t="str" y t="d" no se leían en ningún test, ni las posiciones implícitas, ni la detección de formatos de fecha personalizados con sus falsos positivos (literales entrecomillados, moneda, secciones entre corchetes).

xml.ts declaraba el 60% de funciones cubiertas: las entidades numéricas y el escape de _xHHHH_ nunca se ejercitaban.

De sheet.ts quedaban sin tocar colCount, la opción headerRow y la semántica de huecos de addRow. Dos tests marcados como LIMITACIÓN fijan el comportamiento actual con cabeceras duplicadas y con __proto__.
Faltaban el techo de bomba de descompresión, la cabecera local corrupta, el fallo de inflado y el método de compresión no soportado.
El desfase por el falso año bisiesto de 1900 y el parámetro epoch1904, ambos documentados en el README, no tenían ninguna aserción.
Hasta ahora todas las entradas de la suite las construía el propio zipSync de minixlsx, así que el lector solo se comprobaba contra la salida exacta de nuestro escritor.

Los dos ficheros aportan estructuras que minixlsx nunca genera: openpyxl escribe las cadenas en línea y sin sharedStrings.xml y deja la fórmula sin valor cacheado; LibreOffice añade docProps/custom.xml, convierte TRUE y FALSE en fórmulas y sí cachea los resultados. Ambos traen sus propias tablas de estilos, que es lo que ejercita de verdad la detección de fechas.

Los .xlsx están versionados: la suite no depende de tener openpyxl ni LibreOffice instalados.
El repositorio no tenía workflows: test, typecheck y lint estaban definidos y no se ejecutaban nunca de forma automática.

La matriz cruza Node 22 y 24 con dos husos horarios, porque la conversión de fechas usa componentes de hora local. Los umbrales de test:coverage van fijados a la cobertura ya alcanzada (99% líneas, 93% ramas, 100% funciones) para que solo pueda subir.
Las celdas de error pierden el marcador t="e" y las fechas ISO t="d" se reescriben como serial del sistema 1900. Ambas conversiones quedan fijadas por tests; documentarlas permite distinguir una decisión intencionada de una regresión.
@4a4c53
4a4c53 force-pushed the claude/test-coverage-analysis-e3dw9m branch from ad362b2 to 1e2a035 Compare August 23, 2026 07:49
La skill prescribía 'git commit --no-gpg-sign' como el comando de commit, con una salida pasiva ('unless repository signing rules override it') que exigía conocer ya las reglas, mientras que el paso de inspección nunca mandaba mirar la configuración de firma. Y el paso 1 metía 'firmar' en la misma lista que amend, rebase y reescritura de historia, como si fuera una operación destructiva.

Ese conjunto llevó a desactivar la firma en un repositorio que la tenía activada por defecto.

Ahora la inspección lee la configuración efectiva en todos los ámbitos, el commit respeta el valor por defecto y la distinción pasa a ser de quién firma: la clave propia del committer, incluida la que gestiona el entorno para el agente, se usa; la clave personal de otra persona no se toca nunca.

Se añade la comprobación de que la firma llegó a incrustarse, apuntando a la cabecera gpgsig en vez de a %G?, que informa de la verificación y devuelve N sin allowedSignersFile aunque la firma sea correcta.
4a4c53 pushed a commit that referenced this pull request Sep 6, 2026
The linear scanner yields an empty inner string for a self-closing
<v /> (openpyxl writes it for formula cells without a cached value),
which Number() turned into 0 and a shared-string lookup into index 0.
The previous regex simply did not match, so the value was null; restore
that behaviour and cover it with the openpyxl shape.

Also mark the items already resolved by PR #2 in the docs backlog.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PsvdZfRkdMH19tw7PyDvRY
@4a4c53
4a4c53 merged commit 40b15f8 into main Sep 6, 2026
5 checks passed
4a4c53 pushed a commit that referenced this pull request Sep 6, 2026
The "limitation" test from PR #2 documented the pre-fix behaviour where a
__proto__ header dropped its column. toObjects() now builds rows with
Object.fromEntries, so replace it with an assertion of the fixed
behaviour: the key is an own property and the prototype is untouched.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PsvdZfRkdMH19tw7PyDvRY
@4a4c53
4a4c53 deleted the claude/test-coverage-analysis-e3dw9m branch September 6, 2026 14:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants