@@ -30,7 +30,7 @@ import { ScvdFormatSpecifier } from '../../../../model/scvd-format-specifier';
3030import { ScvdNode } from '../../../../model/scvd-node' ;
3131import { ScvdMember } from '../../../../model/scvd-member' ;
3232import { ScvdComponentViewer } from '../../../../model/scvd-component-viewer' ;
33- import { ScvdTypedef } from '../../../../model/scvd-typedef' ;
33+ import { ScvdTypedef , ScvdTypedefs } from '../../../../model/scvd-typedef' ;
3434
3535class DummyNode extends ScvdNode {
3636 private _testParent : ScvdNode | undefined ;
@@ -304,16 +304,136 @@ describe('ScvdEvalInterface intrinsics and helpers', () => {
304304 await expect ( evalIf . getElementRef ( base ) ) . resolves . toBeUndefined ( ) ;
305305 } ) ;
306306
307- it ( 'resolveColonPath warns on unsupported path format with more than 2 parts ' , async ( ) => {
307+ it ( 'resolveColonPath attempts enum lookup for 3-part path (falls back gracefully) ' , async ( ) => {
308308 const base = new DummyNode ( 'base' ) ;
309309 const container : RefContainer = { base, current : base , valueType : undefined } ;
310310 const { evalIf } = makeEval ( ) ;
311- jest . spyOn ( componentViewerLogger , 'warn' ) . mockImplementation ( ( ) => { } ) ;
311+ jest . spyOn ( componentViewerLogger , 'error' ) . mockImplementation ( ( ) => { } ) ;
312+ // 3-part path now tries enum resolution; DummyNode root is not ScvdComponentViewer so it fails gracefully
312313 await expect ( evalIf . resolveColonPath ( container , [ 'a' , 'b' , 'c' ] ) ) . resolves . toBeUndefined ( ) ;
313- expect ( componentViewerLogger . warn ) . toHaveBeenCalledWith ( expect . stringContaining ( 'Unsupported colon path format with 3 parts' ) ) ;
314+ expect ( componentViewerLogger . error ) . toHaveBeenCalledWith ( expect . stringContaining ( 'Root is not ScvdComponentViewer' ) ) ;
315+ ( componentViewerLogger . error as unknown as jest . Mock ) . mockRestore ( ) ;
316+ } ) ;
317+
318+ it ( 'resolveColonPath warns on unsupported path format with more than 3 parts' , async ( ) => {
319+ const base = new DummyNode ( 'base' ) ;
320+ const container : RefContainer = { base, current : base , valueType : undefined } ;
321+ const { evalIf } = makeEval ( ) ;
322+ jest . spyOn ( componentViewerLogger , 'warn' ) . mockImplementation ( ( ) => { } ) ;
323+ await expect ( evalIf . resolveColonPath ( container , [ 'a' , 'b' , 'c' , 'd' ] ) ) . resolves . toBeUndefined ( ) ;
324+ expect ( componentViewerLogger . warn ) . toHaveBeenCalledWith ( expect . stringContaining ( 'Unsupported colon path format with 4 parts' ) ) ;
314325 ( componentViewerLogger . warn as unknown as jest . Mock ) . mockRestore ( ) ;
315326 } ) ;
316327
328+ describe ( 'resolveEnumValue (3-part colon path)' , ( ) => {
329+ function buildComponentViewerWithEnum ( opts ?: {
330+ typedefName ?: string ;
331+ memberName ?: string ;
332+ enumName ?: string ;
333+ enumValue ?: number | string ;
334+ skipTypedefs ?: boolean ;
335+ skipTypedef ?: boolean ;
336+ skipMember ?: boolean ;
337+ skipEnum ?: boolean ;
338+ } ) : { root : ScvdComponentViewer ; container : RefContainer } {
339+ const root = new ScvdComponentViewer ( undefined ) ;
340+
341+ if ( ! opts ?. skipTypedefs ) {
342+ const typedefs = new ScvdTypedefs ( root ) ;
343+ ( root as unknown as { _typedefs : ScvdTypedefs } ) . _typedefs = typedefs ;
344+
345+ if ( ! opts ?. skipTypedef ) {
346+ const typedef = new ScvdTypedef ( typedefs ) ;
347+ typedef . name = opts ?. typedefName ?? 'MyType' ;
348+ typedefs . typedef . push ( typedef ) ;
349+
350+ if ( ! opts ?. skipMember ) {
351+ const member = typedef . addMember ( ) ;
352+ member . name = opts ?. memberName ?? 'State' ;
353+
354+ if ( ! opts ?. skipEnum ) {
355+ const enumItem = member . addEnum ( ) ;
356+ enumItem . name = opts ?. enumName ?? 'Active' ;
357+ // Mock getValue on the enum's value expression
358+ const mockValue = opts ?. enumValue ?? 42 ;
359+ jest . spyOn ( enumItem . value , 'getValue' ) . mockResolvedValue (
360+ typeof mockValue === 'number' ? mockValue : mockValue
361+ ) ;
362+ }
363+ }
364+ }
365+ }
366+
367+ // Create a DummyNode whose parent chain leads to root
368+ const base = new DummyNode ( 'child' ) ;
369+ base . setTestParent ( root ) ;
370+ const container : RefContainer = { base, current : base , valueType : undefined } ;
371+ return { root, container } ;
372+ }
373+
374+ it ( 'resolves enum value for valid 3-part colon path' , async ( ) => {
375+ const { container } = buildComponentViewerWithEnum ( {
376+ typedefName : 'TCP_INFO4' ,
377+ memberName : 'State' ,
378+ enumName : 'Closed' ,
379+ enumValue : 1 ,
380+ } ) ;
381+ const { evalIf } = makeEval ( ) ;
382+ await expect ( evalIf . resolveColonPath ( container , [ 'TCP_INFO4' , 'State' , 'Closed' ] ) ) . resolves . toBe ( 1 ) ;
383+ } ) ;
384+
385+ it ( 'returns undefined when typedefs are missing' , async ( ) => {
386+ const { container } = buildComponentViewerWithEnum ( { skipTypedefs : true } ) ;
387+ const { evalIf } = makeEval ( ) ;
388+ jest . spyOn ( componentViewerLogger , 'error' ) . mockImplementation ( ( ) => { } ) ;
389+ await expect ( evalIf . resolveColonPath ( container , [ 'a' , 'b' , 'c' ] ) ) . resolves . toBeUndefined ( ) ;
390+ expect ( componentViewerLogger . error ) . toHaveBeenCalledWith ( expect . stringContaining ( 'No typedefs found' ) ) ;
391+ ( componentViewerLogger . error as unknown as jest . Mock ) . mockRestore ( ) ;
392+ } ) ;
393+
394+ it ( 'returns undefined when typedef not found' , async ( ) => {
395+ const { container } = buildComponentViewerWithEnum ( { typedefName : 'Existing' } ) ;
396+ const { evalIf } = makeEval ( ) ;
397+ jest . spyOn ( componentViewerLogger , 'error' ) . mockImplementation ( ( ) => { } ) ;
398+ await expect ( evalIf . resolveColonPath ( container , [ 'NonExistent' , 'State' , 'Active' ] ) ) . resolves . toBeUndefined ( ) ;
399+ expect ( componentViewerLogger . error ) . toHaveBeenCalledWith ( expect . stringContaining ( 'Typedef "NonExistent" not found' ) ) ;
400+ ( componentViewerLogger . error as unknown as jest . Mock ) . mockRestore ( ) ;
401+ } ) ;
402+
403+ it ( 'returns undefined when member not found in typedef' , async ( ) => {
404+ const { container } = buildComponentViewerWithEnum ( { typedefName : 'MyType' , memberName : 'State' } ) ;
405+ const { evalIf } = makeEval ( ) ;
406+ jest . spyOn ( componentViewerLogger , 'error' ) . mockImplementation ( ( ) => { } ) ;
407+ await expect ( evalIf . resolveColonPath ( container , [ 'MyType' , 'WrongMember' , 'Active' ] ) ) . resolves . toBeUndefined ( ) ;
408+ expect ( componentViewerLogger . error ) . toHaveBeenCalledWith ( expect . stringContaining ( 'Member "WrongMember" not found' ) ) ;
409+ ( componentViewerLogger . error as unknown as jest . Mock ) . mockRestore ( ) ;
410+ } ) ;
411+
412+ it ( 'returns undefined when enum not found in member' , async ( ) => {
413+ const { container } = buildComponentViewerWithEnum ( { enumName : 'Active' } ) ;
414+ const { evalIf } = makeEval ( ) ;
415+ jest . spyOn ( componentViewerLogger , 'error' ) . mockImplementation ( ( ) => { } ) ;
416+ await expect ( evalIf . resolveColonPath ( container , [ 'MyType' , 'State' , 'WrongEnum' ] ) ) . resolves . toBeUndefined ( ) ;
417+ expect ( componentViewerLogger . error ) . toHaveBeenCalledWith ( expect . stringContaining ( 'Enum "WrongEnum" not found' ) ) ;
418+ ( componentViewerLogger . error as unknown as jest . Mock ) . mockRestore ( ) ;
419+ } ) ;
420+
421+ it ( 'returns undefined when enum value is not a number' , async ( ) => {
422+ const { container } = buildComponentViewerWithEnum ( { enumValue : 'not-a-number' as unknown as number } ) ;
423+ const { evalIf } = makeEval ( ) ;
424+ jest . spyOn ( componentViewerLogger , 'warn' ) . mockImplementation ( ( ) => { } ) ;
425+ await expect ( evalIf . resolveColonPath ( container , [ 'MyType' , 'State' , 'Active' ] ) ) . resolves . toBeUndefined ( ) ;
426+ expect ( componentViewerLogger . warn ) . toHaveBeenCalledWith ( expect . stringContaining ( 'value is not a number' ) ) ;
427+ ( componentViewerLogger . warn as unknown as jest . Mock ) . mockRestore ( ) ;
428+ } ) ;
429+
430+ it ( 'returns enum value 0 correctly (falsy but valid)' , async ( ) => {
431+ const { container } = buildComponentViewerWithEnum ( { enumValue : 0 } ) ;
432+ const { evalIf } = makeEval ( ) ;
433+ await expect ( evalIf . resolveColonPath ( container , [ 'MyType' , 'State' , 'Active' ] ) ) . resolves . toBe ( 0 ) ;
434+ } ) ;
435+ } ) ;
436+
317437 it ( 'read/write value wrap host errors' , async ( ) => {
318438 const memHost = {
319439 readValue : jest . fn ( ( ) => { throw new Error ( 'boom' ) ; } ) ,
0 commit comments