fix(settings): guard Atmos diagnostics stop
This commit is contained in:
@@ -29,6 +29,7 @@ class _AtmosDiagnosticsScreenState extends State<AtmosDiagnosticsScreen> {
|
||||
Timer? _poll;
|
||||
Map<Object?, Object?> _status = const {};
|
||||
String? _activeMode;
|
||||
bool _stopping = false;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
@@ -40,7 +41,7 @@ class _AtmosDiagnosticsScreenState extends State<AtmosDiagnosticsScreen> {
|
||||
@override
|
||||
void dispose() {
|
||||
_poll?.cancel();
|
||||
_channel.invokeMethod('stop').ignore();
|
||||
if (!_stopping) _channel.invokeMethod('stop').ignore();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@@ -70,9 +71,18 @@ class _AtmosDiagnosticsScreenState extends State<AtmosDiagnosticsScreen> {
|
||||
}
|
||||
|
||||
Future<void> _stop() async {
|
||||
await _channel.invokeMethod('stop');
|
||||
setState(() => _activeMode = null);
|
||||
await _refreshStatus();
|
||||
if (_stopping) return;
|
||||
_stopping = true;
|
||||
try {
|
||||
await _channel.invokeMethod('stop');
|
||||
if (!mounted) return;
|
||||
setState(() => _activeMode = null);
|
||||
await _refreshStatus();
|
||||
} on PlatformException catch (e) {
|
||||
if (mounted) showErrorSnackBar(context, e.message ?? e.code);
|
||||
} finally {
|
||||
_stopping = false;
|
||||
}
|
||||
}
|
||||
|
||||
Widget _testTile({required String mode, required IconData icon, required String title, required String subtitle}) {
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:plezy/i18n/strings.g.dart';
|
||||
import 'package:plezy/screens/settings/atmos_diagnostics_screen.dart';
|
||||
import 'package:plezy/services/settings_service.dart';
|
||||
import 'package:plezy/theme/mono_theme.dart';
|
||||
|
||||
import '../../test_helpers/prefs.dart';
|
||||
|
||||
void main() {
|
||||
TestWidgetsFlutterBinding.ensureInitialized();
|
||||
|
||||
const channel = MethodChannel('plezy/atmos_probe');
|
||||
final messenger = TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger;
|
||||
|
||||
setUp(() async {
|
||||
resetSharedPreferencesForTest();
|
||||
SettingsService.resetForTesting();
|
||||
await SettingsService.getInstance();
|
||||
LocaleSettings.setLocaleSync(AppLocale.en);
|
||||
});
|
||||
|
||||
tearDown(() {
|
||||
messenger.setMockMethodCallHandler(channel, null);
|
||||
});
|
||||
|
||||
Future<void> pumpScreen(WidgetTester tester) async {
|
||||
await tester.pumpWidget(MaterialApp(theme: monoTheme(dark: true), home: const AtmosDiagnosticsScreen()));
|
||||
await tester.pump();
|
||||
await tester.ensureVisible(find.text(t.settings.atmosTestStop));
|
||||
}
|
||||
|
||||
testWidgets('unmounting during stop does not set state or stop twice', (tester) async {
|
||||
final stopCompleter = Completer<void>();
|
||||
var stopCalls = 0;
|
||||
messenger.setMockMethodCallHandler(channel, (call) async {
|
||||
if (call.method == 'stop') {
|
||||
stopCalls++;
|
||||
await stopCompleter.future;
|
||||
}
|
||||
return call.method == 'getStatus' ? <Object?, Object?>{} : null;
|
||||
});
|
||||
|
||||
await pumpScreen(tester);
|
||||
await tester.tap(find.text(t.settings.atmosTestStop));
|
||||
await tester.pump();
|
||||
expect(stopCalls, 1);
|
||||
|
||||
await tester.pumpWidget(const MaterialApp(home: SizedBox()));
|
||||
expect(stopCalls, 1);
|
||||
|
||||
stopCompleter.complete();
|
||||
await tester.pump();
|
||||
|
||||
expect(tester.takeException(), isNull);
|
||||
expect(stopCalls, 1);
|
||||
});
|
||||
|
||||
testWidgets('native stop failure is shown without escaping', (tester) async {
|
||||
var stopCalls = 0;
|
||||
messenger.setMockMethodCallHandler(channel, (call) async {
|
||||
if (call.method == 'stop') {
|
||||
stopCalls++;
|
||||
throw PlatformException(code: 'stop_failed', message: 'Native stop failed');
|
||||
}
|
||||
return call.method == 'getStatus' ? <Object?, Object?>{} : null;
|
||||
});
|
||||
|
||||
await pumpScreen(tester);
|
||||
await tester.tap(find.text(t.settings.atmosTestStop));
|
||||
await tester.pump();
|
||||
|
||||
expect(stopCalls, 1);
|
||||
expect(find.text('Native stop failed'), findsOneWidget);
|
||||
expect(tester.takeException(), isNull);
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user