embed mission-planner

This commit is contained in:
Oleksandr Bezdieniezhnykh
2026-04-06 05:51:31 +03:00
parent 667c9f8153
commit 2f9c4efc8e
68 changed files with 4340 additions and 1 deletions
+176
View File
@@ -0,0 +1,176 @@
const testData = {
"geofences": {
"polygons": [
{
"northWest": {
"lat": 48.28022277841604,
"lon": 37.37548828125001
},
"southEast": {
"lat": 48.2720540660028,
"lon": 37.3901653289795
}
},
{
"northWest": {
"lat": 48.2614270732573,
"lon": 37.35239982604981
},
"southEast": {
"lat": 48.24988342757033,
"lon": 37.37943649291993
}
}
]
},
"action_points": [
{ "lat": 48.276067180586544, "lon": 37.38445758819581 },
{ "lat": 48.27074009522731, "lon": 37.374029159545906 },
{ "lat": 48.263312668696855, "lon": 37.37707614898682 },
{ "lat": 48.26539817051818, "lon": 37.36587524414063 },
{ "lat": 48.25851283439989, "lon": 37.35952377319337 },
{ "lat": 48.254426906081555, "lon": 37.374801635742195 },
{ "lat": 48.25914140977405, "lon": 37.39068031311036 },
{ "lat": 48.25354110233028, "lon": 37.401752471923835 },
{ "lat": 48.25902712391726, "lon": 37.416257858276374 },
{ "lat": 48.26828345053738, "lon": 37.402009963989265 }
]
};
const newGuid = () => Math.random().toString(36).substring(2, 15);
const purposes = [
{ value: 'artillery' },
{ value: 'tank' }
];
describe('JSON Import Functionality', () => {
describe('Action Points Import', () => {
it('should correctly import action points with lat/lon format', () => {
const importedPoints = testData.action_points.map(ap => ({
id: newGuid(),
position: { lat: (ap as Record<string, unknown> & { point?: { lat: number; lon: number } }).point?.lat || ap.lat, lng: (ap as Record<string, unknown> & { point?: { lat: number; lon: number } }).point?.lon || ap.lon },
altitude: parseFloat(String((ap as Record<string, unknown>).height || 300)),
meta: (ap as Record<string, unknown> & { action_specific?: { targets: string[] } }).action_specific?.targets || [purposes[0].value, purposes[1].value]
}));
expect(importedPoints).toHaveLength(10);
expect(importedPoints[0].position.lat).toBe(48.276067180586544);
expect(importedPoints[0].position.lng).toBe(37.38445758819581);
expect(importedPoints[0].altitude).toBe(300);
expect(importedPoints[0].meta).toEqual(['artillery', 'tank']);
});
it('should handle point.lat/point.lon format', () => {
const dataWithPointFormat = {
action_points: [{
point: { lat: 48.276, lon: 37.384 },
height: 500
}]
};
const importedPoints = dataWithPointFormat.action_points.map(ap => ({
id: newGuid(),
position: { lat: ap.point?.lat || 0, lng: ap.point?.lon || 0 },
altitude: parseFloat(String(ap.height || 300)),
meta: [purposes[0].value, purposes[1].value]
}));
expect(importedPoints[0].position.lat).toBe(48.276);
expect(importedPoints[0].position.lng).toBe(37.384);
expect(importedPoints[0].altitude).toBe(500);
});
});
describe('Geofences Import', () => {
it('should correctly convert northWest/southEast to Leaflet bounds', () => {
const polygon = testData.geofences.polygons[0];
const bounds = {
_southWest: { lat: polygon.southEast.lat, lng: polygon.northWest.lon },
_northEast: { lat: polygon.northWest.lat, lng: polygon.southEast.lon }
};
expect(bounds._southWest.lat).toBe(48.2720540660028);
expect(bounds._southWest.lng).toBe(37.37548828125001);
expect(bounds._northEast.lat).toBe(48.28022277841604);
expect(bounds._northEast.lng).toBe(37.3901653289795);
});
it('should correctly import all geofences with default color', () => {
const importedRectangles = testData.geofences.polygons.map((polygon) => {
const bounds = {
_southWest: { lat: polygon.southEast.lat, lng: polygon.northWest.lon },
_northEast: { lat: polygon.northWest.lat, lng: polygon.southEast.lon }
};
const color = (polygon as Record<string, unknown>).fence_type === "EXCLUSION" ? "red" : "green";
return {
id: newGuid(),
bounds: bounds,
color: color
};
});
expect(importedRectangles).toHaveLength(2);
expect(importedRectangles[0].color).toBe('green');
expect(importedRectangles[1].color).toBe('green');
});
it('should correctly import geofences with fence_type', () => {
const dataWithFenceType = {
geofences: {
polygons: [
{
northWest: { lat: 48.28, lon: 37.375 },
southEast: { lat: 48.27, lon: 37.390 },
fence_type: "EXCLUSION"
},
{
northWest: { lat: 48.26, lon: 37.352 },
southEast: { lat: 48.25, lon: 37.379 },
fence_type: "INCLUSION"
}
]
}
};
const importedRectangles = dataWithFenceType.geofences.polygons.map((polygon) => {
const bounds = {
_southWest: { lat: polygon.southEast.lat, lng: polygon.northWest.lon },
_northEast: { lat: polygon.northWest.lat, lng: polygon.southEast.lon }
};
const color = polygon.fence_type === "EXCLUSION" ? "red" : "green";
return {
id: newGuid(),
bounds: bounds,
color: color
};
});
expect(importedRectangles[0].color).toBe('red');
expect(importedRectangles[1].color).toBe('green');
});
});
describe('Bounds Validation', () => {
it('should ensure southWest is bottom-left and northEast is top-right', () => {
const polygon = {
northWest: { lat: 50.0, lon: 10.0 },
southEast: { lat: 40.0, lon: 20.0 }
};
const bounds = {
_southWest: { lat: polygon.southEast.lat, lng: polygon.northWest.lon },
_northEast: { lat: polygon.northWest.lat, lng: polygon.southEast.lon }
};
expect(bounds._southWest.lat).toBeLessThan(bounds._northEast.lat);
expect(bounds._southWest.lng).toBeLessThan(bounds._northEast.lng);
expect(bounds._southWest.lat).toBe(40.0);
expect(bounds._southWest.lng).toBe(10.0);
expect(bounds._northEast.lat).toBe(50.0);
expect(bounds._northEast.lng).toBe(20.0);
});
});
});