diff --git a/test/network_service_impl_test.dart b/test/network_service_impl_test.dart new file mode 100644 index 000000000..0eaac5591 --- /dev/null +++ b/test/network_service_impl_test.dart @@ -0,0 +1,303 @@ +import 'package:flutter/services.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:registration_client/platform_android/network_service_impl.dart'; + +void main() { + TestWidgetsFlutterBinding.ensureInitialized(); + + late NetworkServiceImpl networkService; + + const StandardMessageCodec codec = StandardMessageCodec(); + + const List saveVersionChannels = [ + 'dev.flutter.pigeon.registration_client.CommonDetailsApi.saveVersionToGlobalParam', + 'dev.flutter.pigeon.registration_client.pigeon.CommonDetailsApi.saveVersionToGlobalParam', + ]; + + const List getVersionChannels = [ + 'dev.flutter.pigeon.registration_client.CommonDetailsApi.getVersionFromGlobalParam', + 'dev.flutter.pigeon.registration_client.pigeon.CommonDetailsApi.getVersionFromGlobalParam', + ]; + + void mockStringResponse(List channels, String value) { + for (final channel in channels) { + TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger + .setMockMessageHandler(channel, (ByteData? message) async { + return codec.encodeMessage([value]); + }); + } + } + + void mockPlatformError(List channels) { + for (final channel in channels) { + TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger + .setMockMessageHandler(channel, (ByteData? message) async { + return codec.encodeMessage([ + 'error', + 'Mock platform error', + null, + ]); + }); + } + } + + void clearMockHandlers() { + for (final channel in [ + ...saveVersionChannels, + ...getVersionChannels, + ]) { + TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger + .setMockMessageHandler(channel, null); + } + } + + setUp(() { + networkService = NetworkServiceImpl(); + + mockStringResponse(saveVersionChannels, 'saved_successfully'); + mockStringResponse(getVersionChannels, '1.0.0'); + }); + + tearDown(() { + clearMockHandlers(); + }); + + group('Factory Tests', () { + test('getNetworkServiceImpl returns NetworkServiceImpl instance', () { + final service = getNetworkServiceImpl(); + + expect(service, isA()); + }); + + test('factory creates separate instances', () { + final first = getNetworkServiceImpl(); + final second = getNetworkServiceImpl(); + + expect(first, isNot(same(second))); + }); + }); + + group('Service Initialization Tests', () { + test('NetworkServiceImpl initializes correctly', () { + expect(networkService, isNotNull); + }); + + test('multiple instances remain independent', () { + final first = NetworkServiceImpl(); + final second = NetworkServiceImpl(); + + expect(first, isNot(same(second))); + }); + }); + + group('checkInternetConnection Tests', () { + test('checkInternetConnection method exists', () { + expect(networkService.checkInternetConnection, isA()); + }); + }); + + group('getVersionNoApp Tests', () { + test('getVersionNoApp method exists', () { + expect(networkService.getVersionNoApp, isA()); + }); + }); + + group('saveVersionToGlobalParam Tests', () { + test('saveVersionToGlobalParam returns success response', () async { + final response = await networkService.saveVersionToGlobalParam( + 'version_id', + '1.0.0', + ); + + expect(response, 'saved_successfully'); + }); + + test('saveVersionToGlobalParam handles empty values', () async { + final response = await networkService.saveVersionToGlobalParam('', ''); + + expect(response, 'saved_successfully'); + }); + + test('saveVersionToGlobalParam handles long strings', () async { + final longString = 'a' * 500; + + final response = await networkService.saveVersionToGlobalParam( + longString, + longString, + ); + + expect(response, 'saved_successfully'); + }); + }); + + group('getVersionFromGobalParam Tests', () { + test('getVersionFromGobalParam returns version successfully', () async { + final response = await networkService.getVersionFromGobalParam( + 'version_id', + ); + + expect(response, '1.0.0'); + }); + + test('getVersionFromGobalParam handles empty id', () async { + final response = await networkService.getVersionFromGobalParam(''); + + expect(response, '1.0.0'); + }); + + test('getVersionFromGobalParam handles special characters', () async { + final response = await networkService.getVersionFromGobalParam( + r'!@#$%^&*()', + ); + + expect(response, '1.0.0'); + }); + }); + + group('saveScreenHeaderToGlobalParam Tests', () { + test('saveScreenHeaderToGlobalParam returns success response', () async { + final response = await networkService.saveScreenHeaderToGlobalParam( + 'header_id', + 'Registration Client', + ); + + expect(response, 'saved_successfully'); + }); + + test('saveScreenHeaderToGlobalParam handles empty values', () async { + final response = await networkService.saveScreenHeaderToGlobalParam( + '', + '', + ); + + expect(response, 'saved_successfully'); + }); + + test('saveScreenHeaderToGlobalParam handles unicode values', () async { + final response = await networkService.saveScreenHeaderToGlobalParam( + 'header', + '测试-प्रशांत-اختبار', + ); + + expect(response, 'saved_successfully'); + }); + }); + + group('Platform Exception Handling Tests', () { + test('saveVersionToGlobalParam returns empty string on platform error', + () async { + mockPlatformError(saveVersionChannels); + + final response = await networkService.saveVersionToGlobalParam( + 'id', + '1.0.0', + ); + + expect(response, ''); + }); + + test('getVersionFromGobalParam returns empty string on platform error', + () async { + mockPlatformError(getVersionChannels); + + final response = await networkService.getVersionFromGobalParam('id'); + + expect(response, ''); + }); + + test('saveScreenHeaderToGlobalParam returns empty string on platform error', + () async { + mockPlatformError(saveVersionChannels); + + final response = await networkService.saveScreenHeaderToGlobalParam( + 'header', + 'value', + ); + + expect(response, ''); + }); + }); + + group('Edge Case Tests', () { + test('service handles repeated save calls correctly', () async { + for (int i = 0; i < 5; i++) { + final response = await networkService.saveVersionToGlobalParam( + 'id_$i', + 'version_$i', + ); + + expect(response, 'saved_successfully'); + } + }); + + test('service handles special characters correctly', () async { + final response = await networkService.saveScreenHeaderToGlobalParam( + r'!@#$%', + 'Header_测试_प्रशांत', + ); + + expect(response, 'saved_successfully'); + }); + + test('service handles numeric strings correctly', () async { + final response = await networkService.saveVersionToGlobalParam( + '123', + '456', + ); + + expect(response, 'saved_successfully'); + }); + }); + + + group('checkInternetConnection Logic Tests', () { + test('method returns Future type', () { + expect( + networkService.checkInternetConnection(), + isA>(), + ); + }); + }); + + group('getVersionNoApp Logic Tests', () { + test('method returns Future type', () { + expect( + networkService.getVersionNoApp(), + isA>(), + ); + }); + }); + + group('Stability Tests', () { + test('service instance remains stable across calls', () async { + final first = await networkService.saveVersionToGlobalParam( + 'id', + '1.0.0', + ); + + final second = await networkService.getVersionFromGobalParam('id'); + + expect(first, 'saved_successfully'); + expect(second, '1.0.0'); + }); + + test('multiple sequential async calls work correctly', () async { + final responses = []; + + for (int i = 0; i < 3; i++) { + final response = await networkService.saveVersionToGlobalParam( + 'id_$i', + 'version_$i', + ); + + responses.add(response); + } + + expect(responses.length, 3); + expect( + responses.every((element) => element == 'saved_successfully'), + true, + ); + }); + }); +} diff --git a/test/sync_job_def_test.dart b/test/sync_job_def_test.dart new file mode 100644 index 000000000..92cd9c6fe --- /dev/null +++ b/test/sync_job_def_test.dart @@ -0,0 +1,264 @@ +import 'package:flutter_test/flutter_test.dart'; +import 'package:registration_client/utils/sync_job_def.dart'; + +void main() { + group('SyncJobDef Constructor Tests', () { + test('creates SyncJobDef with all values', () { + final syncJobDef = SyncJobDef( + id: 'job_001', + name: 'Master Sync', + apiName: 'masterSyncJob', + parentSyncJobId: 'parent_001', + syncFreq: '30m', + lockDuration: '5m', + langCode: 'eng', + isDeleted: false, + isActive: true, + ); + + expect(syncJobDef.id, 'job_001'); + expect(syncJobDef.name, 'Master Sync'); + expect(syncJobDef.apiName, 'masterSyncJob'); + expect(syncJobDef.parentSyncJobId, 'parent_001'); + expect(syncJobDef.syncFreq, '30m'); + expect(syncJobDef.lockDuration, '5m'); + expect(syncJobDef.langCode, 'eng'); + expect(syncJobDef.isDeleted, false); + expect(syncJobDef.isActive, true); + }); + + test('creates SyncJobDef with nullable values', () { + final syncJobDef = SyncJobDef(); + + expect(syncJobDef.id, null); + expect(syncJobDef.name, null); + expect(syncJobDef.apiName, null); + expect(syncJobDef.parentSyncJobId, null); + expect(syncJobDef.syncFreq, null); + expect(syncJobDef.lockDuration, null); + expect(syncJobDef.langCode, null); + expect(syncJobDef.isDeleted, null); + expect(syncJobDef.isActive, null); + }); + }); + + group('fromJson Tests', () { + test('fromJson parses complete json correctly', () { + final json = { + 'id': 'job_001', + 'name': 'Master Sync', + 'apiName': 'masterSyncJob', + 'parentSyncJobId': 'parent_001', + 'syncFreq': '30m', + 'lockDuration': '5m', + 'langCode': 'eng', + 'isDeleted': false, + 'isActive': true, + }; + + final syncJobDef = SyncJobDef.fromJson(json); + + expect(syncJobDef.id, 'job_001'); + expect(syncJobDef.name, 'Master Sync'); + expect(syncJobDef.apiName, 'masterSyncJob'); + expect(syncJobDef.parentSyncJobId, 'parent_001'); + expect(syncJobDef.syncFreq, '30m'); + expect(syncJobDef.lockDuration, '5m'); + expect(syncJobDef.langCode, 'eng'); + expect(syncJobDef.isDeleted, false); + expect(syncJobDef.isActive, true); + }); + + test('fromJson handles null values correctly', () { + final json = { + 'id': null, + 'name': null, + 'apiName': null, + 'parentSyncJobId': null, + 'syncFreq': null, + 'lockDuration': null, + 'langCode': null, + 'isDeleted': null, + 'isActive': null, + }; + + final syncJobDef = SyncJobDef.fromJson(json); + + expect(syncJobDef.id, null); + expect(syncJobDef.name, null); + expect(syncJobDef.apiName, null); + expect(syncJobDef.parentSyncJobId, null); + expect(syncJobDef.syncFreq, null); + expect(syncJobDef.lockDuration, null); + expect(syncJobDef.langCode, null); + expect(syncJobDef.isDeleted, null); + expect(syncJobDef.isActive, null); + }); + + test('fromJson handles empty json correctly', () { + final syncJobDef = SyncJobDef.fromJson({}); + + expect(syncJobDef.id, null); + expect(syncJobDef.name, null); + expect(syncJobDef.apiName, null); + expect(syncJobDef.parentSyncJobId, null); + expect(syncJobDef.syncFreq, null); + expect(syncJobDef.lockDuration, null); + expect(syncJobDef.langCode, null); + expect(syncJobDef.isDeleted, null); + expect(syncJobDef.isActive, null); + }); + + test('fromJson ignores extra json fields', () { + final json = { + 'id': 'job_002', + 'name': 'Global Params Sync', + 'apiName': 'globalParamsSyncJob', + 'extraField': 'extra_value', + 'anotherExtraField': 12345, + }; + + final syncJobDef = SyncJobDef.fromJson(json); + + expect(syncJobDef.id, 'job_002'); + expect(syncJobDef.name, 'Global Params Sync'); + expect(syncJobDef.apiName, 'globalParamsSyncJob'); + expect(syncJobDef.parentSyncJobId, null); + expect(syncJobDef.syncFreq, null); + expect(syncJobDef.lockDuration, null); + expect(syncJobDef.langCode, null); + expect(syncJobDef.isDeleted, null); + expect(syncJobDef.isActive, null); + }); + }); + + group('Boolean Field Tests', () { + test('isDeleted supports true value', () { + final syncJobDef = SyncJobDef.fromJson({ + 'isDeleted': true, + }); + + expect(syncJobDef.isDeleted, true); + }); + + test('isDeleted supports false value', () { + final syncJobDef = SyncJobDef.fromJson({ + 'isDeleted': false, + }); + + expect(syncJobDef.isDeleted, false); + }); + + test('isActive supports true value', () { + final syncJobDef = SyncJobDef.fromJson({ + 'isActive': true, + }); + + expect(syncJobDef.isActive, true); + }); + + test('isActive supports false value', () { + final syncJobDef = SyncJobDef.fromJson({ + 'isActive': false, + }); + + expect(syncJobDef.isActive, false); + }); + }); + + group('Edge Case Tests', () { + test('supports long string values', () { + final longString = 'a' * 1000; + + final syncJobDef = SyncJobDef( + id: longString, + name: longString, + apiName: longString, + parentSyncJobId: longString, + syncFreq: longString, + lockDuration: longString, + langCode: longString, + ); + + expect(syncJobDef.id, longString); + expect(syncJobDef.name, longString); + expect(syncJobDef.apiName, longString); + expect(syncJobDef.parentSyncJobId, longString); + expect(syncJobDef.syncFreq, longString); + expect(syncJobDef.lockDuration, longString); + expect(syncJobDef.langCode, longString); + }); + + test('supports special characters in string values', () { + const specialString = r'!@#$%^&*()_+-=[]{}|;:",.<>?/`~'; + + final syncJobDef = SyncJobDef( + id: specialString, + name: specialString, + apiName: specialString, + ); + + expect(syncJobDef.id, specialString); + expect(syncJobDef.name, specialString); + expect(syncJobDef.apiName, specialString); + }); + + test('supports unicode characters', () { + const unicodeString = 'सिंक-जॉब-测试-وظيفة'; + + final syncJobDef = SyncJobDef( + id: unicodeString, + name: unicodeString, + ); + + expect(syncJobDef.id, unicodeString); + expect(syncJobDef.name, unicodeString); + }); + + test('supports empty string values', () { + final syncJobDef = SyncJobDef( + id: '', + name: '', + apiName: '', + ); + + expect(syncJobDef.id, ''); + expect(syncJobDef.name, ''); + expect(syncJobDef.apiName, ''); + }); + }); + + group('Instance Integrity Tests', () { + test('multiple instances maintain independent values', () { + final firstSyncJob = SyncJobDef( + id: 'job_001', + name: 'Master Sync', + ); + + final secondSyncJob = SyncJobDef( + id: 'job_002', + name: 'Policy Sync', + ); + + expect(firstSyncJob.id, 'job_001'); + expect(firstSyncJob.name, 'Master Sync'); + + expect(secondSyncJob.id, 'job_002'); + expect(secondSyncJob.name, 'Policy Sync'); + }); + + test('fromJson creates separate object instances', () { + final json = { + 'id': 'job_001', + 'name': 'Master Sync', + }; + + final firstInstance = SyncJobDef.fromJson(json); + final secondInstance = SyncJobDef.fromJson(json); + + expect(firstInstance, isNot(same(secondInstance))); + expect(firstInstance.id, secondInstance.id); + expect(firstInstance.name, secondInstance.name); + }); + }); +} \ No newline at end of file