`ux/notifications/events` and `ux/window/events` only had macOS stream handlers, so on Android/iOS the unconditional Dart subscription threw MissingPluginException at startup (EventChannel reports activation failures straight to FlutterError.onError, bypassing the `onError:` callback). - Gate each Dart event-channel subscription to platforms that register a native handler (`defaultTargetPlatform`), silencing iOS. - `WindowPlugin`: report app foreground/background as host focus via `ProcessLifecycleOwner` ON_START/ON_STOP, so a backgrounded-but-alive process reports `focused = false`. - `NotificationsPlugin`: local notifications (show/cancel by thread/all), POST_NOTIFICATIONS request on 13+, and tap routing back over the event channel — a tap that cold-starts the process is buffered until Dart subscribes. - Regression tests for the subscription gate plus contract tests for the method/event payloads.
64 lines
1.9 KiB
Dart
64 lines
1.9 KiB
Dart
import 'package:flutter/foundation.dart';
|
|
import 'package:flutter/services.dart';
|
|
import 'package:flutter_test/flutter_test.dart';
|
|
import 'package:ux/ux.dart';
|
|
|
|
void main() {
|
|
final messenger =
|
|
TestWidgetsFlutterBinding.ensureInitialized().defaultBinaryMessenger;
|
|
const channel = MethodChannel('ux/window/events');
|
|
|
|
final listenCalls = <String>[];
|
|
|
|
setUp(() {
|
|
listenCalls.clear();
|
|
messenger.setMockMethodCallHandler(channel, (call) async {
|
|
listenCalls.add(call.method);
|
|
return null;
|
|
});
|
|
});
|
|
|
|
tearDown(() {
|
|
messenger.setMockMethodCallHandler(channel, null);
|
|
debugDefaultTargetPlatformOverride = null;
|
|
});
|
|
|
|
Future<void> sendEvent(Object? event) => messenger.handlePlatformMessage(
|
|
'ux/window/events',
|
|
const StandardMethodCodec().encodeSuccessEnvelope(event),
|
|
(_) {},
|
|
);
|
|
|
|
// Regression: iOS has no native handler, so activating the broadcast
|
|
// stream throws MissingPluginException straight to FlutterError.onError.
|
|
test('iOS does not activate the events channel', () async {
|
|
debugDefaultTargetPlatformOverride = TargetPlatform.iOS;
|
|
final w = MethodChannelXWindow();
|
|
await pumpEventQueue();
|
|
expect(listenCalls, isEmpty);
|
|
expect(w.focused.value, isTrue);
|
|
});
|
|
|
|
test('Android activates the events channel', () async {
|
|
debugDefaultTargetPlatformOverride = TargetPlatform.android;
|
|
MethodChannelXWindow();
|
|
await pumpEventQueue();
|
|
expect(listenCalls, contains('listen'));
|
|
});
|
|
|
|
test('a focus event flips focused', () async {
|
|
debugDefaultTargetPlatformOverride = TargetPlatform.android;
|
|
final w = MethodChannelXWindow();
|
|
await pumpEventQueue();
|
|
expect(w.focused.value, isTrue);
|
|
|
|
await sendEvent({'type': 'focus', 'focused': false});
|
|
await pumpEventQueue();
|
|
expect(w.focused.value, isFalse);
|
|
|
|
await sendEvent({'type': 'focus', 'focused': true});
|
|
await pumpEventQueue();
|
|
expect(w.focused.value, isTrue);
|
|
});
|
|
}
|