1- import { addTags } from '../src/entry-editable'
1+ import { addTags , getTag } from '../src/entry-editable'
22import { entry_global_field , entry_global_field_multiple , entry_modular_block , entry_reference , entry_with_text , entry_with_applied_variants , entry_with_parent_path_variants } from './mock/entry-editable-mock'
33
44describe ( 'Entry editable test' , ( ) => {
@@ -519,6 +519,91 @@ describe('Entry editable test', () => {
519519 } )
520520 } )
521521
522+ describe ( 'Null and undefined content handling (Issue #193)' , ( ) => {
523+ it ( 'should not throw when entry has a null field value' , done => {
524+ const entryWithNullField : any = {
525+ "uid" : "entry_uid_null" ,
526+ "locale" : "en-us" ,
527+ "title" : "Valid title" ,
528+ "description" : null
529+ }
530+
531+ expect ( ( ) => addTags ( entryWithNullField , 'content_type' , false ) ) . not . toThrow ( )
532+ expect ( ( entryWithNullField as any ) [ '$' ] [ 'title' ] ) . toEqual ( 'data-cslp=content_type.entry_uid_null.en-us.title' )
533+ done ( )
534+ } )
535+
536+ it ( 'should not throw when entry has an undefined field value' , done => {
537+ const entryWithUndefinedField : any = {
538+ "uid" : "entry_uid_undef" ,
539+ "locale" : "en-us" ,
540+ "title" : "Valid title" ,
541+ "description" : undefined
542+ }
543+
544+ expect ( ( ) => addTags ( entryWithUndefinedField , 'content_type' , false ) ) . not . toThrow ( )
545+ expect ( ( entryWithUndefinedField as any ) [ '$' ] [ 'title' ] ) . toEqual ( 'data-cslp=content_type.entry_uid_undef.en-us.title' )
546+ done ( )
547+ } )
548+
549+ it ( 'should return empty tags for a null entry' , done => {
550+ const nullEntry : any = null
551+
552+ expect ( ( ) => addTags ( nullEntry , 'content_type' , false ) ) . not . toThrow ( )
553+ done ( )
554+ } )
555+
556+ it ( 'should return empty tags for an undefined entry' , done => {
557+ const undefinedEntry : any = undefined
558+
559+ expect ( ( ) => addTags ( undefinedEntry , 'content_type' , false ) ) . not . toThrow ( )
560+ done ( )
561+ } )
562+
563+ it ( 'should handle entry with multiple null field values' , done => {
564+ const entryWithMultipleNulls : any = {
565+ "uid" : "entry_uid_multi_null" ,
566+ "locale" : "en-us" ,
567+ "title" : "Valid title" ,
568+ "field_a" : null ,
569+ "field_b" : null ,
570+ "field_c" : "valid"
571+ }
572+
573+ expect ( ( ) => addTags ( entryWithMultipleNulls , 'content_type' , true ) ) . not . toThrow ( )
574+ expect ( ( entryWithMultipleNulls as any ) [ '$' ] [ 'title' ] ) . toEqual ( { 'data-cslp' : 'content_type.entry_uid_multi_null.en-us.title' } )
575+ expect ( ( entryWithMultipleNulls as any ) [ '$' ] [ 'field_c' ] ) . toEqual ( { 'data-cslp' : 'content_type.entry_uid_multi_null.en-us.field_c' } )
576+ done ( )
577+ } )
578+
579+ it ( 'should handle entry with nested null object' , done => {
580+ const entryWithNestedNull : any = {
581+ "uid" : "entry_uid_nested_null" ,
582+ "locale" : "en-us" ,
583+ "title" : "Valid title" ,
584+ "group" : null
585+ }
586+
587+ expect ( ( ) => addTags ( entryWithNestedNull , 'content_type' , false ) ) . not . toThrow ( )
588+ expect ( ( entryWithNestedNull as any ) [ '$' ] [ 'title' ] ) . toEqual ( 'data-cslp=content_type.entry_uid_nested_null.en-us.title' )
589+ done ( )
590+ } )
591+
592+ it ( 'getTag with null content returns empty object (covers null guard)' , done => {
593+ const appliedVariants = { _applied_variants : { } , shouldApplyVariant : false , metaKey : '' }
594+ const result = getTag ( null as any , 'some.prefix' , false , 'en-us' , appliedVariants )
595+ expect ( result ) . toEqual ( { } )
596+ done ( )
597+ } )
598+
599+ it ( 'getTag with undefined content returns empty object (covers null guard)' , done => {
600+ const appliedVariants = { _applied_variants : { } , shouldApplyVariant : false , metaKey : '' }
601+ const result = getTag ( undefined as any , 'some.prefix' , true , 'en-us' , appliedVariants )
602+ expect ( result ) . toEqual ( { } )
603+ done ( )
604+ } )
605+ } )
606+
522607 describe ( 'useLowerCaseLocale option' , ( ) => {
523608 it ( 'should preserve locale casing when useLowerCaseLocale is false' , done => {
524609 const entry = {
@@ -560,4 +645,73 @@ describe('Entry editable test', () => {
560645 } )
561646 } )
562647
648+ describe ( 'Negative and corner cases' , ( ) => {
649+ it ( 'addTags with empty entry object should not throw and should set $ with empty-like tags' , done => {
650+ const emptyEntry = { uid : 'e1' , locale : 'en-us' }
651+ expect ( ( ) => addTags ( emptyEntry , 'ct' , false ) ) . not . toThrow ( )
652+ expect ( ( emptyEntry as any ) . $ ) . toBeDefined ( )
653+ expect ( typeof ( emptyEntry as any ) . $ ) . toBe ( 'object' )
654+ done ( )
655+ } )
656+
657+ it ( 'addTags with empty string contentTypeUid should normalize to lowercase' , done => {
658+ const entry = { uid : 'u1' , locale : 'en-us' , title : 't' }
659+ addTags ( entry , '' , false )
660+ expect ( ( entry as any ) [ '$' ] [ 'title' ] ) . toContain ( '.title' )
661+ done ( )
662+ } )
663+
664+ it ( 'addTags with options as undefined should not throw' , done => {
665+ const entry = { uid : 'u1' , locale : 'en-us' , title : 't' }
666+ expect ( ( ) => addTags ( entry , 'ct' , false , 'en-us' , undefined ) ) . not . toThrow ( )
667+ expect ( ( entry as any ) [ '$' ] [ 'title' ] ) . toBeDefined ( )
668+ done ( )
669+ } )
670+
671+ it ( 'getTag with empty object content should return empty tags object' , done => {
672+ const appliedVariants = { _applied_variants : { } , shouldApplyVariant : false , metaKey : '' }
673+ const result = getTag ( { } , 'prefix' , false , 'en-us' , appliedVariants )
674+ expect ( result ) . toEqual ( { } )
675+ done ( )
676+ } )
677+
678+ it ( 'getTag with content that has only $ key should skip $ and return empty' , done => {
679+ const appliedVariants = { _applied_variants : { } , shouldApplyVariant : false , metaKey : '' }
680+ const result = getTag ( { $ : 'ignored' } , 'prefix' , false , 'en-us' , appliedVariants )
681+ expect ( result ) . toEqual ( { } )
682+ done ( )
683+ } )
684+
685+ it ( 'getTag with appliedVariants._applied_variants null should not throw (getParentVariantisedPath safety)' , done => {
686+ const content = { field : 'value' }
687+ const appliedVariants = { _applied_variants : null as any , shouldApplyVariant : true , metaKey : 'field' }
688+ expect ( ( ) => getTag ( content , 'prefix' , false , 'en-us' , appliedVariants ) ) . not . toThrow ( )
689+ const result = getTag ( content , 'prefix' , false , 'en-us' , appliedVariants )
690+ expect ( result ) . toHaveProperty ( 'field' )
691+ done ( )
692+ } )
693+
694+ it ( 'getTag with appliedVariants.metaKey empty and shouldApplyVariant true should still produce tags' , done => {
695+ const content = { title : 'hello' }
696+ const appliedVariants = { _applied_variants : { } , shouldApplyVariant : true , metaKey : '' }
697+ const result = getTag ( content , 'ct.uid.en-us' , false , 'en-us' , appliedVariants )
698+ expect ( result ) . toHaveProperty ( 'title' )
699+ expect ( ( result as any ) . title ) . toContain ( 'title' )
700+ done ( )
701+ } )
702+
703+ it ( 'addTags with entry that has empty array field should not throw' , done => {
704+ const entry : any = { uid : 'u1' , locale : 'en-us' , items : [ ] }
705+ expect ( ( ) => addTags ( entry , 'ct' , false ) ) . not . toThrow ( )
706+ expect ( ( entry as any ) [ '$' ] [ 'items' ] ) . toBeDefined ( )
707+ done ( )
708+ } )
709+
710+ it ( 'addTags with entry that has nested null object value should not throw' , done => {
711+ const entry : any = { uid : 'u1' , locale : 'en-us' , title : 't' , nested : null }
712+ expect ( ( ) => addTags ( entry , 'ct' , true ) ) . not . toThrow ( )
713+ expect ( ( entry as any ) [ '$' ] [ 'title' ] ) . toEqual ( { 'data-cslp' : expect . stringContaining ( 'title' ) } )
714+ done ( )
715+ } )
716+ } )
563717} )
0 commit comments