Skip to content

Commit

Permalink
consistent handling of null/undefined values
Browse files Browse the repository at this point in the history
  • Loading branch information
mimecorg committed Sep 5, 2024
1 parent db414ac commit a1ef68b
Show file tree
Hide file tree
Showing 6 changed files with 67 additions and 8 deletions.
8 changes: 5 additions & 3 deletions packages/leaner/src/web/classes.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,17 @@ export function setClasses( element, classes ) {
if ( Array.isArray( value ) ) {
element.className = '';
element.classList.add( ...value );
} else {
} else if ( value != null ) {
element.className = value;
} else {
element.removeAttribute( 'class' );
}
} );
} else if ( isPlainObject( classes ) ) {
setClassesObject( element, classes );
} else if ( Array.isArray( classes ) ) {
setClassesArray( element, classes );
} else {
} else if ( classes != null ) {
element.className = classes;
}
}
Expand Down Expand Up @@ -54,7 +56,7 @@ function setClassesArray( element, classes ) {
} );
} else if ( isPlainObject( item ) ) {
setClassesObject( element, item );
} else {
} else if ( item != null ) {
element.classList.add( item );
}
}
Expand Down
4 changes: 2 additions & 2 deletions packages/leaner/src/web/make.js
Original file line number Diff line number Diff line change
Expand Up @@ -97,9 +97,9 @@ function setElementProperty( element, key, value ) {
element.addEventListener( key.substring( 2 ), value );
} else if ( Properties.has( key ) ) {
if ( typeof value == 'function' )
reactive( value, value => element[ key ] = value );
reactive( value, value => element[ key ] = value != null ? value : '' );
else
element[ key ] = value;
element[ key ] = value != null ? value : '';
} else {
if ( typeof value == 'function' )
reactive( value, value => setElementAttribute( element, key, value ) );
Expand Down
10 changes: 7 additions & 3 deletions packages/leaner/src/web/styles.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,27 +8,31 @@ export function setStyles( element, styles ) {
element.style = '';
for ( const [ key, value ] of Object.entries( value ) )
setStyleProperty( element, key, value );
} else {
} else if ( value != null ) {
element.style = value;
} else {
element.removeAttribute( 'style' );
}
} );
} else if ( isPlainObject( styles ) ) {
setStylesObject( element, styles );
} else {
} else if ( styles != null ) {
element.style = styles;
}
}

function setStylesObject( element, styles ) {
for ( const [ key, value ] of Object.entries( styles ) ) {
if ( typeof value == 'function' )
reactive( value, value => element.style[ key ] = value );
reactive( value, value => setStyleProperty( element, key, value ) );
else
setStyleProperty( element, key, value );
}
}

function setStyleProperty( element, key, value ) {
if ( value == null )
value = '';
if ( key.startsWith( '--' ) )
element.style.setProperty( key, value );
else
Expand Down
12 changes: 12 additions & 0 deletions packages/leaner/test/web/classes.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,24 @@ describe( 'classes', () => {
expect( element.className ).toBe( 'btn-primary is-large' );
} );

test( 'undefined', () => {
const element = make( [ 'button', { type: 'button', class: undefined } ] );

expect( element.outerHTML ).toBe( '<button type="button"></button>' );
} );

test( 'static array', () => {
const element = make( [ 'button', { type: 'button', class: [ 'btn-primary', 'is-large' ] } ] );

expect( element.className ).toBe( 'btn-primary is-large' );
} );

test( 'static array with undefined', () => {
const element = make( [ 'button', { type: 'button', class: [ 'btn-primary', 'is-large', undefined ] } ] );

expect( element.className ).toBe( 'btn-primary is-large' );
} );

test( 'dynamic value', () => {
const [ value, setValue ] = state( 'btn-primary' );

Expand Down
21 changes: 21 additions & 0 deletions packages/leaner/test/web/make.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,13 @@ describe( 'make()', () => {
expect( element.value ).toBe( 'hello' );
} );

test( 'undefined value', () => {
const element = make( [ 'input', { value: undefined } ] );

expect( element ).toBeInstanceOf( HTMLInputElement );
expect( element.value ).toBe( '' );
} );

test( 'dynamic content', () => {
const [ value, setValue ] = state( 'test' );

Expand All @@ -62,6 +69,13 @@ describe( 'make()', () => {
expect( element.textContent ).toBe( 'hello' );
} );

test( 'undefined content', () => {
const element = make( [ 'p', undefined ] );

expect( element ).toBeInstanceOf( HTMLElement );
expect( element.textContent ).toBe( '' );
} );

test( 'dynamic attribute', () => {
const [ value, setValue ] = state( 'test' );

Expand All @@ -77,6 +91,13 @@ describe( 'make()', () => {
expect( element.outerHTML ).toBe( '<label for="world">hello</label>' );
} );

test( 'undefined attribute', () => {
const element = make( [ 'label', { for: undefined }, 'hello' ] );

expect( element ).toBeInstanceOf( HTMLLabelElement );
expect( element.outerHTML ).toBe( '<label>hello</label>' );
} );

test( 'remove attribute', () => {
const [ value, setValue ] = state( 'test' );

Expand Down
20 changes: 20 additions & 0 deletions packages/leaner/test/web/styles.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,12 @@ describe( 'styles', () => {
expect( element.style.display ).toBe( 'none' );
} );

test( 'undefined', () => {
const element = make( [ 'button', { type: 'button', style: undefined } ] );

expect( element.outerHTML ).toBe( '<button type="button"></button>' );
} );

test( 'static object', () => {
const element = make( [ 'button', { type: 'button', style: { display: 'none' } } ] );

Expand Down Expand Up @@ -44,5 +50,19 @@ describe( 'styles', () => {
expect( element.style.display ).toBe( 'inline' );
} );

test( 'dynamic object with undefined', () => {
const [ value, setValue ] = state( 'none' );

const element = make( [ 'button', { type: 'button', style: { display: value } } ] );

expect( element.style.display ).toBe( 'none' );

setValue( undefined );

runSchedule();

expect( element.style.display ).toBe( '' );
} );

// NOTE: custom properties cannot be tested because of https://github.com/jsdom/jsdom/issues/1895
} );

0 comments on commit a1ef68b

Please sign in to comment.