From 7a2cfc722c580d6ee6f3f3438bcec60dcfa7a425 Mon Sep 17 00:00:00 2001 From: Kirk Morrow <9563562+kirkmorrow@users.noreply.github.com> Date: Tue, 2 Dec 2025 09:30:53 -0600 Subject: [PATCH 1/9] Use new ethernet enum Part 2 of 2 fixes to address issue #1042 --- packages/flutter/lib/parse_server_sdk_flutter.dart | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/packages/flutter/lib/parse_server_sdk_flutter.dart b/packages/flutter/lib/parse_server_sdk_flutter.dart index 2f1f5a2f..aef9fd53 100644 --- a/packages/flutter/lib/parse_server_sdk_flutter.dart +++ b/packages/flutter/lib/parse_server_sdk_flutter.dart @@ -122,6 +122,8 @@ class Parse extends sdk.Parse if (list.contains(ConnectivityResult.wifi)) { return sdk.ParseConnectivityResult.wifi; + } else if (list.contains(ConnectivityResult.ethernet)) { + return sdk.ParseConnectivityResult.ethernet; } else if (list.contains(ConnectivityResult.mobile)) { return sdk.ParseConnectivityResult.mobile; } else { @@ -136,6 +138,8 @@ class Parse extends sdk.Parse ) { if (event.contains(ConnectivityResult.wifi)) { return sdk.ParseConnectivityResult.wifi; + } else if (event.contains(ConnectivityResult.ethernet)) { + return sdk.ParseConnectivityResult.ethernet; } else if (event.contains(ConnectivityResult.mobile)) { return sdk.ParseConnectivityResult.mobile; } else { From 83ffd5a8e3b410d872afbff2c505bd13edc162ce Mon Sep 17 00:00:00 2001 From: Kirk Morrow <9563562+kirkmorrow@users.noreply.github.com> Date: Tue, 2 Dec 2025 12:45:30 -0600 Subject: [PATCH 2/9] Update parse_server_sdk minimum level --- packages/flutter/pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/flutter/pubspec.yaml b/packages/flutter/pubspec.yaml index 0af1b179..74c8ddff 100644 --- a/packages/flutter/pubspec.yaml +++ b/packages/flutter/pubspec.yaml @@ -25,7 +25,7 @@ dependencies: flutter: sdk: flutter - parse_server_sdk: ">=6.4.0 <10.0.0" + parse_server_sdk: ">=9.4.2 <10.0.0" # Uncomment for local testing #parse_server_sdk: # path: ../dart From 80c45a473184fe355a0f882be939c26b228dee6f Mon Sep 17 00:00:00 2001 From: Kirk Morrow <9563562+kirkmorrow@users.noreply.github.com> Date: Tue, 2 Dec 2025 12:56:09 -0600 Subject: [PATCH 3/9] Simple tests --- .../test/parse_connectivity_mapping_test.dart | 161 ++++++++++++++++++ 1 file changed, 161 insertions(+) create mode 100644 packages/flutter/test/parse_connectivity_mapping_test.dart diff --git a/packages/flutter/test/parse_connectivity_mapping_test.dart b/packages/flutter/test/parse_connectivity_mapping_test.dart new file mode 100644 index 00000000..18b8a4b3 --- /dev/null +++ b/packages/flutter/test/parse_connectivity_mapping_test.dart @@ -0,0 +1,161 @@ +import 'package:connectivity_plus/connectivity_plus.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:parse_server_sdk_flutter/parse_server_sdk_flutter.dart'; + +void main() { + TestWidgetsFlutterBinding.ensureInitialized(); + + group('Connectivity mapping logic', () { + test('should map connectivity_plus results to ParseConnectivityResult', + () { + // This test documents the expected mapping behavior + // The actual Parse class implementation follows this mapping: + + // Test enum structure + expect(ParseConnectivityResult.values.length, 4); + expect(ParseConnectivityResult.values, + containsAll([ + ParseConnectivityResult.wifi, + ParseConnectivityResult.ethernet, + ParseConnectivityResult.mobile, + ParseConnectivityResult.none, + ])); + }); + + test('ParseConnectivityResult should have correct ordering for priority', + () { + // Verify enum ordering (wifi has highest priority in the if-else chain) + expect(ParseConnectivityResult.wifi.index, 0); + expect(ParseConnectivityResult.ethernet.index, 1); + expect(ParseConnectivityResult.mobile.index, 2); + expect(ParseConnectivityResult.none.index, 3); + }); + + test('should identify online vs offline states correctly', () { + // Online states + expect(ParseConnectivityResult.wifi != ParseConnectivityResult.none, + true); + expect( + ParseConnectivityResult.ethernet != ParseConnectivityResult.none, + true); + expect(ParseConnectivityResult.mobile != ParseConnectivityResult.none, + true); + + // Offline state + expect(ParseConnectivityResult.none == ParseConnectivityResult.none, + true); + }); + + test('mapping logic follows priority: wifi > ethernet > mobile > none', + () { + // This documents the if-else chain priority in checkConnectivity() + // If a list contains wifi, it returns wifi + // Else if it contains ethernet, it returns ethernet + // Else if it contains mobile, it returns mobile + // Else it returns none + + // Simulating the mapping logic + ParseConnectivityResult mapResult(List list) { + if (list.contains(ConnectivityResult.wifi)) { + return ParseConnectivityResult.wifi; + } else if (list.contains(ConnectivityResult.ethernet)) { + return ParseConnectivityResult.ethernet; + } else if (list.contains(ConnectivityResult.mobile)) { + return ParseConnectivityResult.mobile; + } else { + return ParseConnectivityResult.none; + } + } + + // Test single connection types + expect(mapResult([ConnectivityResult.wifi]), + ParseConnectivityResult.wifi); + expect(mapResult([ConnectivityResult.ethernet]), + ParseConnectivityResult.ethernet); + expect(mapResult([ConnectivityResult.mobile]), + ParseConnectivityResult.mobile); + expect(mapResult([ConnectivityResult.none]), + ParseConnectivityResult.none); + + // Test priority when multiple connections exist + expect(mapResult([ConnectivityResult.wifi, ConnectivityResult.ethernet]), + ParseConnectivityResult.wifi); + expect(mapResult([ConnectivityResult.wifi, ConnectivityResult.mobile]), + ParseConnectivityResult.wifi); + expect( + mapResult([ConnectivityResult.ethernet, ConnectivityResult.mobile]), + ParseConnectivityResult.ethernet); + + // Test that ethernet takes priority over mobile (important for issue #1042) + expect( + mapResult([ConnectivityResult.mobile, ConnectivityResult.ethernet]), + ParseConnectivityResult.ethernet); + + // Test fallback behavior for unsupported types + expect(mapResult([ConnectivityResult.bluetooth]), + ParseConnectivityResult.none); + expect(mapResult([ConnectivityResult.vpn]), ParseConnectivityResult.none); + expect( + mapResult([ConnectivityResult.other]), ParseConnectivityResult.none); + + // Test mixed with unsupported types + expect( + mapResult([ConnectivityResult.ethernet, ConnectivityResult.vpn]), + ParseConnectivityResult.ethernet); + }); + + test('ethernet should be treated as online connection type', () { + // Critical test for issue #1042 fix + // Ethernet must be treated as an online state, not as "none" + + final isOnline = + ParseConnectivityResult.ethernet != ParseConnectivityResult.none; + expect(isOnline, true, + reason: + 'Ethernet should be treated as online for LiveQuery connectivity'); + }); + + test('all online states should be distinguishable from none', () { + final onlineStates = [ + ParseConnectivityResult.wifi, + ParseConnectivityResult.ethernet, + ParseConnectivityResult.mobile, + ]; + + for (final state in onlineStates) { + expect(state != ParseConnectivityResult.none, true, + reason: '$state should be distinguishable from none'); + } + }); + }); + + group('ConnectivityResult enum compatibility', () { + test('should handle all connectivity_plus enum values', () { + // Ensure we're aware of all possible values from connectivity_plus + final allConnectivityResults = [ + ConnectivityResult.wifi, + ConnectivityResult.ethernet, + ConnectivityResult.mobile, + ConnectivityResult.none, + ConnectivityResult.bluetooth, + ConnectivityResult.vpn, + ConnectivityResult.other, + ]; + + // Verify all values exist (will fail if connectivity_plus adds new values) + expect(allConnectivityResults.length, 7); + }); + + test('ParseConnectivityResult should support main connection types', () { + // The Parse SDK should support the main internet connection types + final supportedTypes = [ + ParseConnectivityResult.wifi, + ParseConnectivityResult.ethernet, + ParseConnectivityResult.mobile, + ]; + + expect(supportedTypes.length, 3, + reason: 'Should support 3 main online connection types'); + }); + }); +} From 79359ed5dce09d2fb07e878380ff01a2b859fac8 Mon Sep 17 00:00:00 2001 From: Kirk Morrow <9563562+kirkmorrow@users.noreply.github.com> Date: Tue, 2 Dec 2025 13:29:31 -0600 Subject: [PATCH 4/9] Test cleanup Revert pubspec.yaml changes --- packages/flutter/pubspec.yaml | 2 +- .../test/parse_connectivity_mapping_test.dart | 103 +----------------- 2 files changed, 4 insertions(+), 101 deletions(-) diff --git a/packages/flutter/pubspec.yaml b/packages/flutter/pubspec.yaml index 74c8ddff..0af1b179 100644 --- a/packages/flutter/pubspec.yaml +++ b/packages/flutter/pubspec.yaml @@ -25,7 +25,7 @@ dependencies: flutter: sdk: flutter - parse_server_sdk: ">=9.4.2 <10.0.0" + parse_server_sdk: ">=6.4.0 <10.0.0" # Uncomment for local testing #parse_server_sdk: # path: ../dart diff --git a/packages/flutter/test/parse_connectivity_mapping_test.dart b/packages/flutter/test/parse_connectivity_mapping_test.dart index 18b8a4b3..a5b38703 100644 --- a/packages/flutter/test/parse_connectivity_mapping_test.dart +++ b/packages/flutter/test/parse_connectivity_mapping_test.dart @@ -6,55 +6,12 @@ void main() { TestWidgetsFlutterBinding.ensureInitialized(); group('Connectivity mapping logic', () { - test('should map connectivity_plus results to ParseConnectivityResult', - () { - // This test documents the expected mapping behavior - // The actual Parse class implementation follows this mapping: - - // Test enum structure - expect(ParseConnectivityResult.values.length, 4); - expect(ParseConnectivityResult.values, - containsAll([ - ParseConnectivityResult.wifi, - ParseConnectivityResult.ethernet, - ParseConnectivityResult.mobile, - ParseConnectivityResult.none, - ])); - }); - - test('ParseConnectivityResult should have correct ordering for priority', - () { - // Verify enum ordering (wifi has highest priority in the if-else chain) - expect(ParseConnectivityResult.wifi.index, 0); - expect(ParseConnectivityResult.ethernet.index, 1); - expect(ParseConnectivityResult.mobile.index, 2); - expect(ParseConnectivityResult.none.index, 3); - }); - - test('should identify online vs offline states correctly', () { - // Online states - expect(ParseConnectivityResult.wifi != ParseConnectivityResult.none, - true); - expect( - ParseConnectivityResult.ethernet != ParseConnectivityResult.none, - true); - expect(ParseConnectivityResult.mobile != ParseConnectivityResult.none, - true); - - // Offline state - expect(ParseConnectivityResult.none == ParseConnectivityResult.none, - true); - }); - test('mapping logic follows priority: wifi > ethernet > mobile > none', () { // This documents the if-else chain priority in checkConnectivity() - // If a list contains wifi, it returns wifi - // Else if it contains ethernet, it returns ethernet - // Else if it contains mobile, it returns mobile - // Else it returns none + // and connectivityStream mapping logic - // Simulating the mapping logic + // Simulating the actual mapping logic from parse_server_sdk_flutter.dart ParseConnectivityResult mapResult(List list) { if (list.contains(ConnectivityResult.wifi)) { return ParseConnectivityResult.wifi; @@ -86,7 +43,7 @@ void main() { mapResult([ConnectivityResult.ethernet, ConnectivityResult.mobile]), ParseConnectivityResult.ethernet); - // Test that ethernet takes priority over mobile (important for issue #1042) + // Test that ethernet takes priority over mobile (critical for issue #1042) expect( mapResult([ConnectivityResult.mobile, ConnectivityResult.ethernet]), ParseConnectivityResult.ethernet); @@ -103,59 +60,5 @@ void main() { mapResult([ConnectivityResult.ethernet, ConnectivityResult.vpn]), ParseConnectivityResult.ethernet); }); - - test('ethernet should be treated as online connection type', () { - // Critical test for issue #1042 fix - // Ethernet must be treated as an online state, not as "none" - - final isOnline = - ParseConnectivityResult.ethernet != ParseConnectivityResult.none; - expect(isOnline, true, - reason: - 'Ethernet should be treated as online for LiveQuery connectivity'); - }); - - test('all online states should be distinguishable from none', () { - final onlineStates = [ - ParseConnectivityResult.wifi, - ParseConnectivityResult.ethernet, - ParseConnectivityResult.mobile, - ]; - - for (final state in onlineStates) { - expect(state != ParseConnectivityResult.none, true, - reason: '$state should be distinguishable from none'); - } - }); - }); - - group('ConnectivityResult enum compatibility', () { - test('should handle all connectivity_plus enum values', () { - // Ensure we're aware of all possible values from connectivity_plus - final allConnectivityResults = [ - ConnectivityResult.wifi, - ConnectivityResult.ethernet, - ConnectivityResult.mobile, - ConnectivityResult.none, - ConnectivityResult.bluetooth, - ConnectivityResult.vpn, - ConnectivityResult.other, - ]; - - // Verify all values exist (will fail if connectivity_plus adds new values) - expect(allConnectivityResults.length, 7); - }); - - test('ParseConnectivityResult should support main connection types', () { - // The Parse SDK should support the main internet connection types - final supportedTypes = [ - ParseConnectivityResult.wifi, - ParseConnectivityResult.ethernet, - ParseConnectivityResult.mobile, - ]; - - expect(supportedTypes.length, 3, - reason: 'Should support 3 main online connection types'); - }); }); } From a3776f992f9ed9e3090421be887d7fc775a0a41f Mon Sep 17 00:00:00 2001 From: Kirk Morrow <9563562+kirkmorrow@users.noreply.github.com> Date: Wed, 3 Dec 2025 08:04:12 -0600 Subject: [PATCH 5/9] Add comments --- packages/flutter/lib/parse_server_sdk_flutter.dart | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/flutter/lib/parse_server_sdk_flutter.dart b/packages/flutter/lib/parse_server_sdk_flutter.dart index aef9fd53..f023f86b 100644 --- a/packages/flutter/lib/parse_server_sdk_flutter.dart +++ b/packages/flutter/lib/parse_server_sdk_flutter.dart @@ -120,6 +120,7 @@ class Parse extends sdk.Parse Future checkConnectivity() async { List list = await Connectivity().checkConnectivity(); + // Priority mapping: wifi > ethernet > mobile > none if (list.contains(ConnectivityResult.wifi)) { return sdk.ParseConnectivityResult.wifi; } else if (list.contains(ConnectivityResult.ethernet)) { @@ -136,6 +137,7 @@ class Parse extends sdk.Parse return Connectivity().onConnectivityChanged.map(( List event, ) { + // Priority mapping: wifi > ethernet > mobile > none if (event.contains(ConnectivityResult.wifi)) { return sdk.ParseConnectivityResult.wifi; } else if (event.contains(ConnectivityResult.ethernet)) { From e662b84c4f2533e6a40573029f104e077809189f Mon Sep 17 00:00:00 2001 From: Kirk Morrow <9563562+kirkmorrow@users.noreply.github.com> Date: Wed, 3 Dec 2025 09:32:20 -0600 Subject: [PATCH 6/9] Bump parse_server_sdk dependency to 9.4.2 --- packages/flutter/pubspec.yaml | 2 +- .../test/parse_connectivity_mapping_test.dart | 64 ++++++++++++------- 2 files changed, 42 insertions(+), 24 deletions(-) diff --git a/packages/flutter/pubspec.yaml b/packages/flutter/pubspec.yaml index 0af1b179..74c8ddff 100644 --- a/packages/flutter/pubspec.yaml +++ b/packages/flutter/pubspec.yaml @@ -25,7 +25,7 @@ dependencies: flutter: sdk: flutter - parse_server_sdk: ">=6.4.0 <10.0.0" + parse_server_sdk: ">=9.4.2 <10.0.0" # Uncomment for local testing #parse_server_sdk: # path: ../dart diff --git a/packages/flutter/test/parse_connectivity_mapping_test.dart b/packages/flutter/test/parse_connectivity_mapping_test.dart index a5b38703..cbaf5571 100644 --- a/packages/flutter/test/parse_connectivity_mapping_test.dart +++ b/packages/flutter/test/parse_connectivity_mapping_test.dart @@ -6,8 +6,7 @@ void main() { TestWidgetsFlutterBinding.ensureInitialized(); group('Connectivity mapping logic', () { - test('mapping logic follows priority: wifi > ethernet > mobile > none', - () { + test('mapping logic follows priority: wifi > ethernet > mobile > none', () { // This documents the if-else chain priority in checkConnectivity() // and connectivityStream mapping logic @@ -25,40 +24,59 @@ void main() { } // Test single connection types - expect(mapResult([ConnectivityResult.wifi]), - ParseConnectivityResult.wifi); - expect(mapResult([ConnectivityResult.ethernet]), - ParseConnectivityResult.ethernet); - expect(mapResult([ConnectivityResult.mobile]), - ParseConnectivityResult.mobile); - expect(mapResult([ConnectivityResult.none]), - ParseConnectivityResult.none); + expect( + mapResult([ConnectivityResult.wifi]), + ParseConnectivityResult.wifi, + ); + expect( + mapResult([ConnectivityResult.ethernet]), + ParseConnectivityResult.ethernet, + ); + expect( + mapResult([ConnectivityResult.mobile]), + ParseConnectivityResult.mobile, + ); + expect( + mapResult([ConnectivityResult.none]), + ParseConnectivityResult.none, + ); // Test priority when multiple connections exist - expect(mapResult([ConnectivityResult.wifi, ConnectivityResult.ethernet]), - ParseConnectivityResult.wifi); - expect(mapResult([ConnectivityResult.wifi, ConnectivityResult.mobile]), - ParseConnectivityResult.wifi); expect( - mapResult([ConnectivityResult.ethernet, ConnectivityResult.mobile]), - ParseConnectivityResult.ethernet); + mapResult([ConnectivityResult.wifi, ConnectivityResult.ethernet]), + ParseConnectivityResult.wifi, + ); + expect( + mapResult([ConnectivityResult.wifi, ConnectivityResult.mobile]), + ParseConnectivityResult.wifi, + ); + expect( + mapResult([ConnectivityResult.ethernet, ConnectivityResult.mobile]), + ParseConnectivityResult.ethernet, + ); // Test that ethernet takes priority over mobile (critical for issue #1042) expect( - mapResult([ConnectivityResult.mobile, ConnectivityResult.ethernet]), - ParseConnectivityResult.ethernet); + mapResult([ConnectivityResult.mobile, ConnectivityResult.ethernet]), + ParseConnectivityResult.ethernet, + ); // Test fallback behavior for unsupported types - expect(mapResult([ConnectivityResult.bluetooth]), - ParseConnectivityResult.none); + expect( + mapResult([ConnectivityResult.bluetooth]), + ParseConnectivityResult.none, + ); expect(mapResult([ConnectivityResult.vpn]), ParseConnectivityResult.none); expect( - mapResult([ConnectivityResult.other]), ParseConnectivityResult.none); + mapResult([ConnectivityResult.other]), + ParseConnectivityResult.none, + ); // Test mixed with unsupported types expect( - mapResult([ConnectivityResult.ethernet, ConnectivityResult.vpn]), - ParseConnectivityResult.ethernet); + mapResult([ConnectivityResult.ethernet, ConnectivityResult.vpn]), + ParseConnectivityResult.ethernet, + ); }); }); } From 1edf729f2aa237aea029c7a5612ada76f0790019 Mon Sep 17 00:00:00 2001 From: Kirk Morrow <9563562+kirkmorrow@users.noreply.github.com> Date: Wed, 3 Dec 2025 10:30:52 -0600 Subject: [PATCH 7/9] Improve testing Eliminate duplicated code with helper function --- .../flutter/lib/parse_server_sdk_flutter.dart | 38 ++-- packages/flutter/pubspec.yaml | 1 + ...arse_connectivity_implementation_test.dart | 204 ++++++++++++++++++ .../test/parse_connectivity_mapping_test.dart | 82 ------- 4 files changed, 221 insertions(+), 104 deletions(-) create mode 100644 packages/flutter/test/parse_connectivity_implementation_test.dart delete mode 100644 packages/flutter/test/parse_connectivity_mapping_test.dart diff --git a/packages/flutter/lib/parse_server_sdk_flutter.dart b/packages/flutter/lib/parse_server_sdk_flutter.dart index f023f86b..f1cd4db2 100644 --- a/packages/flutter/lib/parse_server_sdk_flutter.dart +++ b/packages/flutter/lib/parse_server_sdk_flutter.dart @@ -116,38 +116,32 @@ class Parse extends sdk.Parse final StreamController _appResumedStreamController = StreamController(); - @override - Future checkConnectivity() async { - List list = await Connectivity().checkConnectivity(); - - // Priority mapping: wifi > ethernet > mobile > none - if (list.contains(ConnectivityResult.wifi)) { + /// Maps connectivity_plus results to ParseConnectivityResult. + /// + /// Priority: wifi > ethernet > mobile > none + /// This ensures ethernet is treated as an online connection type. + sdk.ParseConnectivityResult _mapConnectivity( + List results) { + if (results.contains(ConnectivityResult.wifi)) { return sdk.ParseConnectivityResult.wifi; - } else if (list.contains(ConnectivityResult.ethernet)) { + } else if (results.contains(ConnectivityResult.ethernet)) { return sdk.ParseConnectivityResult.ethernet; - } else if (list.contains(ConnectivityResult.mobile)) { + } else if (results.contains(ConnectivityResult.mobile)) { return sdk.ParseConnectivityResult.mobile; } else { return sdk.ParseConnectivityResult.none; } } + @override + Future checkConnectivity() async { + List list = await Connectivity().checkConnectivity(); + return _mapConnectivity(list); + } + @override Stream get connectivityStream { - return Connectivity().onConnectivityChanged.map(( - List event, - ) { - // Priority mapping: wifi > ethernet > mobile > none - if (event.contains(ConnectivityResult.wifi)) { - return sdk.ParseConnectivityResult.wifi; - } else if (event.contains(ConnectivityResult.ethernet)) { - return sdk.ParseConnectivityResult.ethernet; - } else if (event.contains(ConnectivityResult.mobile)) { - return sdk.ParseConnectivityResult.mobile; - } else { - return sdk.ParseConnectivityResult.none; - } - }); + return Connectivity().onConnectivityChanged.map(_mapConnectivity); } @override diff --git a/packages/flutter/pubspec.yaml b/packages/flutter/pubspec.yaml index 74c8ddff..888be6a2 100644 --- a/packages/flutter/pubspec.yaml +++ b/packages/flutter/pubspec.yaml @@ -48,6 +48,7 @@ dev_dependencies: sdk: flutter flutter_lints: ">=4.0.0 <7.0.0" + connectivity_plus_platform_interface: ^2.0.0 path_provider_platform_interface: ^2.1.2 plugin_platform_interface: ^2.1.8 diff --git a/packages/flutter/test/parse_connectivity_implementation_test.dart b/packages/flutter/test/parse_connectivity_implementation_test.dart new file mode 100644 index 00000000..fbab6122 --- /dev/null +++ b/packages/flutter/test/parse_connectivity_implementation_test.dart @@ -0,0 +1,204 @@ +import 'dart:async'; + +import 'package:connectivity_plus/connectivity_plus.dart'; +import 'package:connectivity_plus_platform_interface/connectivity_plus_platform_interface.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:parse_server_sdk_flutter/parse_server_sdk_flutter.dart'; +import 'package:plugin_platform_interface/plugin_platform_interface.dart'; + +/// Mock implementation of ConnectivityPlatform for testing +class MockConnectivityPlatform extends Fake + with MockPlatformInterfaceMixin + implements ConnectivityPlatform { + List _connectivity = [ConnectivityResult.none]; + final StreamController> _controller = + StreamController>.broadcast(); + + void setConnectivity(List connectivity) { + _connectivity = connectivity; + _controller.add(connectivity); + } + + @override + Future> checkConnectivity() async { + return _connectivity; + } + + @override + Stream> get onConnectivityChanged => + _controller.stream; + + void dispose() { + _controller.close(); + } +} + +void main() { + TestWidgetsFlutterBinding.ensureInitialized(); + + group('Parse.checkConnectivity() implementation', () { + late MockConnectivityPlatform mockPlatform; + + setUp(() { + mockPlatform = MockConnectivityPlatform(); + ConnectivityPlatform.instance = mockPlatform; + }); + + tearDown(() { + mockPlatform.dispose(); + }); + + test('wifi connection returns ParseConnectivityResult.wifi', () async { + mockPlatform.setConnectivity([ConnectivityResult.wifi]); + + final result = await Parse().checkConnectivity(); + + expect(result, ParseConnectivityResult.wifi); + }); + + test('ethernet connection returns ParseConnectivityResult.ethernet', + () async { + mockPlatform.setConnectivity([ConnectivityResult.ethernet]); + + final result = await Parse().checkConnectivity(); + + expect(result, ParseConnectivityResult.ethernet); + }); + + test('mobile connection returns ParseConnectivityResult.mobile', () async { + mockPlatform.setConnectivity([ConnectivityResult.mobile]); + + final result = await Parse().checkConnectivity(); + + expect(result, ParseConnectivityResult.mobile); + }); + + test('no connection returns ParseConnectivityResult.none', () async { + mockPlatform.setConnectivity([ConnectivityResult.none]); + + final result = await Parse().checkConnectivity(); + + expect(result, ParseConnectivityResult.none); + }); + + test('wifi takes priority over ethernet', () async { + mockPlatform + .setConnectivity([ConnectivityResult.wifi, ConnectivityResult.ethernet]); + + final result = await Parse().checkConnectivity(); + + expect(result, ParseConnectivityResult.wifi); + }); + + test('ethernet takes priority over mobile (issue #1042 fix)', () async { + mockPlatform.setConnectivity( + [ConnectivityResult.ethernet, ConnectivityResult.mobile]); + + final result = await Parse().checkConnectivity(); + + expect(result, ParseConnectivityResult.ethernet); + }); + + test('unsupported connection types fall back to none', () async { + mockPlatform.setConnectivity([ConnectivityResult.bluetooth]); + + final result = await Parse().checkConnectivity(); + + expect(result, ParseConnectivityResult.none); + }); + }); + + group('Parse.connectivityStream implementation', () { + late MockConnectivityPlatform mockPlatform; + + setUp(() { + mockPlatform = MockConnectivityPlatform(); + ConnectivityPlatform.instance = mockPlatform; + }); + + tearDown(() { + mockPlatform.dispose(); + }); + + test('wifi event emits ParseConnectivityResult.wifi', () async { + final completer = Completer(); + final subscription = Parse().connectivityStream.listen((result) { + if (!completer.isCompleted) { + completer.complete(result); + } + }); + + mockPlatform.setConnectivity([ConnectivityResult.wifi]); + + final result = await completer.future; + expect(result, ParseConnectivityResult.wifi); + + await subscription.cancel(); + }); + + test('ethernet event emits ParseConnectivityResult.ethernet', () async { + final completer = Completer(); + final subscription = Parse().connectivityStream.listen((result) { + if (!completer.isCompleted) { + completer.complete(result); + } + }); + + mockPlatform.setConnectivity([ConnectivityResult.ethernet]); + + final result = await completer.future; + expect(result, ParseConnectivityResult.ethernet); + + await subscription.cancel(); + }); + + test('mobile event emits ParseConnectivityResult.mobile', () async { + final completer = Completer(); + final subscription = Parse().connectivityStream.listen((result) { + if (!completer.isCompleted) { + completer.complete(result); + } + }); + + mockPlatform.setConnectivity([ConnectivityResult.mobile]); + + final result = await completer.future; + expect(result, ParseConnectivityResult.mobile); + + await subscription.cancel(); + }); + + test('none event emits ParseConnectivityResult.none', () async { + final completer = Completer(); + final subscription = Parse().connectivityStream.listen((result) { + if (!completer.isCompleted) { + completer.complete(result); + } + }); + + mockPlatform.setConnectivity([ConnectivityResult.none]); + + final result = await completer.future; + expect(result, ParseConnectivityResult.none); + + await subscription.cancel(); + }); + + test('stream respects priority: ethernet over mobile', () async { + final completer = Completer(); + final subscription = Parse().connectivityStream.listen((result) { + if (!completer.isCompleted) { + completer.complete(result); + } + }); + + mockPlatform.setConnectivity( + [ConnectivityResult.ethernet, ConnectivityResult.mobile]); + + final result = await completer.future; + expect(result, ParseConnectivityResult.ethernet); + + await subscription.cancel(); + }); + }); +} diff --git a/packages/flutter/test/parse_connectivity_mapping_test.dart b/packages/flutter/test/parse_connectivity_mapping_test.dart deleted file mode 100644 index cbaf5571..00000000 --- a/packages/flutter/test/parse_connectivity_mapping_test.dart +++ /dev/null @@ -1,82 +0,0 @@ -import 'package:connectivity_plus/connectivity_plus.dart'; -import 'package:flutter_test/flutter_test.dart'; -import 'package:parse_server_sdk_flutter/parse_server_sdk_flutter.dart'; - -void main() { - TestWidgetsFlutterBinding.ensureInitialized(); - - group('Connectivity mapping logic', () { - test('mapping logic follows priority: wifi > ethernet > mobile > none', () { - // This documents the if-else chain priority in checkConnectivity() - // and connectivityStream mapping logic - - // Simulating the actual mapping logic from parse_server_sdk_flutter.dart - ParseConnectivityResult mapResult(List list) { - if (list.contains(ConnectivityResult.wifi)) { - return ParseConnectivityResult.wifi; - } else if (list.contains(ConnectivityResult.ethernet)) { - return ParseConnectivityResult.ethernet; - } else if (list.contains(ConnectivityResult.mobile)) { - return ParseConnectivityResult.mobile; - } else { - return ParseConnectivityResult.none; - } - } - - // Test single connection types - expect( - mapResult([ConnectivityResult.wifi]), - ParseConnectivityResult.wifi, - ); - expect( - mapResult([ConnectivityResult.ethernet]), - ParseConnectivityResult.ethernet, - ); - expect( - mapResult([ConnectivityResult.mobile]), - ParseConnectivityResult.mobile, - ); - expect( - mapResult([ConnectivityResult.none]), - ParseConnectivityResult.none, - ); - - // Test priority when multiple connections exist - expect( - mapResult([ConnectivityResult.wifi, ConnectivityResult.ethernet]), - ParseConnectivityResult.wifi, - ); - expect( - mapResult([ConnectivityResult.wifi, ConnectivityResult.mobile]), - ParseConnectivityResult.wifi, - ); - expect( - mapResult([ConnectivityResult.ethernet, ConnectivityResult.mobile]), - ParseConnectivityResult.ethernet, - ); - - // Test that ethernet takes priority over mobile (critical for issue #1042) - expect( - mapResult([ConnectivityResult.mobile, ConnectivityResult.ethernet]), - ParseConnectivityResult.ethernet, - ); - - // Test fallback behavior for unsupported types - expect( - mapResult([ConnectivityResult.bluetooth]), - ParseConnectivityResult.none, - ); - expect(mapResult([ConnectivityResult.vpn]), ParseConnectivityResult.none); - expect( - mapResult([ConnectivityResult.other]), - ParseConnectivityResult.none, - ); - - // Test mixed with unsupported types - expect( - mapResult([ConnectivityResult.ethernet, ConnectivityResult.vpn]), - ParseConnectivityResult.ethernet, - ); - }); - }); -} From f57af7b80dc18579f5ec6d60e0dffa59e8ab9e90 Mon Sep 17 00:00:00 2001 From: Kirk Morrow <9563562+kirkmorrow@users.noreply.github.com> Date: Wed, 3 Dec 2025 10:33:41 -0600 Subject: [PATCH 8/9] Run dart format to cleanup --- .../flutter/lib/parse_server_sdk_flutter.dart | 3 +- ...arse_connectivity_implementation_test.dart | 32 ++++++++++++------- 2 files changed, 22 insertions(+), 13 deletions(-) diff --git a/packages/flutter/lib/parse_server_sdk_flutter.dart b/packages/flutter/lib/parse_server_sdk_flutter.dart index f1cd4db2..4a8dd7c1 100644 --- a/packages/flutter/lib/parse_server_sdk_flutter.dart +++ b/packages/flutter/lib/parse_server_sdk_flutter.dart @@ -121,7 +121,8 @@ class Parse extends sdk.Parse /// Priority: wifi > ethernet > mobile > none /// This ensures ethernet is treated as an online connection type. sdk.ParseConnectivityResult _mapConnectivity( - List results) { + List results, + ) { if (results.contains(ConnectivityResult.wifi)) { return sdk.ParseConnectivityResult.wifi; } else if (results.contains(ConnectivityResult.ethernet)) { diff --git a/packages/flutter/test/parse_connectivity_implementation_test.dart b/packages/flutter/test/parse_connectivity_implementation_test.dart index fbab6122..666daf89 100644 --- a/packages/flutter/test/parse_connectivity_implementation_test.dart +++ b/packages/flutter/test/parse_connectivity_implementation_test.dart @@ -56,14 +56,16 @@ void main() { expect(result, ParseConnectivityResult.wifi); }); - test('ethernet connection returns ParseConnectivityResult.ethernet', - () async { - mockPlatform.setConnectivity([ConnectivityResult.ethernet]); + test( + 'ethernet connection returns ParseConnectivityResult.ethernet', + () async { + mockPlatform.setConnectivity([ConnectivityResult.ethernet]); - final result = await Parse().checkConnectivity(); + final result = await Parse().checkConnectivity(); - expect(result, ParseConnectivityResult.ethernet); - }); + expect(result, ParseConnectivityResult.ethernet); + }, + ); test('mobile connection returns ParseConnectivityResult.mobile', () async { mockPlatform.setConnectivity([ConnectivityResult.mobile]); @@ -82,8 +84,10 @@ void main() { }); test('wifi takes priority over ethernet', () async { - mockPlatform - .setConnectivity([ConnectivityResult.wifi, ConnectivityResult.ethernet]); + mockPlatform.setConnectivity([ + ConnectivityResult.wifi, + ConnectivityResult.ethernet, + ]); final result = await Parse().checkConnectivity(); @@ -91,8 +95,10 @@ void main() { }); test('ethernet takes priority over mobile (issue #1042 fix)', () async { - mockPlatform.setConnectivity( - [ConnectivityResult.ethernet, ConnectivityResult.mobile]); + mockPlatform.setConnectivity([ + ConnectivityResult.ethernet, + ConnectivityResult.mobile, + ]); final result = await Parse().checkConnectivity(); @@ -192,8 +198,10 @@ void main() { } }); - mockPlatform.setConnectivity( - [ConnectivityResult.ethernet, ConnectivityResult.mobile]); + mockPlatform.setConnectivity([ + ConnectivityResult.ethernet, + ConnectivityResult.mobile, + ]); final result = await completer.future; expect(result, ParseConnectivityResult.ethernet); From e8fe2d3af0fcf9893c6369d372ccd2dd0883cf1a Mon Sep 17 00:00:00 2001 From: Kirk Morrow <9563562+kirkmorrow@users.noreply.github.com> Date: Wed, 3 Dec 2025 13:40:57 -0600 Subject: [PATCH 9/9] Remove unnecessary import --- .../flutter/test/parse_connectivity_implementation_test.dart | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/flutter/test/parse_connectivity_implementation_test.dart b/packages/flutter/test/parse_connectivity_implementation_test.dart index 666daf89..cc6ab7b8 100644 --- a/packages/flutter/test/parse_connectivity_implementation_test.dart +++ b/packages/flutter/test/parse_connectivity_implementation_test.dart @@ -1,6 +1,5 @@ import 'dart:async'; -import 'package:connectivity_plus/connectivity_plus.dart'; import 'package:connectivity_plus_platform_interface/connectivity_plus_platform_interface.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:parse_server_sdk_flutter/parse_server_sdk_flutter.dart';