mirror of
https://github.com/dz0ny/meshcore-sar.git
synced 2026-08-11 16:30:28 +00:00
Add custom cave map mode
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:latlong2/latlong.dart';
|
||||
import 'package:meshcore_sar_app/models/map_drawing.dart';
|
||||
import 'package:meshcore_sar_app/models/map_coordinate_space.dart';
|
||||
import 'package:meshcore_sar_app/utils/drawing_message_parser.dart';
|
||||
|
||||
void main() {
|
||||
@@ -10,10 +11,7 @@ void main() {
|
||||
id: 'test-123',
|
||||
color: DrawingColors.palette[0],
|
||||
createdAt: DateTime.now(),
|
||||
points: [
|
||||
LatLng(37.7749, -122.4194),
|
||||
LatLng(37.7750, -122.4195),
|
||||
],
|
||||
points: [LatLng(37.7749, -122.4194), LatLng(37.7750, -122.4195)],
|
||||
);
|
||||
|
||||
final message = DrawingMessageParser.createDrawingMessage(drawing);
|
||||
@@ -59,29 +57,55 @@ void main() {
|
||||
expect((parsed as LineDrawing).points.length, equals(3));
|
||||
});
|
||||
|
||||
test('createDrawingMessage handles rectangle with proper string format', () {
|
||||
final drawing = RectangleDrawing(
|
||||
id: 'rect-789',
|
||||
color: DrawingColors.palette[4], // orange
|
||||
test(
|
||||
'createDrawingMessage handles rectangle with proper string format',
|
||||
() {
|
||||
final drawing = RectangleDrawing(
|
||||
id: 'rect-789',
|
||||
color: DrawingColors.palette[4], // orange
|
||||
createdAt: DateTime.now(),
|
||||
topLeft: LatLng(45.5231, -122.6765),
|
||||
bottomRight: LatLng(45.5100, -122.6600),
|
||||
);
|
||||
|
||||
final message = DrawingMessageParser.createDrawingMessage(drawing);
|
||||
|
||||
// CRITICAL: Must be pure string
|
||||
expect(message, isA<String>());
|
||||
expect(message, startsWith('D:'));
|
||||
|
||||
// Should contain compact JSON format
|
||||
expect(message, contains('"t":'));
|
||||
expect(message, contains('"c":'));
|
||||
expect(message, contains('"b":'));
|
||||
|
||||
// Must NOT contain any object representations
|
||||
expect(message, isNot(contains('RectangleDrawing')));
|
||||
expect(message, isNot(contains('Instance')));
|
||||
},
|
||||
);
|
||||
|
||||
test('custom-map drawings use D2 format and preserve map metadata', () {
|
||||
final drawing = LineDrawing(
|
||||
id: 'custom-1',
|
||||
color: DrawingColors.palette[1],
|
||||
createdAt: DateTime.now(),
|
||||
topLeft: LatLng(45.5231, -122.6765),
|
||||
bottomRight: LatLng(45.5100, -122.6600),
|
||||
points: [LatLng(120, 200), LatLng(320, 450)],
|
||||
coordinateSpace: MapCoordinateSpace.customMap,
|
||||
mapId: '1234567890abcdef',
|
||||
);
|
||||
|
||||
final message = DrawingMessageParser.createDrawingMessage(drawing);
|
||||
|
||||
// CRITICAL: Must be pure string
|
||||
expect(message, isA<String>());
|
||||
expect(message, startsWith('D:'));
|
||||
expect(message, startsWith('D2:'));
|
||||
|
||||
// Should contain compact JSON format
|
||||
expect(message, contains('"t":'));
|
||||
expect(message, contains('"c":'));
|
||||
expect(message, contains('"b":'));
|
||||
|
||||
// Must NOT contain any object representations
|
||||
expect(message, isNot(contains('RectangleDrawing')));
|
||||
expect(message, isNot(contains('Instance')));
|
||||
final parsed = DrawingMessageParser.parseDrawingMessage(message);
|
||||
expect(parsed, isA<LineDrawing>());
|
||||
expect(parsed!.coordinateSpace, MapCoordinateSpace.customMap);
|
||||
expect(parsed.mapId, '1234567890ab');
|
||||
final parsedLine = parsed as LineDrawing;
|
||||
expect(parsedLine.points.first.latitude, 120);
|
||||
expect(parsedLine.points.first.longitude, 200);
|
||||
});
|
||||
|
||||
test('JSON encoding produces string with coordinates as numbers', () {
|
||||
@@ -89,9 +113,7 @@ void main() {
|
||||
id: 'coord-test',
|
||||
color: DrawingColors.palette[1], // blue
|
||||
createdAt: DateTime.now(),
|
||||
points: [
|
||||
LatLng(37.77490, -122.41940),
|
||||
],
|
||||
points: [LatLng(37.77490, -122.41940)],
|
||||
);
|
||||
|
||||
final message = DrawingMessageParser.createDrawingMessage(drawing);
|
||||
@@ -110,17 +132,17 @@ void main() {
|
||||
});
|
||||
|
||||
test('isDrawingMessage correctly identifies valid drawing messages', () {
|
||||
expect(DrawingMessageParser.isDrawingMessage('D:{"t":0,"c":1,"p":[1,2]}'), isTrue);
|
||||
expect(
|
||||
DrawingMessageParser.isDrawingMessage('D:{"t":0,"c":1,"p":[1,2]}'),
|
||||
isTrue,
|
||||
);
|
||||
expect(DrawingMessageParser.isDrawingMessage('S:🧑:37,-122'), isFalse);
|
||||
expect(DrawingMessageParser.isDrawingMessage('Plain text'), isFalse);
|
||||
expect(DrawingMessageParser.isDrawingMessage('D:'), isTrue);
|
||||
});
|
||||
|
||||
test('parseDrawingMessage returns null for malformed messages', () {
|
||||
expect(
|
||||
DrawingMessageParser.parseDrawingMessage('Not a drawing'),
|
||||
isNull,
|
||||
);
|
||||
expect(DrawingMessageParser.parseDrawingMessage('Not a drawing'), isNull);
|
||||
expect(
|
||||
DrawingMessageParser.parseDrawingMessage('D:invalid json'),
|
||||
isNull,
|
||||
@@ -132,10 +154,7 @@ void main() {
|
||||
id: 'roundtrip-1',
|
||||
color: DrawingColors.palette[3], // yellow
|
||||
createdAt: DateTime.now(),
|
||||
points: [
|
||||
LatLng(51.5074, -0.1278),
|
||||
LatLng(51.5075, -0.1279),
|
||||
],
|
||||
points: [LatLng(51.5074, -0.1278), LatLng(51.5075, -0.1279)],
|
||||
);
|
||||
|
||||
// Create message
|
||||
@@ -204,9 +223,7 @@ void main() {
|
||||
id: 'precision-test',
|
||||
color: DrawingColors.palette[0],
|
||||
createdAt: DateTime.now(),
|
||||
points: [
|
||||
LatLng(37.774901234567, -122.419401234567),
|
||||
],
|
||||
points: [LatLng(37.774901234567, -122.419401234567)],
|
||||
);
|
||||
|
||||
final message = DrawingMessageParser.createDrawingMessage(drawing);
|
||||
@@ -259,8 +276,14 @@ void main() {
|
||||
final lineMsg = 'D:{"t":0,"c":1,"p":[1,2,3,4]}';
|
||||
final rectMsg = 'D:{"t":1,"c":2,"b":[1,2,3,4]}';
|
||||
|
||||
expect(DrawingMessageParser.getDrawingTypeDisplay(lineMsg), equals('Line'));
|
||||
expect(DrawingMessageParser.getDrawingTypeDisplay(rectMsg), equals('Rectangle'));
|
||||
expect(
|
||||
DrawingMessageParser.getDrawingTypeDisplay(lineMsg),
|
||||
equals('Line'),
|
||||
);
|
||||
expect(
|
||||
DrawingMessageParser.getDrawingTypeDisplay(rectMsg),
|
||||
equals('Rectangle'),
|
||||
);
|
||||
expect(DrawingMessageParser.getDrawingTypeDisplay('Invalid'), isNull);
|
||||
});
|
||||
|
||||
@@ -322,7 +345,10 @@ void main() {
|
||||
expect(message, isA<String>());
|
||||
expect(message, startsWith('D:'));
|
||||
// Should still be parseable
|
||||
expect(() => DrawingMessageParser.parseDrawingMessage(message), returnsNormally);
|
||||
expect(
|
||||
() => DrawingMessageParser.parseDrawingMessage(message),
|
||||
returnsNormally,
|
||||
);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:latlong2/latlong.dart';
|
||||
import 'package:meshcore_sar_app/models/sar_marker.dart';
|
||||
import 'package:meshcore_sar_app/models/map_coordinate_space.dart';
|
||||
import 'package:meshcore_sar_app/utils/sar_message_parser.dart';
|
||||
|
||||
void main() {
|
||||
@@ -50,7 +51,10 @@ void main() {
|
||||
|
||||
// CRITICAL: Coordinates must be in string form, not Object
|
||||
expect(message, contains('40.7128'));
|
||||
expect(message, contains('-74.006')); // Trailing zero trimmed by toString()
|
||||
expect(
|
||||
message,
|
||||
contains('-74.006'),
|
||||
); // Trailing zero trimmed by toString()
|
||||
|
||||
// Must NOT contain object representation
|
||||
expect(message, isNot(contains('LatLng')));
|
||||
@@ -115,6 +119,26 @@ void main() {
|
||||
expect(info.notes, equals('Large fire'));
|
||||
});
|
||||
|
||||
test('custom-map SAR markers use S2 format and preserve map metadata', () {
|
||||
final message = SarMessageParser.createCustomMapSarMessage(
|
||||
emoji: '📦',
|
||||
mapId: 'abcdef1234567890',
|
||||
point: LatLng(250, 400),
|
||||
notes: 'Cache location',
|
||||
colorIndex: 4,
|
||||
);
|
||||
|
||||
expect(message, startsWith('S2:'));
|
||||
|
||||
final parsed = SarMessageParser.parse(message);
|
||||
expect(parsed, isNotNull);
|
||||
expect(parsed!.coordinateSpace, MapCoordinateSpace.customMap);
|
||||
expect(parsed.mapId, 'abcdef123456');
|
||||
expect(parsed.location.latitude, 250);
|
||||
expect(parsed.location.longitude, 400);
|
||||
expect(parsed.notes, 'Cache location');
|
||||
});
|
||||
|
||||
test('round-trip: create -> parse -> create preserves format', () {
|
||||
final original = SarMessageParser.createSarMessage(
|
||||
type: SarMarkerType.stagingArea,
|
||||
@@ -271,15 +295,9 @@ void main() {
|
||||
isTrue,
|
||||
);
|
||||
|
||||
expect(
|
||||
SarMessageParser.isValidFormat('S:invalid:format'),
|
||||
isFalse,
|
||||
);
|
||||
expect(SarMessageParser.isValidFormat('S:invalid:format'), isFalse);
|
||||
|
||||
expect(
|
||||
SarMessageParser.isValidFormat('Not SAR message'),
|
||||
isFalse,
|
||||
);
|
||||
expect(SarMessageParser.isValidFormat('Not SAR message'), isFalse);
|
||||
});
|
||||
|
||||
test('getFormatError provides helpful error messages', () {
|
||||
@@ -288,10 +306,7 @@ void main() {
|
||||
contains('must start with "S:"'),
|
||||
);
|
||||
|
||||
expect(
|
||||
SarMessageParser.getFormatError('S:'),
|
||||
contains('Invalid format'),
|
||||
);
|
||||
expect(SarMessageParser.getFormatError('S:'), contains('Invalid format'));
|
||||
|
||||
expect(
|
||||
SarMessageParser.getFormatError('S::37.7,-122.4'),
|
||||
@@ -415,6 +430,7 @@ void main() {
|
||||
emoji: '🧑',
|
||||
notes: 'Test notes',
|
||||
colorIndex: 2,
|
||||
coordinateSpace: MapCoordinateSpace.geo,
|
||||
);
|
||||
|
||||
final str = info.toString();
|
||||
|
||||
Reference in New Issue
Block a user