159 lines
5.5 KiB
Dart
159 lines
5.5 KiB
Dart
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);
|
|
});
|
|
});
|
|
}
|