Skip to content

Commit a934707

Browse files
committed
fix: Traffic polyline when location does not update, improve test cases
1 parent 1bfde4b commit a934707

File tree

2 files changed

+64
-77
lines changed

2 files changed

+64
-77
lines changed

src/TrafficPolyline.js

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -94,13 +94,15 @@ export class TrafficPolyline {
9494
}
9595

9696
calculateSplitPoints(roadStretches, totalLength) {
97-
let points = [0];
97+
// Use a Set to automatically handle duplicate points
98+
const points = new Set([0, totalLength]);
9899
roadStretches.forEach((stretch) => {
99-
points.push(stretch.offsetmeters);
100-
points.push(stretch.offsetmeters + stretch.lengthmeters);
100+
const offset = stretch.offsetmeters || 0;
101+
points.add(offset);
102+
points.add(offset + stretch.lengthmeters);
101103
});
102-
points.push(totalLength * 1000);
103-
return [...new Set(points)].sort((a, b) => a - b);
104+
// Filter out any points that might be beyond the line's total length and sort them
105+
return [...points].filter((p) => p <= totalLength).sort((a, b) => a - b);
104106
}
105107

106108
createSegmentsData(line, splitPoints, roadStretches) {
@@ -121,7 +123,8 @@ export class TrafficPolyline {
121123

122124
getSegmentStyle(startDistance, roadStretches) {
123125
for (const stretch of roadStretches) {
124-
if (startDistance >= stretch.offsetmeters && startDistance < stretch.offsetmeters + stretch.lengthmeters) {
126+
const offset = stretch.offsetmeters || 0;
127+
if (startDistance >= offset && startDistance < offset + stretch.lengthmeters) {
125128
return stretch.style;
126129
}
127130
}

src/TrafficPolyline.test.js

Lines changed: 55 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,18 @@
11
// src/TrafficPolyline.test.js
2-
32
import { TRAFFIC_COLORS } from "./TrafficPolyline";
3+
import TrafficPolyline from "./TrafficPolyline";
44

5-
// Mock turf due to module compatibility
6-
/* eslint-disable no-unused-vars */
5+
// Mock the entire turf library. The implementation details don't matter,
6+
// only that the functions return an object with the expected shape to prevent crashes.
77
jest.mock("@turf/turf", () => ({
8-
lineString: (coords) => ({ type: "LineString", coordinates: coords }),
9-
length: () => 10,
10-
along: (_line, _distance) => ({
11-
type: "Point",
12-
coordinates: [0, 0],
13-
}),
14-
lineSlice: () => ({
15-
type: "LineString",
16-
geometry: {
17-
coordinates: [
18-
[0, 0],
19-
[1, 1],
20-
],
21-
},
22-
}),
8+
lineString: () => ({ geometry: { coordinates: [] } }),
9+
length: () => 1000,
10+
point: () => ({ geometry: { coordinates: [] } }),
11+
lineSlice: () => ({ geometry: { coordinates: [[], []] } }),
12+
along: () => ({ geometry: { coordinates: [] } }),
2313
}));
2414

25-
// Mock google maps
15+
// Mock the Google Maps API
2616
global.google = {
2717
maps: {
2818
Polyline: class MockPolyline {
@@ -33,91 +23,85 @@ global.google = {
3323
this.map = map;
3424
}
3525
},
26+
SymbolPath: {
27+
FORWARD_OPEN_ARROW: "test-arrow",
28+
},
3629
},
3730
};
3831

3932
describe("TrafficPolyline", () => {
40-
let TrafficPolyline;
41-
42-
beforeEach(() => {
43-
jest.resetModules();
44-
TrafficPolyline = require("./TrafficPolyline").default;
45-
});
46-
4733
const samplePath = [
4834
{ lat: 0, lng: 0 },
4935
{ lat: 1, lng: 1 },
5036
];
5137

52-
test("creates STYLE_NORMAL polyline when no traffic data provided", () => {
53-
const polyline = new TrafficPolyline({
54-
path: samplePath,
55-
map: {},
56-
});
57-
38+
test("creates STYLE_NORMAL polyline when no traffic data is provided", () => {
39+
const polyline = new TrafficPolyline({ path: samplePath, map: {} });
5840
expect(polyline.polylines.length).toBe(1);
5941
expect(polyline.polylines[0].options.strokeColor).toBe(TRAFFIC_COLORS.STYLE_NORMAL);
6042
});
6143

62-
test("creates NORMAL polylines when traffic data exists but no stretches", () => {
63-
const polyline = new TrafficPolyline({
64-
path: samplePath,
65-
trafficRendering: { roadstretch: [] },
66-
map: {},
67-
});
44+
test("creates multiple polylines for different traffic segments", () => {
45+
const trafficRendering = {
46+
roadstretch: [
47+
{ style: "SLOWER_TRAFFIC", lengthmeters: 100, offsetmeters: 0 },
48+
{ style: "TRAFFIC_JAM", lengthmeters: 100, offsetmeters: 200 },
49+
],
50+
};
51+
const polyline = new TrafficPolyline({ path: samplePath, trafficRendering, map: {} });
52+
expect(polyline.polylines.length).toBeGreaterThan(1);
53+
const colors = polyline.polylines.map((p) => p.options.strokeColor);
54+
expect(colors).toContain(TRAFFIC_COLORS.SLOWER_TRAFFIC);
55+
expect(colors).toContain(TRAFFIC_COLORS.TRAFFIC_JAM);
56+
});
6857

69-
expect(polyline.polylines.length).toBe(1);
70-
expect(polyline.polylines[0].options.strokeColor).toBe(TRAFFIC_COLORS.STYLE_NORMAL);
58+
test("handles traffic data with missing offsetmeters without crashing", () => {
59+
const trafficRendering = {
60+
roadstretch: [
61+
{ style: "TRAFFIC_JAM", lengthmeters: 200 }, // No offsetmeters
62+
],
63+
};
64+
let polyline;
65+
// The test passes if it doesn't throw an error.
66+
expect(() => {
67+
polyline = new TrafficPolyline({ path: samplePath, trafficRendering, map: {} });
68+
}).not.toThrow();
69+
const colors = polyline.polylines.map((p) => p.options.strokeColor);
70+
expect(colors).toContain(TRAFFIC_COLORS.TRAFFIC_JAM);
7171
});
7272

73-
test("creates multiple polylines for different traffic segments", () => {
73+
test("correctly processes unsorted roadstretch data", () => {
7474
const trafficRendering = {
7575
roadstretch: [
76-
{
77-
style: "STYLE_SLOWER_TRAFFIC",
78-
lengthmeters: 100,
79-
offsetmeters: 0,
80-
},
81-
{
82-
style: "STYLE_TRAFFIC_JAM",
83-
lengthmeters: 100,
84-
offsetmeters: 200,
85-
},
76+
{ style: "SLOWER_TRAFFIC", offsetmeters: 500, lengthmeters: 100 },
77+
{ style: "TRAFFIC_JAM", offsetmeters: 100, lengthmeters: 200 },
8678
],
8779
};
80+
const polyline = new TrafficPolyline({ path: samplePath, trafficRendering, map: {} });
81+
// Check that segments were created, implying the sorting worked.
82+
expect(polyline.segments.length).toBeGreaterThan(2);
83+
});
8884

85+
test('creates a "NO_DATA" segment for the traveled portion of the path', () => {
8986
const polyline = new TrafficPolyline({
9087
path: samplePath,
91-
trafficRendering,
88+
currentLatLng: { latitude: 0.5, longitude: 0.5 },
9289
map: {},
9390
});
94-
95-
expect(polyline.polylines.length).toBeGreaterThan(1);
96-
9791
const colors = polyline.polylines.map((p) => p.options.strokeColor);
98-
expect(colors).toContain(TRAFFIC_COLORS.STYLE_SLOWER_TRAFFIC);
99-
expect(colors).toContain(TRAFFIC_COLORS.STYLE_TRAFFIC_JAM);
92+
expect(colors).toContain(TRAFFIC_COLORS.STYLE_NO_DATA);
10093
});
10194

102-
test("handles invalid path gracefully", () => {
103-
const polyline = new TrafficPolyline({
104-
path: [],
105-
map: {},
106-
});
107-
95+
test("handles invalid or empty path gracefully", () => {
96+
const polyline = new TrafficPolyline({ path: [], map: {} });
10897
expect(polyline.polylines.length).toBe(1);
10998
expect(polyline.polylines[0].options.strokeColor).toBe(TRAFFIC_COLORS.STYLE_NO_DATA);
11099
});
111100

112-
test("setMap updates all polylines", () => {
113-
const polyline = new TrafficPolyline({
114-
path: samplePath,
115-
map: {},
116-
});
117-
118-
const newMap = {};
101+
test("setMap updates all child polylines", () => {
102+
const polyline = new TrafficPolyline({ path: samplePath, map: {} });
103+
const newMap = { id: "new-map" };
119104
polyline.setMap(newMap);
120-
121105
polyline.polylines.forEach((p) => {
122106
expect(p.map).toBe(newMap);
123107
});

0 commit comments

Comments
 (0)