Files
TREK/client/src/components/Tours/TourGpxPreviewDialog.test.tsx
T
Maurice 39ebf0976c fix(tours): a tour import takes over a track imported before Tours
A GPX track imported in 4.x is a plain place: a line, no tours row. It never
showed under Tours, and importing the same file there was refused as a
duplicate by its name, so there was no way to turn it into a tour (#2810).

The tour import now takes over a track of the trip that has the same name
and is no tour yet: the place keeps its name and line and gets the tours
row, with the recorded times the file adds. The preview says so instead of
"Already in the trip". New and taken-over tracks commit in one transaction.
2026-10-26 12:17:15 +01:00

82 lines
3.4 KiB
TypeScript

// FE-GPX-PREVIEW-001 to FE-GPX-PREVIEW-004
// The GPX preview as ACT-01 uses it: preset to the tour's type, a city walk
// imported as one, and when a track was recorded shown where it carried times.
import { fireEvent, render, screen } from '@testing-library/react';
import type { TourGpxPreviewTrack } from '@trek/shared';
import { describe, expect, it, vi } from 'vitest';
import TourGpxPreviewDialog from './TourGpxPreviewDialog';
import type { TourGpxImport } from './useTourGpxImport';
vi.mock('../Map/MapViewAuto', () => ({ MapViewAuto: () => <div data-testid="gpx-preview-map-stub" /> }));
function track(overrides: Partial<TourGpxPreviewTrack> = {}): TourGpxPreviewTrack {
return {
name: 'Morning',
geometry: [
[47, 11],
[47.01, 11],
],
point_count: 2,
distance_km: 1.1,
elevation_gain_m: null,
elevation_loss_m: null,
started_at: '2026-07-02T06:10:00.000Z',
ended_at: '2026-07-02T07:00:00.000Z',
duplicate: false,
...overrides,
};
}
function gpxImport(tracks: TourGpxPreviewTrack[]): TourGpxImport {
return {
importing: false,
preview: [{ file: new File(['<gpx/>'], 'morning.gpx'), tracks }],
confirm: vi.fn(),
cancel: vi.fn(),
pick: vi.fn(),
importFiles: vi.fn(),
} as unknown as TourGpxImport;
}
describe('TourGpxPreviewDialog (ACT-01)', () => {
it('FE-GPX-PREVIEW-001: shows when a track was recorded and how long it took, and nothing for one without times', () => {
const tracks = [track(), track({ name: 'Drawn', started_at: null, ended_at: null })];
render(<TourGpxPreviewDialog gpxImport={gpxImport(tracks)} />);
const recorded = screen.getAllByTestId('gpx-preview-recorded');
expect(recorded).toHaveLength(1);
expect(recorded[0]).toHaveTextContent('50 min');
});
it('FE-GPX-PREVIEW-004: a track taken over from before Tours reads as one, not as a duplicate (#2810)', () => {
render(<TourGpxPreviewDialog gpxImport={gpxImport([track({ adopts_track: true })])} />);
expect(screen.getByTestId('gpx-preview-track')).not.toHaveAttribute('data-duplicate');
expect(screen.getByText(/tours\.import\.previewAdopts|becomes a tour/)).toBeInTheDocument();
expect(screen.queryByText(/tours\.import\.previewDuplicate|Already in the trip/)).toBeNull();
});
it('FE-GPX-PREVIEW-002: imports as the preset type, a paddle tour with its boat and water', () => {
const current = gpxImport([track()]);
render(
<TourGpxPreviewDialog
gpxImport={current}
initial={{ tour_type: 'kayak', boat_type: 'sup', water_context: 'lake' }}
/>
);
fireEvent.click(screen.getByTestId('gpx-preview-import'));
expect(current.confirm).toHaveBeenCalledWith({ tour_type: 'kayak', boat_type: 'sup', water_context: 'lake' });
});
it('FE-GPX-PREVIEW-003: a city walk is imported as a city walk, and without a preset as a hike', () => {
const walk = gpxImport([track()]);
const { unmount } = render(<TourGpxPreviewDialog gpxImport={walk} initial={{ tour_type: 'walk' }} />);
fireEvent.click(screen.getByTestId('gpx-preview-import'));
expect(walk.confirm).toHaveBeenCalledWith({ tour_type: 'walk' });
unmount();
const hike = gpxImport([track()]);
render(<TourGpxPreviewDialog gpxImport={hike} />);
fireEvent.click(screen.getByTestId('gpx-preview-import'));
expect(hike.confirm).toHaveBeenCalledWith({ tour_type: 'hike' });
});
});