210 lines
9.1 KiB
Dart
210 lines
9.1 KiB
Dart
import 'package:flutter/material.dart';
|
|
import 'package:flutter_test/flutter_test.dart';
|
|
import 'package:siro_maps/core/services/deep_link_service.dart';
|
|
import 'package:siro_maps/core/services/pip_service.dart';
|
|
import 'package:siro_maps/core/services/vehicle_icon_generator.dart';
|
|
import 'package:siro_maps/core/utils/arabic_search_normalizer.dart';
|
|
|
|
void main() {
|
|
TestWidgetsFlutterBinding.ensureInitialized();
|
|
|
|
group('ArabicSearchNormalizer Tests', () {
|
|
test('Normalizes diacritics and tashkeel', () {
|
|
const input = 'مَدِينَةُ عَمَّانَ';
|
|
expect(ArabicSearchNormalizer.normalize(input), equals('مدينه عمان'));
|
|
});
|
|
|
|
test('Normalizes various forms of Alef', () {
|
|
expect(ArabicSearchNormalizer.normalize('أحمد'), equals('احمد'));
|
|
expect(ArabicSearchNormalizer.normalize('إبراهيم'), equals('ابراهيم'));
|
|
expect(ArabicSearchNormalizer.normalize('آلاء'), equals('الاء'));
|
|
expect(ArabicSearchNormalizer.normalize('ٱستقبال'), equals('استقبال'));
|
|
});
|
|
|
|
test('Normalizes Teh Marbuta and Alef Maqsura', () {
|
|
expect(ArabicSearchNormalizer.normalize('مستشفى'), equals('مستشفي'));
|
|
expect(ArabicSearchNormalizer.normalize('جامعة'), equals('جامعه'));
|
|
expect(ArabicSearchNormalizer.normalize('صيدلية النهدي'), equals('صيدليه النهدي'));
|
|
});
|
|
|
|
test('Matches normalized queries flexibly', () {
|
|
expect(
|
|
ArabicSearchNormalizer.matches('صيدلية النهدي الكبرى', 'نهدي'),
|
|
isTrue,
|
|
);
|
|
expect(
|
|
ArabicSearchNormalizer.matches('مستشفى الجامعة الأردنية', 'جامعة'),
|
|
isTrue,
|
|
);
|
|
expect(
|
|
ArabicSearchNormalizer.matches('مستشفى الجامعة الأردنية', 'جامعه'),
|
|
isTrue,
|
|
);
|
|
expect(
|
|
ArabicSearchNormalizer.matches('مطعم القدس', 'القدس'),
|
|
isTrue,
|
|
);
|
|
});
|
|
|
|
test('Correctly identifies category queries vs specific landmarks', () {
|
|
// General categories -> true
|
|
expect(ArabicSearchNormalizer.isCategoryQuery('مسجد'), isTrue);
|
|
expect(ArabicSearchNormalizer.isCategoryQuery('مطعم'), isTrue);
|
|
expect(ArabicSearchNormalizer.isCategoryQuery('مخبز'), isTrue);
|
|
expect(ArabicSearchNormalizer.isCategoryQuery('سوبرماركت'), isTrue);
|
|
expect(ArabicSearchNormalizer.isCategoryQuery('دكان'), isTrue);
|
|
expect(ArabicSearchNormalizer.isCategoryQuery('كافيه'), isTrue);
|
|
expect(ArabicSearchNormalizer.isCategoryQuery('صيدلية'), isTrue);
|
|
expect(ArabicSearchNormalizer.isCategoryQuery('محطة بنزين'), isTrue);
|
|
|
|
// Specific landmarks / names -> false
|
|
expect(ArabicSearchNormalizer.isCategoryQuery('المدينة الطبية'), isFalse);
|
|
expect(ArabicSearchNormalizer.isCategoryQuery('سيتي مول'), isFalse);
|
|
expect(ArabicSearchNormalizer.isCategoryQuery('دوار الداخلية'), isFalse);
|
|
});
|
|
});
|
|
|
|
group('VehicleIconGenerator Tests', () {
|
|
test('Generates valid PNG bytes for modern sedan', () async {
|
|
final bytes = await VehicleIconGenerator.generateVehicleIconBytes(
|
|
styleId: 'car',
|
|
primaryColor: const Color(0xFF007AFF),
|
|
);
|
|
expect(bytes, isNotEmpty);
|
|
// Valid PNG header starts with 0x89, 'P', 'N', 'G' (0x89, 0x50, 0x4E, 0x47)
|
|
expect(bytes[0], equals(0x89));
|
|
expect(bytes[1], equals(0x50));
|
|
expect(bytes[2], equals(0x4E));
|
|
expect(bytes[3], equals(0x47));
|
|
});
|
|
|
|
test('Generates valid PNG bytes for SUV and Arrow styles', () async {
|
|
final suvBytes = await VehicleIconGenerator.generateVehicleIconBytes(
|
|
styleId: 'suv',
|
|
primaryColor: const Color(0xFF00C853),
|
|
);
|
|
expect(suvBytes, isNotEmpty);
|
|
expect(suvBytes[0], equals(0x89));
|
|
|
|
final arrowBytes = await VehicleIconGenerator.generateVehicleIconBytes(
|
|
styleId: 'arrow',
|
|
primaryColor: const Color(0xFFFF3B30),
|
|
);
|
|
expect(arrowBytes, isNotEmpty);
|
|
expect(arrowBytes[0], equals(0x89));
|
|
});
|
|
|
|
test('Exposes predefined vehicle styles and colors', () {
|
|
expect(VehicleIconGenerator.availableStyles, isNotEmpty);
|
|
expect(VehicleIconGenerator.availableStyles.any((s) => s.id == 'car'), isTrue);
|
|
expect(VehicleIconGenerator.availableStyles.any((s) => s.id == 'suv'), isTrue);
|
|
expect(VehicleIconGenerator.availableStyles.any((s) => s.id == 'arrow'), isTrue);
|
|
|
|
expect(VehicleIconGenerator.availableColors, isNotEmpty);
|
|
expect(VehicleIconGenerator.availableColors.any((c) => c.colorValue == 0xFF007AFF), isTrue);
|
|
});
|
|
});
|
|
|
|
group('DeepLinkService Tests', () {
|
|
test('Parses basic geo URI', () {
|
|
final target = DeepLinkService.instance.parseUri('geo:31.97869,35.83426');
|
|
expect(target, isNotNull);
|
|
expect(target!.destination.latitude, closeTo(31.97869, 0.0001));
|
|
expect(target.destination.longitude, closeTo(35.83426, 0.0001));
|
|
expect(target.autoStartNavigation, isFalse);
|
|
});
|
|
|
|
test('Parses geo URI with label in parenthesis', () {
|
|
final target = DeepLinkService.instance.parseUri('geo:31.97869,35.83426?q=31.97869,35.83426(المدينة%20الطبية)');
|
|
expect(target, isNotNull);
|
|
expect(target!.destination.latitude, closeTo(31.97869, 0.0001));
|
|
expect(target.destination.longitude, closeTo(35.83426, 0.0001));
|
|
expect(target.title, equals('المدينة الطبية'));
|
|
});
|
|
|
|
test('Parses geo:0,0 query format used by Android apps', () {
|
|
final target = DeepLinkService.instance.parseUri('geo:0,0?q=31.9539,35.9106(سيتي%20مول)');
|
|
expect(target, isNotNull);
|
|
expect(target!.destination.latitude, closeTo(31.9539, 0.0001));
|
|
expect(target.destination.longitude, closeTo(35.9106, 0.0001));
|
|
expect(target.title, equals('سيتي مول'));
|
|
});
|
|
|
|
test('Parses custom siromaps://navigate with autoStartNavigation', () {
|
|
final target = DeepLinkService.instance.parseUri('siromaps://navigate?lat=31.97869&lng=35.83426&title=مدينة_الحسين_الطبية');
|
|
expect(target, isNotNull);
|
|
expect(target!.destination.latitude, closeTo(31.97869, 0.0001));
|
|
expect(target.destination.longitude, closeTo(35.83426, 0.0001));
|
|
expect(target.title, equals('مدينة_الحسين_الطبية'));
|
|
expect(target.autoStartNavigation, isTrue);
|
|
});
|
|
|
|
test('Parses custom siromaps://route with preview mode', () {
|
|
final target = DeepLinkService.instance.parseUri('siromaps://route?dlat=32.01&dlng=35.86&dname=جامعة_اليرموك');
|
|
expect(target, isNotNull);
|
|
expect(target!.destination.latitude, closeTo(32.01, 0.0001));
|
|
expect(target.destination.longitude, closeTo(35.86, 0.0001));
|
|
expect(target.title, equals('جامعة_اليرموك'));
|
|
expect(target.autoStartNavigation, isFalse);
|
|
});
|
|
|
|
test('Parses google.navigation URI intent', () {
|
|
final target = DeepLinkService.instance.parseUri('google.navigation:q=31.97869,35.83426&mode=d');
|
|
expect(target, isNotNull);
|
|
expect(target!.destination.latitude, closeTo(31.97869, 0.0001));
|
|
expect(target.destination.longitude, closeTo(35.83426, 0.0001));
|
|
expect(target.autoStartNavigation, isTrue);
|
|
});
|
|
|
|
test('Parses Google Maps URL', () {
|
|
final target = DeepLinkService.instance.parseUri('https://www.google.com/maps/dir/?api=1&destination=31.97869,35.83426');
|
|
expect(target, isNotNull);
|
|
expect(target!.destination.latitude, closeTo(31.97869, 0.0001));
|
|
expect(target.destination.longitude, closeTo(35.83426, 0.0001));
|
|
});
|
|
|
|
test('Parses Universal Siro Web Link', () {
|
|
final target = DeepLinkService.instance.parseUri('https://maps.siro.app/navigate?lat=31.97869&lng=35.83426&title=المدينة%20الطبية');
|
|
expect(target, isNotNull);
|
|
expect(target!.destination.latitude, closeTo(31.97869, 0.0001));
|
|
expect(target.destination.longitude, closeTo(35.83426, 0.0001));
|
|
expect(target.title, equals('المدينة الطبية'));
|
|
expect(target.autoStartNavigation, isTrue);
|
|
});
|
|
|
|
test('Returns null on invalid or empty URIs', () {
|
|
expect(DeepLinkService.instance.parseUri(''), isNull);
|
|
expect(DeepLinkService.instance.parseUri('invalid_link_without_coords'), isNull);
|
|
expect(DeepLinkService.instance.parseUri('geo:invalid,coords'), isNull);
|
|
});
|
|
});
|
|
|
|
group('PipService Tests', () {
|
|
test('PipService initializes and reports supported', () async {
|
|
final pip = PipService.instance;
|
|
pip.init();
|
|
final supported = await pip.isPipSupported();
|
|
expect(supported, isTrue);
|
|
});
|
|
|
|
test('PipService toggles and enters/exits PiP mode correctly', () async {
|
|
final pip = PipService.instance;
|
|
await pip.exitPictureInPicture();
|
|
expect(pip.isInPipMode.value, isFalse);
|
|
|
|
await pip.enterPictureInPicture();
|
|
expect(pip.isInPipMode.value, isTrue);
|
|
|
|
await pip.exitPictureInPicture();
|
|
expect(pip.isInPipMode.value, isFalse);
|
|
|
|
await pip.togglePip();
|
|
expect(pip.isInPipMode.value, isTrue);
|
|
|
|
await pip.togglePip();
|
|
expect(pip.isInPipMode.value, isFalse);
|
|
});
|
|
});
|
|
}
|
|
|