@@ -380,3 +380,110 @@ def test_networkx_algorithm():
380380 )
381381 # Expect two equally short paths: A->B->C (10+4=14) and A->BB->C (10+4=14)
382382 assert sorted (all_sp ) == sorted ([["A" , "B" , "C" ], ["A" , "BB" , "C" ]])
383+
384+
385+ def test_to_dict ():
386+ """Test that to_dict() returns proper node-link format for JSON serialization."""
387+ g = StrictMultiDiGraph ()
388+
389+ # Test empty graph
390+ result = g .to_dict ()
391+ assert result == {"graph" : {}, "nodes" : [], "links" : []}
392+
393+ # Add nodes with attributes
394+ g .add_node ("A" , type = "router" , location = "rack1" )
395+ g .add_node ("B" , type = "switch" , location = "rack2" )
396+ g .add_node ("C" , type = "server" )
397+
398+ # Add edges with attributes
399+ e1 = g .add_edge ("A" , "B" , capacity = 100 , cost = 5 )
400+ e2 = g .add_edge ("B" , "C" , capacity = 50 , cost = 2 )
401+ e3 = g .add_edge ("A" , "C" , capacity = 25 ) # No cost attribute
402+
403+ result = g .to_dict ()
404+
405+ # Verify structure
406+ assert "graph" in result
407+ assert "nodes" in result
408+ assert "links" in result
409+
410+ # Verify graph attributes (should be empty for this test)
411+ assert result ["graph" ] == {}
412+
413+ # Verify nodes
414+ assert len (result ["nodes" ]) == 3
415+ node_ids = [node ["id" ] for node in result ["nodes" ]]
416+ assert set (node_ids ) == {"A" , "B" , "C" }
417+
418+ # Find specific nodes and verify their attributes
419+ node_a = next (n for n in result ["nodes" ] if n ["id" ] == "A" )
420+ assert node_a ["attr" ] == {"type" : "router" , "location" : "rack1" }
421+
422+ node_b = next (n for n in result ["nodes" ] if n ["id" ] == "B" )
423+ assert node_b ["attr" ] == {"type" : "switch" , "location" : "rack2" }
424+
425+ node_c = next (n for n in result ["nodes" ] if n ["id" ] == "C" )
426+ assert node_c ["attr" ] == {"type" : "server" }
427+
428+ # Verify edges
429+ assert len (result ["links" ]) == 3
430+
431+ # Create a mapping from node ID to index for edge verification
432+ node_indices = {node ["id" ]: i for i , node in enumerate (result ["nodes" ])}
433+
434+ # Find specific edges by their keys and verify attributes
435+ edge_by_key = {link ["key" ]: link for link in result ["links" ]}
436+
437+ assert e1 in edge_by_key
438+ e1_link = edge_by_key [e1 ]
439+ assert e1_link ["source" ] == node_indices ["A" ]
440+ assert e1_link ["target" ] == node_indices ["B" ]
441+ assert e1_link ["attr" ] == {"capacity" : 100 , "cost" : 5 }
442+
443+ assert e2 in edge_by_key
444+ e2_link = edge_by_key [e2 ]
445+ assert e2_link ["source" ] == node_indices ["B" ]
446+ assert e2_link ["target" ] == node_indices ["C" ]
447+ assert e2_link ["attr" ] == {"capacity" : 50 , "cost" : 2 }
448+
449+ assert e3 in edge_by_key
450+ e3_link = edge_by_key [e3 ]
451+ assert e3_link ["source" ] == node_indices ["A" ]
452+ assert e3_link ["target" ] == node_indices ["C" ]
453+ assert e3_link ["attr" ] == {"capacity" : 25 }
454+
455+
456+ def test_to_dict_with_graph_attributes ():
457+ """Test to_dict() with graph-level attributes."""
458+ g = StrictMultiDiGraph (name = "test_network" , version = "1.0" )
459+ g .add_node ("A" )
460+ g .add_node ("B" )
461+ g .add_edge ("A" , "B" )
462+
463+ result = g .to_dict ()
464+
465+ # Verify graph attributes are included
466+ assert result ["graph" ]["name" ] == "test_network"
467+ assert result ["graph" ]["version" ] == "1.0"
468+ assert len (result ["nodes" ]) == 2
469+ assert len (result ["links" ]) == 1
470+
471+
472+ def test_to_dict_json_serializable ():
473+ """Test that to_dict() output is JSON serializable."""
474+ import json
475+
476+ g = StrictMultiDiGraph ()
477+ g .add_node ("A" , value = 42 , active = True )
478+ g .add_node ("B" , value = 3.14 , tags = ["tag1" , "tag2" ])
479+ g .add_edge ("A" , "B" , weight = 1.5 , metadata = {"created" : "2025-06-13" })
480+
481+ result = g .to_dict ()
482+
483+ # Should be able to serialize to JSON without errors
484+ json_str = json .dumps (result )
485+
486+ # Should be able to round-trip
487+ parsed = json .loads (json_str )
488+ assert parsed ["nodes" ][0 ]["attr" ]["value" ] in [42 , 3.14 ] # Could be in any order
489+ assert len (parsed ["links" ]) == 1
0 commit comments