Skip to content

Commit b5af8c9

Browse files
committed
refactor: extract valhalla warnings handler and add unit tests
1 parent 27f224c commit b5af8c9

File tree

6 files changed

+77
-42
lines changed

6 files changed

+77
-42
lines changed

src/components/types.ts

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -213,22 +213,21 @@ export interface Address {
213213
country_code: string;
214214
}
215215

216+
export interface ValhallaWarning {
217+
code: number;
218+
message: string;
219+
}
220+
216221
export interface ValhallaRouteResponse {
217222
id: 'valhalla_directions';
218223
trip: Trip;
219224
alternates?: ValhallaRouteResponse[];
220-
warnings?: {
221-
code: number;
222-
message: string;
223-
}[];
225+
warnings?: ValhallaWarning[];
224226
}
225227

226228
export interface ValhallaIsochroneResponse extends GeoJSON.FeatureCollection {
227229
id: string;
228-
warnings?: {
229-
code: number;
230-
message: string;
231-
}[];
230+
warnings?: ValhallaWarning[];
232231
}
233232

234233
export interface FetchGeocodeObject {
@@ -249,8 +248,5 @@ export interface OptimizedLocation {
249248
export interface ValhallaOptimizedRouteResponse {
250249
trip: Trip;
251250
id?: string;
252-
warnings?: {
253-
code: number;
254-
message: string;
255-
}[];
251+
warnings?: ValhallaWarning[];
256252
}

src/hooks/use-directions-queries.ts

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import { getDirectionsLanguage } from '@/utils/directions-language';
2222
import { useCommonStore } from '@/stores/common-store';
2323
import { useDirectionsStore, type Waypoint } from '@/stores/directions-store';
2424
import { router } from '@/routes';
25+
import { handleValhallaWarnings } from '@/utils/handle-valhalla-warnings';
2526

2627
const getActiveWaypoints = (waypoints: Waypoint[]): ActiveWaypoint[] =>
2728
waypoints.flatMap((wp) => wp.geocodeResults.filter((r) => r.selected));
@@ -57,16 +58,7 @@ async function fetchDirections() {
5758
);
5859

5960
// Display routing warnings if present
60-
if (data.warnings && data.warnings.length > 0) {
61-
data.warnings.forEach((warning) => {
62-
toast.warning('Routing warning', {
63-
description: warning.message,
64-
position: 'bottom-center',
65-
duration: 5000,
66-
closeButton: true,
67-
});
68-
});
69-
}
61+
handleValhallaWarnings(data.warnings);
7062

7163
// Parse geometry for main route
7264
(data as ParsedDirectionsGeometry).decodedGeometry =

src/hooks/use-isochrones-queries.ts

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import { calcArea } from '@/utils/geom';
1818
import { useCommonStore } from '@/stores/common-store';
1919
import { useIsochronesStore } from '@/stores/isochrones-store';
2020
import { router } from '@/routes';
21+
import { handleValhallaWarnings } from '@/utils/handle-valhalla-warnings';
2122

2223
async function fetchIsochrones() {
2324
const { geocodeResults, maxRange, interval, denoise, generalize } =
@@ -52,16 +53,7 @@ async function fetchIsochrones() {
5253
);
5354

5455
// Display routing warnings if present
55-
if (data.warnings && data.warnings.length > 0) {
56-
data.warnings.forEach((warning) => {
57-
toast.warning('Isochrone warning', {
58-
description: warning.message,
59-
position: 'bottom-center',
60-
duration: 5000,
61-
closeButton: true,
62-
});
63-
});
64-
}
56+
handleValhallaWarnings(data.warnings);
6557

6658
// Calculate area for each feature
6759
data.features.forEach((feature) => {

src/hooks/use-optimized-route-query.ts

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import { router } from '@/routes';
1313
import type { ValhallaOptimizedRouteResponse } from '@/components/types';
1414
import type { Waypoint } from '@/stores/directions-store';
1515
import { getDirectionsLanguage } from '@/utils/directions-language';
16+
import { handleValhallaWarnings } from '@/utils/handle-valhalla-warnings';
1617

1718
export function useOptimizedRouteQuery() {
1819
const waypoints = useDirectionsStore((state) => state.waypoints);
@@ -56,16 +57,7 @@ export function useOptimizedRouteQuery() {
5657
);
5758

5859
// Display routing warnings if present
59-
if (data.warnings && data.warnings.length > 0) {
60-
data.warnings.forEach((warning) => {
61-
toast.warning('Optimization warning', {
62-
description: warning.message,
63-
position: 'bottom-center',
64-
duration: 5000,
65-
closeButton: true,
66-
});
67-
});
68-
}
60+
handleValhallaWarnings(data.warnings);
6961

7062
const processedData = {
7163
...data,
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import { describe, it, expect, vi, beforeEach } from 'vitest';
2+
import { toast } from 'sonner';
3+
import { handleValhallaWarnings } from './handle-valhalla-warnings';
4+
5+
vi.mock('sonner', () => ({
6+
toast: {
7+
warning: vi.fn(),
8+
},
9+
}));
10+
11+
describe('handleValhallaWarnings', () => {
12+
beforeEach(() => {
13+
vi.clearAllMocks();
14+
});
15+
16+
it('should display toast for each warning', () => {
17+
const warnings = [
18+
{ code: 1, message: 'Warning one' },
19+
{ code: 2, message: 'Warning two' },
20+
];
21+
22+
handleValhallaWarnings(warnings);
23+
24+
expect(toast.warning).toHaveBeenCalledTimes(2);
25+
});
26+
27+
it('should not display toast when warnings are empty', () => {
28+
handleValhallaWarnings([]);
29+
30+
expect(toast.warning).not.toHaveBeenCalled();
31+
});
32+
33+
it('should not display toast when warnings are undefined', () => {
34+
handleValhallaWarnings(undefined);
35+
36+
expect(toast.warning).not.toHaveBeenCalled();
37+
});
38+
});
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import { toast } from 'sonner';
2+
import type { ValhallaWarning } from '@/components/types';
3+
import type { ExternalToast } from 'sonner';
4+
5+
/**
6+
* Displays toast notifications for warnings returned by the Valhalla API
7+
* @param warnings - Optional warnings array from Valhalla API response
8+
*/
9+
10+
const TOAST_CONFIG: ExternalToast = {
11+
position: 'bottom-center',
12+
duration: 5000,
13+
closeButton: true,
14+
};
15+
16+
export const handleValhallaWarnings = (warnings?: ValhallaWarning[]): void => {
17+
if (!warnings?.length) return;
18+
19+
warnings?.forEach((warning) => {
20+
toast.warning('Routing warning', {
21+
description: warning.message,
22+
...TOAST_CONFIG,
23+
});
24+
});
25+
};

0 commit comments

Comments
 (0)