@@ -118,6 +118,13 @@ describe("buildPathOffsetPatches / buildClearPathOffsetPatches", () => {
118118 ] ) ;
119119 } ) ;
120120
121+ it ( "clear: empty STUDIO_ORIGINAL_INLINE_TRANSLATE_ATTR coerces to null (translate not set to empty string)" , ( ) => {
122+ const e = div ( ) ;
123+ e . setAttribute ( STUDIO_ORIGINAL_INLINE_TRANSLATE_ATTR , "" ) ;
124+ const ops = buildClearPathOffsetPatches ( e ) ;
125+ expect ( ops . find ( ( o ) => o . property === "translate" ) ?. value ) . toBeNull ( ) ;
126+ } ) ;
127+
121128 it ( "build/clear symmetry: clear addresses every {type,property} key that build emits" , ( ) => {
122129 const e = populatedPathEl ( ) ;
123130 assertClearCoversKeys ( buildPathOffsetPatches ( e ) , buildClearPathOffsetPatches ( e ) ) ;
@@ -203,22 +210,54 @@ describe("buildBoxSizePatches / buildClearBoxSizePatches", () => {
203210 ] ) ;
204211 } ) ;
205212
206- it ( "clear: restores width and height from orig attrs, nulls all orig attrs" , ( ) => {
213+ it ( "clear(populated): ops follow interleaved restore-then-null order for every orig attr" , ( ) => {
214+ const ops = buildClearBoxSizePatches ( populatedBoxEl ( ) ) ;
215+ expect ( ops ) . toEqual ( [
216+ { type : "inline-style" , property : STUDIO_WIDTH_PROP , value : null } ,
217+ { type : "inline-style" , property : STUDIO_HEIGHT_PROP , value : null } ,
218+ { type : "attribute" , property : STUDIO_BOX_SIZE_ATTR , value : null } ,
219+ { type : "inline-style" , property : "width" , value : "250px" } ,
220+ { type : "attribute" , property : STUDIO_ORIGINAL_WIDTH_ATTR , value : null } ,
221+ { type : "inline-style" , property : "height" , value : "150px" } ,
222+ { type : "attribute" , property : STUDIO_ORIGINAL_HEIGHT_ATTR , value : null } ,
223+ { type : "inline-style" , property : "min-width" , value : "0px" } ,
224+ { type : "attribute" , property : STUDIO_ORIGINAL_MIN_WIDTH_ATTR , value : null } ,
225+ { type : "inline-style" , property : "min-height" , value : "0px" } ,
226+ { type : "attribute" , property : STUDIO_ORIGINAL_MIN_HEIGHT_ATTR , value : null } ,
227+ { type : "inline-style" , property : "max-width" , value : "none" } ,
228+ { type : "attribute" , property : STUDIO_ORIGINAL_MAX_WIDTH_ATTR , value : null } ,
229+ { type : "inline-style" , property : "max-height" , value : "none" } ,
230+ { type : "attribute" , property : STUDIO_ORIGINAL_MAX_HEIGHT_ATTR , value : null } ,
231+ { type : "inline-style" , property : "flex-basis" , value : "0px" } ,
232+ { type : "attribute" , property : STUDIO_ORIGINAL_FLEX_BASIS_ATTR , value : null } ,
233+ { type : "inline-style" , property : "flex-grow" , value : "0" } ,
234+ { type : "attribute" , property : STUDIO_ORIGINAL_FLEX_GROW_ATTR , value : null } ,
235+ { type : "inline-style" , property : "flex-shrink" , value : "1" } ,
236+ { type : "attribute" , property : STUDIO_ORIGINAL_FLEX_SHRINK_ATTR , value : null } ,
237+ { type : "inline-style" , property : "box-sizing" , value : "content-box" } ,
238+ { type : "attribute" , property : STUDIO_ORIGINAL_BOX_SIZING_ATTR , value : null } ,
239+ { type : "inline-style" , property : "scale" , value : "1" } ,
240+ { type : "attribute" , property : STUDIO_ORIGINAL_SCALE_ATTR , value : null } ,
241+ { type : "inline-style" , property : "transform-origin" , value : "50% 50%" } ,
242+ { type : "attribute" , property : STUDIO_ORIGINAL_TRANSFORM_ORIGIN_ATTR , value : null } ,
243+ { type : "inline-style" , property : "display" , value : "flex" } ,
244+ { type : "attribute" , property : STUDIO_ORIGINAL_DISPLAY_ATTR , value : null } ,
245+ { type : "attribute" , property : STUDIO_ORIGINAL_TRANSFORM_DISPLAY_ATTR , value : null } ,
246+ ] ) ;
247+ } ) ;
248+
249+ it ( "clear: empty orig attr coerces to null (style is removed rather than set to empty string)" , ( ) => {
207250 const e = div ( ) ;
208- e . setAttribute ( STUDIO_ORIGINAL_WIDTH_ATTR , "200px" ) ;
209- e . setAttribute ( STUDIO_ORIGINAL_HEIGHT_ATTR , "100px" ) ;
251+ e . setAttribute ( STUDIO_ORIGINAL_WIDTH_ATTR , "" ) ;
210252 const ops = buildClearBoxSizePatches ( e ) ;
211- expect ( ops ) . toEqual (
212- expect . arrayContaining ( [
213- { type : "inline-style" , property : STUDIO_WIDTH_PROP , value : null } ,
214- { type : "inline-style" , property : STUDIO_HEIGHT_PROP , value : null } ,
215- { type : "attribute" , property : STUDIO_BOX_SIZE_ATTR , value : null } ,
216- { type : "inline-style" , property : "width" , value : "200px" } ,
217- { type : "attribute" , property : STUDIO_ORIGINAL_WIDTH_ATTR , value : null } ,
218- { type : "inline-style" , property : "height" , value : "100px" } ,
219- { type : "attribute" , property : STUDIO_ORIGINAL_HEIGHT_ATTR , value : null } ,
220- ] ) ,
221- ) ;
253+ expect ( ops . find ( ( o ) => o . property === "width" ) ?. value ) . toBeNull ( ) ;
254+ } ) ;
255+
256+ it ( "clear: bare element emits only null ops — no style restores fire when orig attrs are absent" , ( ) => {
257+ const ops = buildClearBoxSizePatches ( div ( ) ) ;
258+ // 3 fixed (studio-width, studio-height, box-size marker) + 14 attr-null pushes (one per BOX_SIZE_ORIG_ATTR)
259+ expect ( ops ) . toHaveLength ( 17 ) ;
260+ expect ( ops . every ( ( op ) => op . value === null ) ) . toBe ( true ) ;
222261 } ) ;
223262
224263 it ( "build/clear symmetry: clear addresses every {type,property} key that build emits" , ( ) => {
@@ -288,6 +327,18 @@ describe("buildRotationPatches / buildClearRotationPatches", () => {
288327 ] ) ;
289328 } ) ;
290329
330+ it ( "clear: absent STUDIO_ORIGINAL_ROTATION_TRANSFORM_ORIGIN_ATTR yields null for transform-origin" , ( ) => {
331+ const ops = buildClearRotationPatches ( div ( ) ) ;
332+ expect ( ops . find ( ( o ) => o . property === "transform-origin" ) ?. value ) . toBeNull ( ) ;
333+ } ) ;
334+
335+ it ( "clear: empty STUDIO_ORIGINAL_INLINE_ROTATE_ATTR coerces to null (rotate not set to empty string)" , ( ) => {
336+ const e = div ( ) ;
337+ e . setAttribute ( STUDIO_ORIGINAL_INLINE_ROTATE_ATTR , "" ) ;
338+ const ops = buildClearRotationPatches ( e ) ;
339+ expect ( ops . find ( ( o ) => o . property === "rotate" ) ?. value ) . toBeNull ( ) ;
340+ } ) ;
341+
291342 it ( "build/clear symmetry: clear addresses every {type,property} key that build emits" , ( ) => {
292343 const e = populatedRotEl ( ) ;
293344 assertClearCoversKeys ( buildRotationPatches ( e ) , buildClearRotationPatches ( e ) ) ;
@@ -327,12 +378,14 @@ describe("buildMotionPatches / buildClearMotionPatches", () => {
327378 } ) ;
328379
329380 it ( "clear: always nulls all four motion attrs regardless of element state" , ( ) => {
330- expect ( buildClearMotionPatches ( div ( ) ) ) . toEqual ( [
381+ const expected = [
331382 { type : "attribute" , property : STUDIO_MOTION_ATTR , value : null } ,
332383 { type : "attribute" , property : STUDIO_MOTION_ORIGINAL_TRANSFORM_ATTR , value : null } ,
333384 { type : "attribute" , property : STUDIO_MOTION_ORIGINAL_OPACITY_ATTR , value : null } ,
334385 { type : "attribute" , property : STUDIO_MOTION_ORIGINAL_VISIBILITY_ATTR , value : null } ,
335- ] ) ;
386+ ] ;
387+ expect ( buildClearMotionPatches ( div ( ) ) ) . toEqual ( expected ) ;
388+ expect ( buildClearMotionPatches ( populatedMotionEl ( ) ) ) . toEqual ( expected ) ;
336389 } ) ;
337390
338391 it ( "build/clear symmetry: clear addresses every {type,property} key that build emits" , ( ) => {
0 commit comments