swarm/test/geo_actor_test.dart
2026-06-07 16:51:14 +03:00

122 lines
4.2 KiB
Dart

import 'package:swarm/swarm.dart';
import 'package:test/test.dart';
void main() {
late GeoActor actor;
setUp(() => actor = GeoActor());
group('GeoActor', () {
group('EncodeLocation', () {
test('returns GeohashEncoded with correct length', () async {
final result = await actor.handle(
const EncodeLocation(
latitude: 48.8566, longitude: 2.3522, precision: 6),
);
expect(result, isA<GeohashEncoded>());
expect((result as GeohashEncoded).geohash, hasLength(6));
});
test('default precision is 9', () async {
final result = await actor.handle(
const EncodeLocation(latitude: 51.5074, longitude: -0.1278),
);
expect((result as GeohashEncoded).geohash, hasLength(9));
});
test(
'higher precision produces longer hash with lower precision as prefix',
() async {
const lat = 52.52, lon = 13.405;
final r6 = await actor.handle(
const EncodeLocation(latitude: lat, longitude: lon, precision: 6),
);
final r9 = await actor.handle(
const EncodeLocation(latitude: lat, longitude: lon, precision: 9),
);
final h6 = (r6 as GeohashEncoded).geohash;
final h9 = (r9 as GeohashEncoded).geohash;
expect(h9, startsWith(h6));
});
});
group('DecodeGeohash', () {
test('returns LocationDecoded', () async {
final result = await actor.handle(const DecodeGeohash('u33dbf'));
expect(result, isA<LocationDecoded>());
});
test('decoded coordinates are within cell bounds for precision 6',
() async {
// precision-6 cell error: ±0.0034° lat, ±0.0017° lon
final result = await actor.handle(const DecodeGeohash('u33dbf'));
final loc = result as LocationDecoded;
expect(loc.latitude, inInclusiveRange(52.0, 53.0));
expect(loc.longitude, inInclusiveRange(13.0, 14.0));
});
test('roundtrip encode→decode recovers coordinates within cell error',
() async {
const lat = 48.8566, lon = 2.3522;
final encoded = await actor.handle(
const EncodeLocation(latitude: lat, longitude: lon, precision: 9),
);
final decoded = await actor.handle(
DecodeGeohash((encoded as GeohashEncoded).geohash),
);
final loc = decoded as LocationDecoded;
// precision-9 cell error: ±0.000021° lat, ±0.000021° lon
expect(loc.latitude, closeTo(lat, 0.001));
expect(loc.longitude, closeTo(lon, 0.001));
});
});
group('NeighborsOf', () {
const directions = [
'NORTH',
'NORTHEAST',
'EAST',
'SOUTHEAST',
'SOUTH',
'SOUTHWEST',
'WEST',
'NORTHWEST',
'CENTRAL',
];
test('returns NeighborsResult with 9 entries', () async {
final result = await actor.handle(const NeighborsOf('u33dbf'));
expect(result, isA<NeighborsResult>());
expect((result as NeighborsResult).neighbors, hasLength(9));
});
test('result contains all 8 compass directions plus CENTRAL', () async {
final result = await actor.handle(const NeighborsOf('u33dbf'));
expect(
(result as NeighborsResult).neighbors.keys,
containsAll(directions),
);
});
test('CENTRAL equals the input geohash', () async {
const hash = 'u33dbf';
final result = await actor.handle(const NeighborsOf(hash));
expect((result as NeighborsResult).neighbors['CENTRAL'], equals(hash));
});
test('all neighbor hashes have the same precision as input', () async {
const hash = 'u33dbf';
final result = await actor.handle(const NeighborsOf(hash));
for (final neighbor in (result as NeighborsResult).neighbors.values) {
expect(neighbor, hasLength(hash.length));
}
});
test('neighbor hashes are all distinct', () async {
final result = await actor.handle(const NeighborsOf('u33dbf'));
final values = (result as NeighborsResult).neighbors.values.toList();
expect(values.toSet(), hasLength(values.length));
});
});
});
}