@@ -53,6 +53,70 @@ def filter_func(u, v, d):
5353 list (filtered_graph .get_graph ().edges (data = True ))[0 ][2 ]["property" ], "A"
5454 )
5555
56+ def test_node_adds_tagged_node_with_coordinates (self ):
57+ class DummyNode :
58+ def __init__ (self , node_id , tags , lon , lat ):
59+ self .id = node_id
60+ self .tags = tags
61+
62+ class Location :
63+ def __init__ (self , lon , lat ):
64+ self .lon = lon
65+ self .lat = lat
66+
67+ self .location = Location (lon , lat )
68+
69+ tagged = DummyNode (101 , {"highway" : "footway" }, - 122.3 , 47.6 )
70+
71+ self .osm_graph .node (tagged )
72+
73+ self .assertIn (101 , self .mock_graph .nodes )
74+ node_data = self .mock_graph .nodes [101 ]
75+ self .assertEqual (node_data ["highway" ], "footway" )
76+ self .assertEqual (node_data ["lon" ], - 122.3 )
77+ self .assertEqual (node_data ["lat" ], 47.6 )
78+
79+ def test_node_skips_existing_identifiers (self ):
80+ self .mock_graph .add_node (202 , lon = 0.0 , lat = 0.0 , name = "original" )
81+
82+ class DummyNode :
83+ def __init__ (self ):
84+ self .id = 202
85+ self .tags = {"name" : "replacement" }
86+
87+ class Location :
88+ lon = 1.0
89+ lat = 1.0
90+
91+ self .location = Location ()
92+
93+ duplicate = DummyNode ()
94+
95+ self .osm_graph .node (duplicate )
96+
97+ node_data = self .mock_graph .nodes [202 ]
98+ self .assertEqual (node_data ["name" ], "original" )
99+ self .assertEqual (node_data ["lon" ], 0.0 )
100+ self .assertEqual (node_data ["lat" ], 0.0 )
101+
102+ def test_node_requires_tags (self ):
103+ class DummyNode :
104+ def __init__ (self ):
105+ self .id = 303
106+ self .tags = {}
107+
108+ class Location :
109+ lon = 2.0
110+ lat = 2.0
111+
112+ self .location = Location ()
113+
114+ empty = DummyNode ()
115+
116+ self .osm_graph .node (empty )
117+
118+ self .assertNotIn (303 , self .mock_graph .nodes )
119+
56120 @patch ('src.osm_osw_reformatter.serializer.osm.osm_graph.mapping' )
57121 def test_to_geojson (self , mock_mapping ):
58122 # Mock mapping function to return a sample GeoJSON structure
@@ -457,16 +521,29 @@ def test_construct_geometries_line_node(self):
457521class TestFromGeoJSON (unittest .TestCase ):
458522 def setUp (self ):
459523 # Create valid test GeoJSON files
460- self .nodes_path = "test_nodes.geojson"
461- self .edges_path = "test_edges.geojson"
524+ self .tempdir = TemporaryDirectory ()
525+ self .nodes_path = os .path .join (self .tempdir .name , "nodes.geojson" )
526+ self .edges_path = os .path .join (self .tempdir .name , "edges.geojson" )
462527
463- self .node_data = {
528+ def tearDown (self ):
529+ self .tempdir .cleanup ()
530+
531+ def _write_geojson (self , node_data , edge_data ):
532+ with open (self .nodes_path , "w" ) as f :
533+ json .dump (node_data , f )
534+
535+ with open (self .edges_path , "w" ) as f :
536+ json .dump (edge_data , f )
537+
538+
539+ def test_from_geojson_populates_graph (self ):
540+ node_data = {
464541 "type" : "FeatureCollection" ,
465542 "features" : [
466543 {
467544 "type" : "Feature" ,
468545 "geometry" : {"type" : "Point" , "coordinates" : [1 , 1 ]},
469- "properties" : {"_id" : "1" , "attribute" : "value1" },
546+ "properties" : {"_id" : "1" , "attribute" : "value1" , "ext:osm_id" : "11" },
470547 },
471548 {
472549 "type" : "Feature" ,
@@ -476,45 +553,88 @@ def setUp(self):
476553 ],
477554 }
478555
479- self . edge_data = {
556+ edge_data = {
480557 "type" : "FeatureCollection" ,
481558 "features" : [
482559 {
483560 "type" : "Feature" ,
484561 "geometry" : {"type" : "LineString" , "coordinates" : [[1 , 1 ], [2 , 2 ]]},
485- "properties" : {"_id" : "1" , "_u_id" : "1" , "_v_id" : "2" , "attribute" : "edge_value" },
562+ "properties" : {
563+ "_id" : "5" ,
564+ "_u_id" : "1" ,
565+ "_v_id" : "2" ,
566+ "attribute" : "edge_value" ,
567+ "ext:osm_id" : "99" ,
568+ },
486569 },
487570 ],
488571 }
489572
490- # Write the data to files
491- with open (self .nodes_path , "w" ) as f :
492- json . dump ( self . node_data , f )
573+ self . _write_geojson ( node_data , edge_data )
574+ osm_graph = OSMGraph . from_geojson (self .nodes_path , self . edges_path )
575+ graph = osm_graph . get_graph ( )
493576
494- with open (self .edges_path , "w" ) as f :
495- json .dump (self .edge_data , f )
577+ self .assertEqual (set (graph .nodes ), {1 , 2 })
578+ node_attrs = graph .nodes [1 ]
579+ self .assertIsInstance (node_attrs ["geometry" ], Point )
580+ self .assertEqual (node_attrs ["lon" ], 1 )
581+ self .assertEqual (node_attrs ["lat" ], 1 )
582+ self .assertEqual (node_attrs ["osm_id" ], 11 )
496583
497- def tearDown (self ):
498- # Clean up files after tests
499- import os
500- if os .path .exists (self .nodes_path ):
501- os .remove (self .nodes_path )
502- if os .path .exists (self .edges_path ):
503- os .remove (self .edges_path )
504-
505- @patch ("src.osm_osw_reformatter.serializer.osm.osm_graph.OSMGraph.from_geojson" )
506- def test_from_geojson (self , mock_from_geojson ):
507- mock_graph = MagicMock ()
508- mock_graph .get_graph .return_value .nodes = {"1" : {"geometry" : Point (1 , 1 )}}
509- mock_graph .get_graph .return_value .edges = {("1" , "2" ): {"geometry" : LineString ([(1 , 1 ), (2 , 2 )])}}
510- mock_from_geojson .return_value = mock_graph
584+ edges = list (graph .edges (keys = True , data = True ))
585+ self .assertEqual (len (edges ), 1 )
586+ u , v , key , attrs = edges [0 ]
587+ self .assertEqual ((u , v , key ), (1 , 2 , 5 ))
588+ self .assertIsInstance (attrs ["geometry" ], LineString )
589+ self .assertEqual (attrs ["osm_id" ], 99 )
590+ self .assertEqual (attrs ["attribute" ], "edge_value" )
591+
592+ def test_from_geojson_preserves_non_numeric_identifiers (self ):
593+ node_data = {
594+ "type" : "FeatureCollection" ,
595+ "features" : [
596+ {
597+ "type" : "Feature" ,
598+ "geometry" : {"type" : "Point" , "coordinates" : [3 , 3 ]},
599+ "properties" : {"_id" : "p123" , "ext:osm_id" : "node-1" },
600+ },
601+ {
602+ "type" : "Feature" ,
603+ "geometry" : {"type" : "Point" , "coordinates" : [4 , 4 ]},
604+ "properties" : {"_id" : "p456" },
605+ },
606+ ],
607+ }
608+
609+ edge_data = {
610+ "type" : "FeatureCollection" ,
611+ "features" : [
612+ {
613+ "type" : "Feature" ,
614+ "geometry" : {"type" : "LineString" , "coordinates" : [[3 , 3 ], [4 , 4 ]]},
615+ "properties" : {
616+ "_id" : "edge-7" ,
617+ "_u_id" : "p123" ,
618+ "_v_id" : "p456" ,
619+ "ext:osm_id" : "edge-A" ,
620+ },
621+ },
622+ ],
623+ }
624+
625+ self ._write_geojson (node_data , edge_data )
511626
512627 osm_graph = OSMGraph .from_geojson (self .nodes_path , self .edges_path )
628+ graph = osm_graph .get_graph ()
629+
630+ self .assertIn ("p123" , graph .nodes )
631+ self .assertEqual (graph .nodes ["p123" ]["osm_id" ], "node-1" )
513632
514- # Assertions
515- self .assertIsNotNone (osm_graph , "OSMGraph object should not be None" )
516- self .assertEqual (len (osm_graph .get_graph ().nodes ), 1 )
517- self .assertEqual (len (osm_graph .get_graph ().edges ), 1 )
633+ edges = list (graph .edges (keys = True , data = True ))
634+ self .assertEqual (len (edges ), 1 )
635+ u , v , key , attrs = edges [0 ]
636+ self .assertEqual ((u , v , key ), ("p123" , "p456" , "edge-7" ))
637+ self .assertEqual (attrs ["osm_id" ], "edge-A" )
518638
519639 def test_tagged_node_parser_skips_non_osw_nodes (self ):
520640 graph = nx .MultiDiGraph ()
0 commit comments