This commit is contained in:
gili8420 2026-08-14 00:01:49 +09:00
commit b43955e0d9
162 changed files with 15425 additions and 0 deletions

66
tests/unit/export.test.ts Normal file
View file

@ -0,0 +1,66 @@
import { describe, it, expect } from 'vitest';
import { toGpx, toKml, toCsv, parsePrediction, EXPORT_MIME, exportPrediction } from '$domain';
import type { PredictionStage } from '$domain';
const stages: PredictionStage[] = [
{
stage: 'ascent',
trajectory: [
{ altitude: 0, datetime: '2026-01-01T00:00:00Z', latitude: 62.0, longitude: 129.0 },
{ altitude: 30000, datetime: '2026-01-01T01:00:00Z', latitude: 62.1, longitude: 129.2 }
]
},
{
stage: 'descent',
trajectory: [
{ altitude: 30000, datetime: '2026-01-01T01:00:00Z', latitude: 62.1, longitude: 129.2 },
{ altitude: 0, datetime: '2026-01-01T01:30:00Z', latitude: 62.05, longitude: 129.4 }
]
}
];
const prediction = parsePrediction(stages);
describe('toGpx', () => {
it('emits one trkpt per sample with elevation and time', () => {
const gpx = toGpx(prediction, 'Flight 1');
expect(gpx).toContain('<gpx version="1.1"');
expect(gpx.match(/<trkpt /g)).toHaveLength(4);
expect(gpx).toContain('lat="62.000000" lon="129.000000"');
expect(gpx).toContain('<ele>30000.0</ele>');
expect(gpx).toContain('<time>2026-01-01T00:00:00.000Z</time>');
});
it('escapes the name so a quote cannot break the XML', () => {
expect(toGpx(prediction, 'A & <B>')).toContain('A &amp; &lt;B&gt;');
});
});
describe('toKml', () => {
it('orders coordinates longitude-first and marks the key points', () => {
const kml = toKml(prediction);
expect(kml).toContain('<kml xmlns="http://www.opengis.net/kml/2.2">');
// lon,lat,alt — the opposite order to GPX.
expect(kml).toContain('129.000000,62.000000,0.0');
expect(kml).toContain('<name>Launch</name>');
expect(kml).toContain('<name>Burst</name>');
expect(kml).toContain('<name>Landing</name>');
});
});
describe('toCsv', () => {
it('writes a header plus one row per sample', () => {
const lines = toCsv(prediction).split('\n');
expect(lines[0]).toBe('datetime_utc,latitude,longitude,altitude_m');
expect(lines).toHaveLength(5);
expect(lines[1]).toBe('2026-01-01T00:00:00.000Z,62.000000,129.000000,0.0');
});
});
describe('exportPrediction', () => {
it('dispatches by format and exposes a mime type for each', () => {
expect(exportPrediction(prediction, 'gpx')).toContain('<gpx');
expect(exportPrediction(prediction, 'kml')).toContain('<kml');
expect(exportPrediction(prediction, 'csv')).toContain('datetime_utc');
expect(Object.keys(EXPORT_MIME).sort()).toEqual(['csv', 'gpx', 'kml']);
});
});