import 'dart:convert'; import 'package:flutter_test/flutter_test.dart'; import 'package:http/http.dart' as http; import 'package:http/testing.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:siro_maps/core/constants/api_constants.dart'; import 'package:siro_maps/core/services/device_fingerprint_service.dart'; import 'package:siro_maps/data/models/place_gate.dart'; import 'package:siro_maps/data/models/place_model.dart'; void main() { TestWidgetsFlutterBinding.ensureInitialized(); group('PlaceGate & PlaceModel Tests', () { test('PlaceGate parses json correctly', () { final json = { 'name_ar': 'بوابة رقم 1 - كارفور', 'name_en': 'Gate 1 - Carrefour', 'latitude': 31.9712, 'longitude': 35.8456, 'is_main_gate': true, }; final gate = PlaceGate.fromJson(json); expect(gate.nameAr, equals('بوابة رقم 1 - كارفور')); expect(gate.nameEn, equals('Gate 1 - Carrefour')); expect(gate.latitude, equals(31.9712)); expect(gate.longitude, equals(35.8456)); expect(gate.isMainGate, isTrue); final outJson = gate.toJson(); expect(outJson['name_ar'], equals('بوابة رقم 1 - كارفور')); expect(outJson['is_main_gate'], isTrue); }); test('PlaceModel parses gates array from API payload', () { final rawPlace = { 'id': 'poi_city_mall', 'name': 'سيتي مول عمان', 'category': 'mall', 'latitude': 31.9823, 'longitude': 35.8344, 'elevation_meters': 980.5, 'gates': [ { 'name_ar': 'بوابة 1 - الطوارئ والخدمات', 'latitude': 31.9820, 'longitude': 35.8340, 'is_main_gate': false, }, { 'name_ar': 'بوابة 2 - المدخل الرئيسي والزوار', 'latitude': 31.9825, 'longitude': 35.8346, 'is_main_gate': true, } ] }; final place = PlaceModel.fromJson(rawPlace); expect(place.id, equals('poi_city_mall')); expect(place.name, equals('سيتي مول عمان')); expect(place.hasGates, isTrue); expect(place.gates.length, equals(2)); expect(place.gates.first.nameAr, equals('بوابة 1 - الطوارئ والخدمات')); expect(place.gates.last.isMainGate, isTrue); }); test('PlaceModel handles empty or null gates gracefully', () { final rawPlace = { 'name': 'كافيه عادي', 'category': 'cafe', 'latitude': 31.95, 'longitude': 35.91, }; final place = PlaceModel.fromJson(rawPlace); expect(place.hasGates, isFalse); expect(place.gates, isEmpty); }); }); group('DeviceFingerprintService Tests', () { setUp(() { SharedPreferences.setMockInitialValues({}); }); test('Generates deterministic hardware fingerprint and initializes headers', () async { final service = DeviceFingerprintService.instance; await service.init(); expect(service.fingerprintId, isNotEmpty); expect(service.fingerprintId.startsWith('siro_'), isTrue); expect(service.shortFingerprint.isNotEmpty, isTrue); final headers = service.headers; expect(headers.containsKey('x-device-fingerprint'), isTrue); expect(headers['x-device-fingerprint'], equals(service.fingerprintId)); expect(headers.containsKey('x-client-version'), isTrue); expect(headers.containsKey('x-device-platform'), isTrue); expect(headers.containsKey('x-api-key'), isTrue); expect(headers['x-api-key'], equals(ApiConstants.mapSaasKey)); }); test('Provisions dedicated consumer API key and switches activeApiKey', () async { final service = DeviceFingerprintService.instance; final mockClient = MockClient((request) async { if (request.url.path.contains('/auth/device-provision')) { return http.Response( jsonEncode({ 'apiKey': 'in_mob_unit_test_dedicated_key_998877', 'keyName': 'Siro Mobile - Unit Test Device', 'rateLimit': 60, 'plan': 'FREE', 'deviceFingerprint': service.fingerprintId, 'isNew': true, }), 200, headers: {'content-type': 'application/json'}, ); } return http.Response('Not Found', 404); }); final success = await service.provisionDedicatedApiKey(httpClient: mockClient); expect(success, isTrue); expect(service.activeApiKey, equals('in_mob_unit_test_dedicated_key_998877')); expect(service.isDedicatedKeyActive, isTrue); expect(service.rateLimit, equals(60)); expect(service.headers['x-api-key'], equals('in_mob_unit_test_dedicated_key_998877')); }); test('Falls back gracefully to embedded key if provisioning fails or is offline', () async { final service = DeviceFingerprintService.instance; final offlineClient = MockClient((request) async { return http.Response('Internal Server Error', 500); }); service.setMockState( fingerprint: 'siro_test_hw_offline_device', clearApiKey: true, ); final success = await service.provisionDedicatedApiKey(httpClient: offlineClient); expect(success, isFalse); // Falls back to master MapSaaS key without crashing expect(service.activeApiKey, equals(ApiConstants.mapSaasKey)); expect(service.isDedicatedKeyActive, isFalse); }); }); }