response_test.go

  1package graphhopper
  2
  3import (
  4	"encoding/json"
  5	"testing"
  6
  7	"github.com/stretchr/testify/assert"
  8	"github.com/stretchr/testify/require"
  9)
 10
 11// helper to create GeoJSON LineString from coordinates
 12func mustMarshalGeoJSON(coords [][]float64) json.RawMessage {
 13	geoJSON := map[string]interface{}{
 14		"type":        "LineString",
 15		"coordinates": coords,
 16	}
 17	b, _ := json.Marshal(geoJSON)
 18	return b
 19}
 20
 21func TestResponse_decode_points_and_elevation(t *testing.T) {
 22	// Graphhopper API returns GeoJSON LineString: {"type":"LineString","coordinates":[[lon, lat, elevation], ...]}
 23	points := [][]float64{
 24		{-74.006, 40.7128, 10.5},   // NYC point with elevation
 25		{-118.2437, 34.0522, 89.0}, // LA point with elevation
 26		{-87.6298, 41.8781, 181.0}, // Chicago point with elevation
 27	}
 28	pointsJSON := mustMarshalGeoJSON(points)
 29
 30	resp := &Response{
 31		Paths: []Path{
 32			{
 33				Distance:      1000.0,
 34				Time:          60000,
 35				Points:        pointsJSON,
 36				PointsEncoded: false,
 37			},
 38		},
 39	}
 40
 41	// Test Points()
 42	decoded, err := resp.Points()
 43	require.NoError(t, err)
 44	assert.Len(t, decoded, 3, "should have 3 points")
 45
 46	// Verify each point has lon, lat (not elevation)
 47	assert.Equal(t, []float64{-74.006, 40.7128}, decoded[0])
 48	assert.Equal(t, []float64{-118.2437, 34.0522}, decoded[1])
 49	assert.Equal(t, []float64{-87.6298, 41.8781}, decoded[2])
 50
 51	// Test Elevation()
 52	elevation, err := resp.Elevation()
 53	require.NoError(t, err)
 54	assert.Len(t, elevation, 3, "should have 3 elevation values")
 55	assert.Equal(t, []float64{10.5, 89.0, 181.0}, elevation)
 56}
 57
 58func TestResponse_decode_points_without_elevation(t *testing.T) {
 59	// Points without elevation as GeoJSON: {"type":"LineString","coordinates":[[lon, lat], ...]}
 60	points := [][]float64{
 61		{-74.006, 40.7128},
 62		{-118.2437, 34.0522},
 63	}
 64	pointsJSON := mustMarshalGeoJSON(points)
 65
 66	resp := &Response{
 67		Paths: []Path{
 68			{
 69				Points:        pointsJSON,
 70				PointsEncoded: false,
 71			},
 72		},
 73	}
 74
 75	decoded, err := resp.Points()
 76	require.NoError(t, err)
 77	assert.Len(t, decoded, 2)
 78	assert.Equal(t, []float64{-74.006, 40.7128}, decoded[0])
 79	assert.Equal(t, []float64{-118.2437, 34.0522}, decoded[1])
 80
 81	elevation, err := resp.Elevation()
 82	require.NoError(t, err)
 83	assert.Empty(t, elevation, "should have no elevation values when not provided")
 84}
 85
 86func TestResponse_decode_multiple_paths(t *testing.T) {
 87	// First path as GeoJSON
 88	points1 := [][]float64{
 89		{-74.006, 40.7128, 10.0},
 90		{-75.0, 41.0, 20.0},
 91	}
 92	points1JSON := mustMarshalGeoJSON(points1)
 93
 94	// Second path as GeoJSON
 95	points2 := [][]float64{
 96		{-118.2437, 34.0522, 50.0},
 97		{-119.0, 35.0, 60.0},
 98	}
 99	points2JSON := mustMarshalGeoJSON(points2)
100
101	resp := &Response{
102		Paths: []Path{
103			{
104				Points:        points1JSON,
105				PointsEncoded: false,
106			},
107			{
108				Points:        points2JSON,
109				PointsEncoded: false,
110			},
111		},
112	}
113
114	// Should combine all points from all paths
115	decoded, err := resp.Points()
116	require.NoError(t, err)
117	assert.Len(t, decoded, 4, "should have 4 points total (2 from each path)")
118	assert.Equal(t, []float64{-74.006, 40.7128}, decoded[0])
119	assert.Equal(t, []float64{-75.0, 41.0}, decoded[1])
120	assert.Equal(t, []float64{-118.2437, 34.0522}, decoded[2])
121	assert.Equal(t, []float64{-119.0, 35.0}, decoded[3])
122
123	// Should combine all elevation values
124	elevation, err := resp.Elevation()
125	require.NoError(t, err)
126	assert.Len(t, elevation, 4)
127	assert.Equal(t, []float64{10.0, 20.0, 50.0, 60.0}, elevation)
128}
129
130func TestResponse_decode_empty_points(t *testing.T) {
131	points := [][]float64{}
132	pointsJSON := mustMarshalGeoJSON(points)
133
134	resp := &Response{
135		Paths: []Path{
136			{
137				Points:        pointsJSON,
138				PointsEncoded: false,
139			},
140		},
141	}
142
143	decoded, err := resp.Points()
144	require.NoError(t, err)
145	assert.Empty(t, decoded)
146
147	elevation, err := resp.Elevation()
148	require.NoError(t, err)
149	assert.Empty(t, elevation)
150}
151
152func TestResponse_decode_memoization(t *testing.T) {
153	points := [][]float64{
154		{-74.006, 40.7128, 10.5},
155	}
156	pointsJSON := mustMarshalGeoJSON(points)
157
158	resp := &Response{
159		Paths: []Path{
160			{
161				Points:        pointsJSON,
162				PointsEncoded: false,
163			},
164		},
165	}
166
167	// First call
168	decoded1, err := resp.Points()
169	require.NoError(t, err)
170	assert.Len(t, decoded1, 1)
171
172	// Second call should return same memoized result
173	decoded2, err := resp.Points()
174	require.NoError(t, err)
175	assert.Len(t, decoded2, 1)
176
177	// Should be the same underlying array
178	assert.Equal(t, decoded1, decoded2)
179}