@@ -3,6 +3,8 @@ import { mkdirSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from 'nod
33import os from 'node:os'
44import path from 'node:path'
55import { fileURLToPath } from 'node:url'
6+ import { createElement } from 'react'
7+ import { renderToStaticMarkup } from 'react-dom/server'
68import { afterAll , expect , test } from 'vitest'
79import { findingFingerprint } from '#control-analysis/review-ledger'
810import { ciRefs , warningExitCode } from '#design-conformance/ci'
@@ -307,6 +309,75 @@ throw new Error('Product source must not execute')
307309 }
308310)
309311
312+ test . each ( [
313+ [ 'grid line integer' , 'gridColumnStart' , 'grid-column-start' , '1' , 1 , '' ] ,
314+ [ 'grid row integer' , 'gridRowEnd' , 'grid-row-end' , '3' , 3 , '' ] ,
315+ [ 'animation count' , 'animationIterationCount' , 'animation-iteration-count' , '2' , 2 , '' ] ,
316+ [ 'border image ratio' , 'borderImageSlice' , 'border-image-slice' , '2' , 2 , '' ] ,
317+ [ 'vendor line clamp' , 'WebkitLineClamp' , '-webkit-line-clamp' , '2' , 2 , '' ] ,
318+ [ 'font weight' , 'fontWeight' , 'font-weight' , '600' , 600 , '' ] ,
319+ [ 'ordinary dimension' , 'width' , 'width' , '1' , 1 , '' ] ,
320+ [ 'numeric string dimension' , 'width' , 'width' , "'1'" , '1' , '' ] ,
321+ [ 'numeric alias dimension' , 'height' , 'height' , 'size' , 4 , 'const size=4;' ] ,
322+ [ 'string member dimension' , 'height' , 'height' , 'sizes.small' , '4' , "const sizes={small:'4'};" ] ,
323+ [ 'typed grid alias' , 'gridColumnEnd' , 'grid-column-end' , 'line' , 2 , 'const line=2 as const;' ] ,
324+ [ 'numeric custom variable' , '--reserve' , '--reserve' , '1' , 1 , '' ] ,
325+ ] as const ) (
326+ 'React numeric style serialization survives the real CLI: %s' ,
327+ ( _name , property , cssProperty , value , runtimeValue , prefix ) => {
328+ const { repo } = fixture ( )
329+ writeFileSync ( path . join ( repo , ui ) , 'const A=()=> <button/>' )
330+ const base = commit ( repo )
331+ writeFileSync (
332+ path . join ( repo , ui ) ,
333+ `${ prefix } const A=()=> <button style={{'${ property } ':${ value } }}/>`
334+ )
335+ const result = run ( [
336+ '--repo' ,
337+ repo ,
338+ '--base' ,
339+ base ,
340+ '--working-tree' ,
341+ '--policy' ,
342+ 'appearance' ,
343+ '--format' ,
344+ 'json' ,
345+ ] )
346+ expect ( result . status , result . stderr ) . toBe ( 1 )
347+ const report = JSON . parse ( result . stdout ) as Report
348+ expect ( report . status ) . toBe ( 'completed' )
349+ const rendered = renderToStaticMarkup (
350+ createElement ( 'button' , { style : { [ property ] : runtimeValue } } )
351+ )
352+ const reactValue = rendered . match ( / s t y l e = " [ ^ : " ] + : ( [ ^ " ] * ) " / ) ?. [ 1 ]
353+ expect ( reactValue ) . toBeTypeOf ( 'string' )
354+ expect ( report . findings . find ( ( finding ) => finding . property === cssProperty ) ?. value ) . toBe (
355+ JSON . stringify ( [ reactValue ] )
356+ )
357+ }
358+ )
359+
360+ test ( 'central numeric-looking style references keep their scalar type ambiguity explicit through the real CLI' , ( ) => {
361+ const { repo } = fixture ( )
362+ mkdirSync ( path . join ( repo , 'packages/emcn/src' ) , { recursive : true } )
363+ writeFileSync ( path . join ( repo , 'packages/emcn/src/index.ts' ) , 'export const dimension=3' )
364+ writeFileSync ( path . join ( repo , ui ) , 'const A=()=> <button/>' )
365+ const base = commit ( repo )
366+ writeFileSync (
367+ path . join ( repo , ui ) ,
368+ "import {dimension} from '@sim/emcn';const A=()=> <button style={{width:dimension}}/>"
369+ )
370+ const result = run ( [ '--repo' , repo , '--base' , base , '--working-tree' , '--format' , 'json' ] )
371+ expect ( [ 0 , 1 ] , result . stderr ) . toContain ( result . status )
372+ const report = JSON . parse ( result . stdout ) as Report
373+ expect ( report . status ) . toBe ( 'completed' )
374+ expect (
375+ report . unchecked . some ( ( note ) =>
376+ note . reason . includes ( 'Central numeric-looking style value has unknown scalar type' )
377+ )
378+ ) . toBe ( true )
379+ } )
380+
310381test ( 'working-tree mode includes a changed central contract registry' , ( ) => {
311382 const { repo } = fixture ( )
312383 const file = 'scripts/design-conformance/contracts.json'
0 commit comments